fix(f6.9): include every field photo and preserve document revisions
Android CI / RC / Android · lint, tests, debug APK, release compile (push) Successful in 3m8s
DH V2 CI / WEB · typecheck, build (push) Successful in 19s
DH V2 CI / API · typecheck, tests, build (push) Successful in 32s
Production dependency audit / API · production dependencies (push) Successful in 8s
Production dependency audit / WEB · production dependencies (push) Successful in 9s
DH V2 CI / Docker / scripts contract (push) Successful in 59s

This commit is contained in:
DH V2
2026-09-15 19:18:31 -03:00
parent 669c0d2656
commit 60ba37c287
9 changed files with 169 additions and 18 deletions
@@ -122,7 +122,7 @@ function imageDimensions(buffer: Buffer): { width: number; height: number } {
return { width: 800, height: 500 };
}
function drawing(relationship: number, image: Buffer, name: string, maxWidth = 4572000, maxHeight = 2743200, right = false): string {
function drawing(relationship: number, image: Buffer, name: string, maxWidth = 4572000, maxHeight = 2057400, right = false): string {
const dimensions = imageDimensions(image);
const scale = Math.min(maxWidth / dimensions.width, maxHeight / dimensions.height);
const cx = Math.round(dimensions.width * scale);
@@ -136,6 +136,7 @@ function documentXml(input: ReportWordInput, logo: Buffer): string {
const photos = input.photos ?? [];
const authors = snapshot.signatures.filter((item) => text(item.signerType, '') === 'INSPECTOR').map((item) => text(item.signerName)).join(', ');
const legalBasis = [...new Set(snapshot.findings.map((item) => text(item.legalBasis, '')).filter(Boolean))];
const quantity = `${snapshot.findings.length} ${snapshot.findings.length === 1 ? 'hallazgo' : 'hallazgos'}`;
const entries: string[] = [
paragraph('MINISTERIO DE ENERGÍA Y AMBIENTE'),
paragraph('DIRECCIÓN DE HIDROCARBUROS'),
@@ -155,10 +156,11 @@ function documentXml(input: ReportWordInput, logo: Buffer): string {
paragraph('MARCO LEGAL', 'Heading1'),
...(legalBasis.length ? legalBasis.map((basis) => paragraph(basis)) : [paragraph('No se consignó normativa específica en los hallazgos del Acta fuente.')]),
paragraph('DESCRIPCIÓN Y ANÁLISIS TÉCNICO', 'Heading1'),
paragraph(input.reportDescription?.trim() || `Según el Acta ${text(snapshot.act.code)}, se documentaron ${snapshot.findings.length} hallazgo(s) durante la inspección. Se detallan las observaciones y evidencias consignadas a continuación.`),
paragraph(input.reportDescription?.trim() || `Según el Acta ${text(snapshot.act.code)}, se documentaron ${quantity} durante la inspección. Se detallan las observaciones y evidencias consignadas a continuación.`),
paragraph('FOTOS Y HALLAZGOS', 'Heading1'),
];
if (!snapshot.findings.length) entries.push(paragraph('El Acta fuente no registra hallazgos.'));
const shownPhotos = new Set<number>();
for (const finding of snapshot.findings) {
entries.push(paragraph(`${text(finding.code)} ${text(finding.title)}`, 'Heading2'));
entries.push(labelValue('Instalación', text(snapshot.inventories.find((item) => text(item.id) === text(finding.assetId))?.name)));
@@ -168,13 +170,24 @@ function documentXml(input: ReportWordInput, logo: Buffer): string {
for (let index = 0; index < photos.length; index++) {
const photo = photos[index]!;
if (photo.findingId !== text(finding.id) && photo.assetId !== text(finding.assetId)) continue;
shownPhotos.add(index);
entries.push(drawing(index + 3, photo.buffer, photo.title || text(finding.title)));
entries.push(paragraph(`Fotografía vinculada · SHA-256 ${photo.sha256}`));
}
}
const otherPhotos = photos.map((photo, index) => ({ photo, index }))
.filter(({ photo, index }) => photo.assetId && !shownPhotos.has(index));
if (otherPhotos.length) {
entries.push(paragraph('OTRAS INSTALACIONES INSPECCIONADAS', 'Heading1'));
for (const { photo, index } of otherPhotos) {
entries.push(labelValue('Instalación', text(photo.title)));
entries.push(drawing(index + 3, photo.buffer, photo.title || 'Fotografía de instalación'));
entries.push(paragraph(`Fotografía de inventario · SHA-256 ${photo.sha256}`));
}
}
entries.push(
paragraph('CONCLUSIONES', 'Heading1'),
paragraph(input.executiveSummary?.trim() || `La inspección registró ${snapshot.findings.length} hallazgo(s). Su seguimiento y la respuesta de la empresa se documentan en el Informe.`),
paragraph(input.executiveSummary?.trim() || `La inspección registró ${quantity}. Su seguimiento y la respuesta de la empresa se documentan en el Informe.`),
paragraph('ACTA FUENTE E INTEGRIDAD', 'Heading1'),
labelValue('Acta sellada', text(snapshot.source.actCode ?? snapshot.act.code)),
labelValue('SHA-256 del cierre del Acta', text(snapshot.source.actClosureSha256 ?? snapshot.sealedAct.finalSha256)),