feat(actas): render complete self-contained PDF
DH V2 CI / API · typecheck, tests, build (push) Successful in 43s
Production dependency audit / API · production dependencies (push) Successful in 15s
Production dependency audit / WEB · production dependencies (push) Successful in 14s
DH V2 CI / WEB · typecheck, build (push) Successful in 1m36s
DH V2 CI / Docker / migrations / production images (push) Successful in 2m45s
DH V2 CI / Promote verified main to deploy (push) Successful in 6s
Android CI / RC / Android · lint, tests, debug APK, release compile (push) Successful in 4m59s
DH V2 CI / API · typecheck, tests, build (push) Successful in 43s
Production dependency audit / API · production dependencies (push) Successful in 15s
Production dependency audit / WEB · production dependencies (push) Successful in 14s
DH V2 CI / WEB · typecheck, build (push) Successful in 1m36s
DH V2 CI / Docker / migrations / production images (push) Successful in 2m45s
DH V2 CI / Promote verified main to deploy (push) Successful in 6s
Android CI / RC / Android · lint, tests, debug APK, release compile (push) Successful in 4m59s
This commit is contained in:
@@ -4,7 +4,7 @@ import { isAbsolute, parse, resolve } from 'node:path';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { Injectable, InternalServerErrorException, NotFoundException } from '@nestjs/common';
|
||||
import { DataSource } from 'typeorm';
|
||||
import { buildInspectionActPdf, type ActPdfImage } from './inspection-act-pdf-builder';
|
||||
import { buildInspectionActPdf, type ActPdfContext, type ActPdfImage } from './inspection-act-pdf-builder';
|
||||
import { renderableInspectionImage } from './inspection-document-images';
|
||||
|
||||
@Injectable()
|
||||
@@ -96,7 +96,7 @@ export class InspectionActPdfService {
|
||||
SELECT stored_name AS "storedName",original_name AS "originalName",
|
||||
size_bytes AS "sizeBytes",sha256
|
||||
FROM inspection_act_consolidated_pdf_revisions
|
||||
WHERE act_id=$1 AND template_version=2
|
||||
WHERE act_id=$1 AND template_version=3
|
||||
`, [actId]) as Array<{ storedName: string; originalName: string; sizeBytes: number; sha256: string }>;
|
||||
if (existing) {
|
||||
const buffer = await this.verifiedImage(this.root, existing);
|
||||
@@ -126,12 +126,12 @@ export class InspectionActPdfService {
|
||||
});
|
||||
await this.dataSource.query(`
|
||||
INSERT INTO inspection_act_consolidated_pdf_revisions(act_id,template_version,stored_name,original_name,size_bytes,sha256)
|
||||
VALUES($1,2,$2,$3,$4,$5) ON CONFLICT (act_id,template_version) DO NOTHING
|
||||
VALUES($1,3,$2,$3,$4,$5) ON CONFLICT (act_id,template_version) DO NOTHING
|
||||
`, [actId, storedName, originalName, built.buffer.length, built.sha256]);
|
||||
const [saved] = await this.dataSource.query(`
|
||||
SELECT stored_name AS "storedName",original_name AS "originalName",
|
||||
size_bytes AS "sizeBytes",sha256
|
||||
FROM inspection_act_consolidated_pdf_revisions WHERE act_id=$1 AND template_version=2
|
||||
FROM inspection_act_consolidated_pdf_revisions WHERE act_id=$1 AND template_version=3
|
||||
`, [actId]) as Array<{ storedName: string; originalName: string; sizeBytes: number; sha256: string }>;
|
||||
if (!saved) throw this.storageError();
|
||||
return {
|
||||
@@ -141,7 +141,7 @@ export class InspectionActPdfService {
|
||||
}
|
||||
|
||||
async consolidatedRevisionContent(actId: string, version: number): Promise<{ buffer: Buffer; originalName: string; mimeType: string }> {
|
||||
if (![1, 2].includes(version)) throw new NotFoundException('Versión documental inexistente');
|
||||
if (![1, 2, 3].includes(version)) throw new NotFoundException('Versión documental inexistente');
|
||||
const [row] = await this.dataSource.query(`
|
||||
SELECT stored_name AS "storedName",original_name AS "originalName",
|
||||
size_bytes AS "sizeBytes",sha256
|
||||
@@ -152,17 +152,38 @@ export class InspectionActPdfService {
|
||||
return { buffer: await this.verifiedImage(this.root, row), originalName: row.originalName, mimeType: 'application/pdf' };
|
||||
}
|
||||
|
||||
private async actContext(actId: string): Promise<{ companyName: string | null; areaName: string | null; scopeName: string | null }> {
|
||||
private async actContext(actId: string): Promise<ActPdfContext> {
|
||||
const [row] = await this.dataSource.query(`
|
||||
SELECT company.name AS "companyName",area.name AS "areaName",scope.name AS "scopeName"
|
||||
SELECT company.name AS "companyName",department.name AS "departmentName",area.name AS "areaName",
|
||||
scope.name AS "scopeName",scope.code AS "scopeCode",scope_type.name AS "scopeTypeName",scope_type.code AS "scopeTypeCode",
|
||||
COALESCE(CASE WHEN lower(scope_type.code)='yacimiento' THEN scope.name END,yacimiento_from_findings.name) AS "yacimientoName",
|
||||
COALESCE(CASE WHEN lower(scope_type.code)='yacimiento' THEN scope.code END,yacimiento_from_findings.code) AS "yacimientoCode",
|
||||
btrim(concat_ws(' ',lead.first_name,lead.last_name)) AS "leadInspectorName"
|
||||
FROM inspection_acts act
|
||||
JOIN inspection_visits visit ON visit.id=act.visit_id
|
||||
LEFT JOIN assets company ON company.id=visit.operator_company_id
|
||||
LEFT JOIN assets area ON area.id=visit.operational_area_id
|
||||
LEFT JOIN assets department ON department.id=area.parent_id
|
||||
LEFT JOIN assets scope ON scope.id=visit.scope_asset_id
|
||||
LEFT JOIN asset_types scope_type ON scope_type.id=scope.asset_type_id
|
||||
LEFT JOIN users lead ON lead.id=visit.lead_inspector_user_id
|
||||
LEFT JOIN LATERAL (
|
||||
WITH RECURSIVE ancestors AS (
|
||||
SELECT asset.id,asset.parent_id,asset.code,asset.name,asset.asset_type_id
|
||||
FROM inspection_findings finding JOIN assets asset ON asset.id=finding.asset_id
|
||||
WHERE finding.act_id=act.id AND finding.status<>'VOIDED'
|
||||
UNION
|
||||
SELECT parent.id,parent.parent_id,parent.code,parent.name,parent.asset_type_id
|
||||
FROM ancestors JOIN assets parent ON parent.id=ancestors.parent_id
|
||||
)
|
||||
SELECT string_agg(DISTINCT ancestors.name, ', ' ORDER BY ancestors.name) AS name,
|
||||
string_agg(DISTINCT ancestors.code, ', ' ORDER BY ancestors.code) AS code
|
||||
FROM ancestors JOIN asset_types ancestor_type ON ancestor_type.id=ancestors.asset_type_id
|
||||
WHERE lower(ancestor_type.code)='yacimiento'
|
||||
) yacimiento_from_findings ON true
|
||||
WHERE act.id=$1
|
||||
`, [actId]) as Array<{ companyName: string | null; areaName: string | null; scopeName: string | null }>;
|
||||
return row ?? { companyName: null, areaName: null, scopeName: null };
|
||||
`, [actId]) as ActPdfContext[];
|
||||
return row ?? {};
|
||||
}
|
||||
|
||||
private async verifiedImage(root: string, row: { storedName: string; sha256: string; sizeBytes: number }): Promise<Buffer> {
|
||||
|
||||
Reference in New Issue
Block a user