# Arquitectura ACE2

## Objetivo

Construir ACE desde cero con una base de datos mas pequena, consultable y preparada para crecer. La prioridad es espacio de servidor; la segunda prioridad es velocidad de consulta.

## Decision principal

ACE2 no debe guardar cada columna textual del CSV repetida por linea historica. El importador debe leer el archivo, normalizar entidades y dejar la menor cantidad posible de texto repetido.

## Capas

### 1. Ingesta transitoria

El archivo se registra en `ace2_upload_batches`. Durante la carga se procesa en lotes. Si se necesita staging, debe ser temporal y limpiarse al terminar.

Politica:

- No conservar `raw_row` por cada fila como dato permanente.
- Conservar el archivo original comprimido fuera de la base solo si hace falta auditoria.
- Guardar errores de importacion en `ace2_ingest_errors`.

### 2. Dimensiones

Tablas pequenas y deduplicadas:

- `ace2_statuses`
- `ace2_buyers`
- `ace2_suppliers`
- `ace2_product_taxonomy`
- `ace2_descriptions`
- `ace2_market_categories`
- `ace2_market_products`

### 3. Hechos

`ace2_purchase_order_lines` es la tabla central. Guarda IDs, fechas, montos y campos analiticos baratos:

- `period_year`
- `period_month`
- `buyer_id`
- `supplier_id`
- `status_id`
- `supplier_status_id`
- `taxonomy_id`
- `buyer_description_id`
- `supplier_description_id`
- `line_total_net`
- `include_in_market`

Esto evita joins innecesarios para filtros frecuentes y permite excluir canceladas sin recalcular reglas en cada consulta.

### 4. Clasificacion

La clasificacion vive fuera de la linea historica:

- `ace2_description_classifications`
- `ace2_classification_rules`
- `ace2_market_categories`
- `ace2_market_products`

La clave de reimportacion desde ACE antiguo debe ser:

- `source_field`
- `description_hash`
- `normalized_description`

Asi no dependemos de IDs antiguos.

### 5. Resumenes

Las pantallas ejecutivas deben leer desde resumenes:

- `ace2_metric_market_period_summary`
- `ace2_metric_supplier_share`
- `ace2_metric_buyer_share`

Los resumenes se recalculan por categoria y periodo, no en cada carga de pantalla.

## Campos del CSV

### Permanentes

- OC: codigo, link, nombre, tipo, procedencia, trato directo, compra agil, licitacion, convenio.
- Estados: estado OC, estado proveedor, codigos y grupo analitico.
- Fechas: creacion, envio, aceptacion, cancelacion.
- Comprador: codigo, RUT, unidad, organismo, sector, actividad, ciudad, region, pais.
- Proveedor: codigo, RUT/sucursal, nombre, actividad, comuna, region, pais.
- Producto: codigo categoria, categoria, codigo ONU, producto generico, rubros.
- Item: id item, cantidad, unidad, moneda, precio neto, total linea neto.
- Descripciones: comprador y proveedor, ambas preservadas.

### Transitorios o derivados

- Fila raw completa.
- Textos repetidos que ya viven en dimensiones.
- Valores vacios o `NA`.
- Campos derivables desde OC o linea.

## Estados excluidos

Una fila puede cargarse aunque sea cancelada, pero debe quedar con `include_in_market = 0`.

Regla inicial:

- Si `estado_proveedor` contiene `cancelada`, excluir.
- Si `estado` contiene `cancelada`, excluir.
- Lo demas queda incluido salvo regla posterior.

## Particion por ano

No se recomienda crear tablas manuales por ano como `mercado_2024`, `mercado_2025`. La opcion correcta, si el motor lo permite, es particion nativa por `period_year`.

Si el hosting no soporta particiones, basta con:

- indices por `period_year, period_month`
- resumenes por periodo
- limpieza de staging
- dimensiones deduplicadas

La reduccion real de espacio viene de no repetir texto, no de dividir tablas por ano.
