feat: Add catalog import and progress tracking features

1. Catalog Import (Generadores de Precios):
   - ImportacionCatalogo model for tracking import history
   - POST /api/importar - Process Excel/CSV files
   - GET /api/importar - List import history
   - ImportadorCatalogo component with:
     - Template download for materials, labor, equipment
     - Auto unit mapping (PZA→PIEZA, M2→METRO_CUADRADO, etc.)
     - FSR auto-calculation for labor imports
     - Import history view

2. Progress Tracking (Control de Avance por Partida):
   - AvancePartida model with quantity, percentage, amount tracking
   - CRUD API endpoints for avances
   - GET /api/avances/resumen - Summary per presupuesto
   - ControlAvancePartidas component with:
     - Global progress summary cards
     - Per-partida progress table with bars
     - Register progress dialog
     - Auto-calculation of accumulated values

3. Bug fixes:
   - ClientDate component to fix hydration mismatch errors
   - Date formatting now consistent between server and client

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Mexus
2026-02-05 09:00:36 +00:00
parent 56e39af3ff
commit e964e8f0b5
13 changed files with 1930 additions and 9 deletions

View File

@@ -146,6 +146,9 @@ model User {
pushSubscriptions PushSubscription[]
notificaciones Notificacion[]
actividades ActividadLog[]
avancesRegistrados AvancePartida[] @relation("AvancesRegistrados")
avancesAprobados AvancePartida[] @relation("AvancesAprobados")
importaciones ImportacionCatalogo[]
@@index([empresaId])
@@index([email])
@@ -174,6 +177,7 @@ model Empresa {
equiposMaquinaria EquipoMaquinaria[]
apus AnalisisPrecioUnitario[]
configuracionAPU ConfiguracionAPU?
importaciones ImportacionCatalogo[]
}
model Cliente {
@@ -360,11 +364,40 @@ model PartidaPresupuesto {
// Relations
gastos Gasto[]
avances AvancePartida[]
@@index([presupuestoId])
@@index([apuId])
}
model AvancePartida {
id String @id @default(cuid())
fecha DateTime @default(now())
cantidadEjecutada Float // Cantidad ejecutada en este registro
cantidadAcumulada Float // Cantidad acumulada hasta este registro
porcentajeAvance Float // Porcentaje de avance (0-100)
montoEjecutado Float // Monto correspondiente a este avance
montoAcumulado Float // Monto acumulado hasta este registro
notas String?
fotos String[]
partidaId String
partida PartidaPresupuesto @relation(fields: [partidaId], references: [id], onDelete: Cascade)
registradoPorId String
registradoPor User @relation("AvancesRegistrados", fields: [registradoPorId], references: [id])
aprobadoPorId String?
aprobadoPor User? @relation("AvancesAprobados", fields: [aprobadoPorId], references: [id])
aprobado Boolean @default(false)
fechaAprobacion DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([partidaId])
@@index([registradoPorId])
@@index([fecha])
}
model Gasto {
id String @id @default(cuid())
concepto String
@@ -1074,3 +1107,41 @@ model ConfiguracionAPU {
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
// ============== IMPORTACIÓN DE CATÁLOGOS ==============
enum TipoImportacion {
MATERIALES
MANO_OBRA
EQUIPOS
}
enum EstadoImportacion {
PENDIENTE
PROCESANDO
COMPLETADA
ERROR
}
model ImportacionCatalogo {
id String @id @default(cuid())
tipo TipoImportacion
nombreArchivo String
estado EstadoImportacion @default(PENDIENTE)
registrosTotal Int @default(0)
registrosCreados Int @default(0)
registrosActualizados Int @default(0)
registrosError Int @default(0)
errores String? // JSON con detalles de errores
fuenteDatos String? // BIMSA, Proveedor, Manual, etc.
empresaId String
empresa Empresa @relation(fields: [empresaId], references: [id])
creadoPorId String
creadoPor User @relation(fields: [creadoPorId], references: [id])
createdAt DateTime @default(now())
completadoAt DateTime?
@@index([empresaId])
@@index([tipo])
@@index([estado])
}