import { CONSEGNA_CONSTRAINTS } from "./constraints"; import { buildResult, normalizePositiveInt, normalizeString, validateDate, validateEnum, validateMaxLength, validatePositiveInt, validateRequired, type FieldErrors, type ValidationResult, } from "./primitives"; export type StatoConsegna = (typeof CONSEGNA_CONSTRAINTS.stato.allowedValues)[number]; export interface ConsegnaInput { dataRitiro: string | null; dataConsegna: string | null; stato: StatoConsegna; chiaveConsegna: string; clienteId: number; } function normalizeOptionalDate(value: unknown): string | null { const str = normalizeString(value); return str || null; } function todayAtMidnight(): Date { const today = new Date(); today.setHours(0, 0, 0, 0); return today; } function validateDateNotRetroactive( errors: FieldErrors, field: string, value: string, label: string ): void { if (!value || errors[field]) return; const parsed = new Date(`${value}T00:00:00`); if (parsed < todayAtMidnight()) { errors[field] = `${label} non può essere anteriore alla data odierna`; } } function validateOptionalDateField( errors: FieldErrors, field: string, value: string | null, label: string ): void { if (!value) return; validateDate(errors, field, value, label); validateDateNotRetroactive(errors, field, value, label); } function validateAtLeastOneDate( errors: FieldErrors, dataRitiro: string | null, dataConsegna: string | null ): void { if (!dataRitiro && !dataConsegna) { errors._form = "Inserire almeno una data di ritiro o di consegna"; } } export function normalizeConsegnaInput(raw: Record): ConsegnaInput { return { dataRitiro: normalizeOptionalDate(raw.dataRitiro), dataConsegna: normalizeOptionalDate(raw.dataConsegna), stato: normalizeString(raw.stato || "in deposito") as StatoConsegna, chiaveConsegna: normalizeString(raw.chiaveConsegna).toUpperCase(), clienteId: normalizePositiveInt(raw.clienteId), }; } function validateConsegnaFields( raw: Record, data: ConsegnaInput, errors: FieldErrors, options: { requireAll: boolean } ): void { if (options.requireAll || "dataRitiro" in raw) { validateOptionalDateField(errors, "dataRitiro", data.dataRitiro, "Data ritiro"); } if (options.requireAll || "dataConsegna" in raw) { validateOptionalDateField(errors, "dataConsegna", data.dataConsegna, "Data consegna"); } if (options.requireAll) { validateAtLeastOneDate(errors, data.dataRitiro, data.dataConsegna); } else if ("dataRitiro" in raw && "dataConsegna" in raw) { validateAtLeastOneDate(errors, data.dataRitiro, data.dataConsegna); } if (options.requireAll || "stato" in raw) { validateRequired(errors, "stato", data.stato, "Stato obbligatorio"); validateEnum( errors, "stato", data.stato, CONSEGNA_CONSTRAINTS.stato.allowedValues, "Stato" ); } if (options.requireAll || "chiaveConsegna" in raw) { validateRequired( errors, "chiaveConsegna", data.chiaveConsegna, "Chiave consegna obbligatoria" ); validateMaxLength( errors, "chiaveConsegna", data.chiaveConsegna, CONSEGNA_CONSTRAINTS.chiaveConsegna.maxLength, "Chiave consegna" ); } if (options.requireAll || "clienteId" in raw) { validatePositiveInt(errors, "clienteId", data.clienteId, "Cliente", options.requireAll); } } export function validateConsegnaCreate( raw: Record ): ValidationResult { const data = normalizeConsegnaInput(raw); const errors: FieldErrors = {}; validateConsegnaFields(raw, data, errors, { requireAll: true }); return buildResult(data, errors); } export function validateConsegnaUpdate( raw: Record ): ValidationResult> { const errors: FieldErrors = {}; const data: Partial = {}; if ("dataRitiro" in raw) { data.dataRitiro = normalizeOptionalDate(raw.dataRitiro); validateOptionalDateField(errors, "dataRitiro", data.dataRitiro, "Data ritiro"); } if ("dataConsegna" in raw) { data.dataConsegna = normalizeOptionalDate(raw.dataConsegna); validateOptionalDateField(errors, "dataConsegna", data.dataConsegna, "Data consegna"); } if ("dataRitiro" in raw && "dataConsegna" in raw) { validateAtLeastOneDate(errors, data.dataRitiro ?? null, data.dataConsegna ?? null); } if ("stato" in raw) { data.stato = normalizeString(raw.stato) as StatoConsegna; validateRequired(errors, "stato", data.stato, "Stato obbligatorio"); validateEnum( errors, "stato", data.stato, CONSEGNA_CONSTRAINTS.stato.allowedValues, "Stato" ); } if ("chiaveConsegna" in raw) { data.chiaveConsegna = normalizeString(raw.chiaveConsegna).toUpperCase(); validateRequired( errors, "chiaveConsegna", data.chiaveConsegna, "Chiave consegna obbligatoria" ); validateMaxLength( errors, "chiaveConsegna", data.chiaveConsegna, CONSEGNA_CONSTRAINTS.chiaveConsegna.maxLength, "Chiave consegna" ); } if ("clienteId" in raw) { data.clienteId = normalizePositiveInt(raw.clienteId); validatePositiveInt(errors, "clienteId", data.clienteId, "Cliente"); } if (Object.keys(data).length === 0) { errors._form = "Nessun campo da aggiornare"; } return buildResult(data, errors); }