111 lines
4.2 KiB
TypeScript
111 lines
4.2 KiB
TypeScript
import { prisma } from './prisma.js'
|
|
import type { UnidadCotizable } from './cotizacion.service.js'
|
|
|
|
/**
|
|
* Espejo local del inventario de unidades (tabla `Unidad`, sembrada por
|
|
* scripts/seed-unidades-locales.js). Es la única fuente de lectura del
|
|
* inventario: misma forma de DTO que consumen controllers y fronts.
|
|
*
|
|
* La tabla `Unidad` no guarda la fecha de entrega: se completa desde la captura
|
|
* de obra/escrituración (`CapturaDepartamento`), que es la que llenan los
|
|
* departamentos. Sin ese dato el cotizador asume el plazo por defecto del
|
|
* desarrollo (ver DESARROLLOS en cotizacion.service.ts).
|
|
*/
|
|
|
|
/**
|
|
* Campos de `CapturaDepartamento` que dan la fecha de entrega de la vivienda,
|
|
* en orden de prioridad:
|
|
* 1. `entrega_programada_fecha` — Fecha Programada Entrega Vivienda (ESCRITURACION)
|
|
* 2. `habitabilidad` — fecha de habitabilidad (OBRA), la de DIAGONAL
|
|
* 3. `inicio_obra_fecha` — último recurso (ESCRITURACION)
|
|
*/
|
|
export const CAMPOS_FECHA_ENTREGA = [
|
|
'entrega_programada_fecha',
|
|
'habitabilidad',
|
|
'inicio_obra_fecha',
|
|
] as const
|
|
|
|
/** Normaliza 'YYYY-MM-DD' (o ISO completo); null si el valor no es una fecha usable */
|
|
function fechaIso(valor: string | null | undefined): string | null {
|
|
if (typeof valor !== 'string') return null
|
|
const fecha = valor.trim().slice(0, 10)
|
|
return /^\d{4}-\d{2}-\d{2}$/.test(fecha) ? fecha : null
|
|
}
|
|
|
|
/** Fecha de entrega (ISO) por código de unidad, según la captura de los departamentos */
|
|
async function fechasEntregaPorUnidad(codigos?: string[]): Promise<Map<string, string>> {
|
|
const filas = await prisma.capturaDepartamento.findMany({
|
|
where: {
|
|
campo: { in: [...CAMPOS_FECHA_ENTREGA] },
|
|
...(codigos ? { unidadCodigo: { in: codigos } } : {}),
|
|
},
|
|
select: { unidadCodigo: true, campo: true, valor: true },
|
|
})
|
|
const porUnidad = new Map<string, string>()
|
|
for (const campo of CAMPOS_FECHA_ENTREGA) {
|
|
for (const fila of filas) {
|
|
if (fila.campo !== campo || porUnidad.has(fila.unidadCodigo)) continue
|
|
const fecha = fechaIso(fila.valor)
|
|
if (fecha !== null) porUnidad.set(fila.unidadCodigo, fecha)
|
|
}
|
|
}
|
|
return porUnidad
|
|
}
|
|
|
|
/** Fila de la tabla Unidad tal como la devuelve Prisma (estructural) */
|
|
export interface FilaUnidad {
|
|
codigo: string
|
|
desarrollo: string
|
|
modelo: string
|
|
supConstruccion: number
|
|
supExcedente: number
|
|
supEstacionamiento: number
|
|
precioLista: number
|
|
precioAcabados: number
|
|
status: string
|
|
etapa: string
|
|
}
|
|
|
|
/** Fila local → DTO `Unidad` (UnidadCotizable) que consumen controllers y fronts */
|
|
export function unidadLocalADto(u: FilaUnidad, fechaEntrega: string | null = null): UnidadCotizable {
|
|
return {
|
|
codigo: u.codigo,
|
|
modelo: u.modelo,
|
|
fechaEntrega,
|
|
supEstacionamiento: u.supEstacionamiento,
|
|
supConstruccion: u.supConstruccion,
|
|
supExcedente: u.supExcedente,
|
|
precioSinAcabados: u.precioLista,
|
|
precioConAcabados: u.precioAcabados,
|
|
status: u.status,
|
|
desarrollo: u.desarrollo,
|
|
mesesParaFirma: null,
|
|
etapa: u.etapa === '' ? null : u.etapa,
|
|
}
|
|
}
|
|
|
|
/** Unidades del espejo local; filtros equivalentes a los del controller */
|
|
export async function getUnidadesLocal(
|
|
filtro: { desarrollo?: string | undefined; soloDisponibles?: boolean | undefined } = {},
|
|
): Promise<UnidadCotizable[]> {
|
|
const rows = await prisma.unidad.findMany({ orderBy: { codigo: 'asc' } })
|
|
const fechas = await fechasEntregaPorUnidad()
|
|
let lista = rows.map((u) => unidadLocalADto(u, fechas.get(u.codigo) ?? null))
|
|
if (filtro.soloDisponibles === true) {
|
|
lista = lista.filter((u) => u.status.trim().toUpperCase() === 'DISPONIBLE')
|
|
}
|
|
if (filtro.desarrollo !== undefined && filtro.desarrollo !== '') {
|
|
const desarrollo = filtro.desarrollo.toUpperCase()
|
|
lista = lista.filter((u) => (u.desarrollo || 'DIAGONAL').toUpperCase() === desarrollo)
|
|
}
|
|
return lista
|
|
}
|
|
|
|
/** Una unidad local por código; null si no existe en el espejo */
|
|
export async function getUnidadLocal(codigo: string): Promise<UnidadCotizable | null> {
|
|
const row = await prisma.unidad.findUnique({ where: { codigo } })
|
|
if (row === null) return null
|
|
const fechas = await fechasEntregaPorUnidad([codigo])
|
|
return unidadLocalADto(row, fechas.get(codigo) ?? null)
|
|
}
|