diff --git a/api-v3/src/act-administration/field-briefing.service.ts b/api-v3/src/act-administration/field-briefing.service.ts index 5b7f917..03df89c 100644 --- a/api-v3/src/act-administration/field-briefing.service.ts +++ b/api-v3/src/act-administration/field-briefing.service.ts @@ -36,6 +36,20 @@ export interface FieldBriefingAct { findings: FieldBriefingFinding[]; } +function toIsoDate(value: unknown): string { + const parsed = value instanceof Date + ? value + : value == null + ? new Date() + : new Date(String(value)); + + if (Number.isNaN(parsed.getTime())) { + throw new Error('La fecha planificada de la inspección no es válida'); + } + + return parsed.toISOString().slice(0, 10); +} + @Injectable() export class FieldBriefingService { constructor(private readonly dataSource: DataSource) {} @@ -67,7 +81,9 @@ export class FieldBriefingService { }); } - const plannedOn = String(visit.plannedStartAt ?? new Date().toISOString()).slice(0, 10); + // PostgreSQL/pg entrega los timestamptz como Date. String(date).slice(0, 10) + // produce textos como "Thu Sep 17", que PostgreSQL rechaza al castear a date. + const plannedOn = toIsoDate(visit.plannedStartAt); const rows = (await this.dataSource.query(` WITH prior_acts AS ( diff --git a/api-v3/test/unit/field-briefing-runtime.test.ts b/api-v3/test/unit/field-briefing-runtime.test.ts new file mode 100644 index 0000000..2665d1d --- /dev/null +++ b/api-v3/test/unit/field-briefing-runtime.test.ts @@ -0,0 +1,50 @@ +import assert from 'node:assert/strict'; +import test from 'node:test'; +import type { DataSource } from 'typeorm'; +import { FieldBriefingService } from '../../src/act-administration/field-briefing.service'; + +test('field briefing convierte el timestamptz de pg a YYYY-MM-DD antes del cast SQL', async () => { + const calls: Array<{ sql: string; params: unknown[] }> = []; + let queryNumber = 0; + + const dataSource = { + query: async (sql: string, params: unknown[]) => { + calls.push({ sql, params }); + queryNumber += 1; + + if (queryNumber === 1) { + return [{ + id: '11111111-1111-4111-8111-111111111111', + code: 'INSP-00002-17-09-26', + status: 'DRAFT', + plannedStartAt: new Date('2026-09-17T23:42:00.000Z'), + areaId: '22222222-2222-4222-8222-222222222222', + companyId: '33333333-3333-4333-8333-333333333333', + areaCode: 'PRES-AREA-TEST', + areaName: 'Barrancas', + companyCode: 'PRES-ORG-TEST', + companyName: 'Petróleos Sudamericanos Energy S.A.', + }]; + } + + return []; + }, + } as unknown as DataSource; + + const result = await new FieldBriefingService(dataSource).forVisit( + '11111111-1111-4111-8111-111111111111', + ); + + assert.equal(calls.length, 2); + assert.equal(calls[1]?.params[3], '2026-09-17'); + assert.equal(result.plannedOn, '2026-09-17'); + assert.deepEqual(result.summary, { + acts: 0, + findings: 0, + inventoryItems: 0, + responseOverdue: 0, + commitmentOverdue: 0, + verificationPending: 0, + }); + assert.deepEqual(result.acts, []); +});