fix(f6.1): resolve verification operator from temporal area relation
This commit is contained in:
@@ -66,9 +66,6 @@ interface LockedFindingRow {
|
||||
assetId: string;
|
||||
assetCode: string;
|
||||
assetName: string;
|
||||
companyId: string | null;
|
||||
companyCode: string | null;
|
||||
companyName: string | null;
|
||||
areaId: string | null;
|
||||
areaCode: string | null;
|
||||
areaName: string | null;
|
||||
@@ -76,6 +73,12 @@ interface LockedFindingRow {
|
||||
status: string;
|
||||
}
|
||||
|
||||
interface PlannedOperatorRow {
|
||||
companyId: string;
|
||||
companyCode: string;
|
||||
companyName: string;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class InspectionVerificationsService {
|
||||
constructor(
|
||||
@@ -142,8 +145,19 @@ export class InspectionVerificationsService {
|
||||
INNER JOIN inspection_visits source_visit ON source_visit.id = act.visit_id
|
||||
INNER JOIN assets asset ON asset.id = finding.asset_id
|
||||
INNER JOIN asset_types asset_type ON asset_type.id = asset.asset_type_id
|
||||
LEFT JOIN assets company ON company.id = asset.operator_company_id
|
||||
LEFT JOIN assets area ON area.id = asset.operational_area_id
|
||||
LEFT JOIN LATERAL (
|
||||
SELECT operator_company.id,operator_company.code,operator_company.name
|
||||
FROM area_company_relations relation
|
||||
INNER JOIN assets operator_company ON operator_company.id=relation.company_id
|
||||
WHERE relation.area_id=asset.operational_area_id
|
||||
AND relation.relation_role='OPERATOR'
|
||||
AND relation.valid_from <= CURRENT_TIMESTAMP
|
||||
AND (relation.valid_until IS NULL OR relation.valid_until > CURRENT_TIMESTAMP)
|
||||
AND operator_company.information_status<>'INACTIVE'
|
||||
ORDER BY relation.valid_from DESC,relation.created_at DESC,relation.id DESC
|
||||
LIMIT 1
|
||||
) company ON true
|
||||
${activeVisitJoin}
|
||||
`;
|
||||
|
||||
@@ -495,15 +509,11 @@ export class InspectionVerificationsService {
|
||||
finding.next_control_on AS "nextControlOn",
|
||||
asset.code AS "assetCode",
|
||||
asset.name AS "assetName",
|
||||
company.id AS "companyId",
|
||||
company.code AS "companyCode",
|
||||
company.name AS "companyName",
|
||||
area.id AS "areaId",
|
||||
area.code AS "areaCode",
|
||||
area.name AS "areaName"
|
||||
FROM inspection_findings finding
|
||||
INNER JOIN assets asset ON asset.id = finding.asset_id
|
||||
LEFT JOIN assets company ON company.id = asset.operator_company_id
|
||||
LEFT JOIN assets area ON area.id = asset.operational_area_id
|
||||
WHERE finding.id = ANY($1::uuid[])
|
||||
FOR UPDATE OF finding
|
||||
@@ -519,25 +529,51 @@ export class InspectionVerificationsService {
|
||||
message: `${invalid.code} necesita estar abierto y tener una fecha de control para planificar su verificación`,
|
||||
});
|
||||
}
|
||||
const missingContext = rows.find((row) => !row.companyId || !row.areaId);
|
||||
if (missingContext) {
|
||||
const missingArea = rows.find((row) => !row.areaId);
|
||||
if (missingArea) {
|
||||
throw new BadRequestException({
|
||||
code: 'VERIFICATION_CONTEXT_REQUIRED',
|
||||
message: `${missingContext.code} necesita empresa y área operativa antes de planificar la visita`,
|
||||
message: `${missingArea.code} necesita un Área física antes de planificar la visita`,
|
||||
});
|
||||
}
|
||||
const companyId = rows[0]?.companyId;
|
||||
const areaId = rows[0]?.areaId;
|
||||
if (!companyId || !areaId) {
|
||||
throw new BadRequestException({ code: 'VERIFICATION_CONTEXT_REQUIRED', message: 'Los hallazgos necesitan empresa y área operativa' });
|
||||
if (!areaId) {
|
||||
throw new BadRequestException({ code: 'VERIFICATION_CONTEXT_REQUIRED', message: 'Los hallazgos necesitan un Área física' });
|
||||
}
|
||||
if (rows.some((row) => row.companyId !== companyId || row.areaId !== areaId)) {
|
||||
if (rows.some((row) => row.areaId !== areaId)) {
|
||||
throw new BadRequestException({
|
||||
code: 'VERIFICATION_CONTEXT_MIXED',
|
||||
message: 'Seleccioná hallazgos de una misma empresa y área para crear una visita de verificación',
|
||||
message: 'Seleccioná hallazgos de una misma Área para crear una visita de verificación',
|
||||
});
|
||||
}
|
||||
|
||||
// A verification visit is a new operational act. Its operator is therefore
|
||||
// the Company valid for the Area at the planned visit date, never the
|
||||
// historical compatibility snapshot stored on the Inventory.
|
||||
const [operator] = await manager.query(`
|
||||
SELECT
|
||||
company.id AS "companyId",
|
||||
company.code AS "companyCode",
|
||||
company.name AS "companyName"
|
||||
FROM area_company_relations relation
|
||||
INNER JOIN assets company ON company.id=relation.company_id
|
||||
WHERE relation.area_id=$1::uuid
|
||||
AND relation.relation_role='OPERATOR'
|
||||
AND relation.valid_from <= $2::timestamptz
|
||||
AND (relation.valid_until IS NULL OR relation.valid_until > $2::timestamptz)
|
||||
AND company.information_status<>'INACTIVE'
|
||||
ORDER BY relation.valid_from DESC,relation.created_at DESC,relation.id DESC
|
||||
LIMIT 1
|
||||
FOR SHARE OF relation
|
||||
`, [areaId, plannedStartAt]) as PlannedOperatorRow[];
|
||||
if (!operator) {
|
||||
throw new ConflictException({
|
||||
code: 'VERIFICATION_OPERATOR_NOT_ACTIVE',
|
||||
message: 'El Área no tiene una Operadora vigente para la fecha prevista de la verificación',
|
||||
});
|
||||
}
|
||||
const companyId = operator.companyId;
|
||||
|
||||
const activeLinks = await manager.query(`
|
||||
SELECT verification_link.finding_id AS "findingId", visit.code
|
||||
FROM inspection_finding_verification_visits verification_link
|
||||
@@ -552,7 +588,7 @@ export class InspectionVerificationsService {
|
||||
});
|
||||
}
|
||||
|
||||
const companyName = rows[0]?.companyName ?? 'Empresa';
|
||||
const companyName = operator.companyName;
|
||||
const areaName = rows[0]?.areaName ?? 'Área';
|
||||
const code = await nextInspectionVisitCode(manager, plannedStartAt);
|
||||
const findingCodes = rows.map((row) => row.code).join(', ');
|
||||
@@ -637,6 +673,7 @@ export class InspectionVerificationsService {
|
||||
areaId,
|
||||
findingIds,
|
||||
assetIds,
|
||||
operatorSource: 'area_company_relations',
|
||||
},
|
||||
}, manager);
|
||||
|
||||
@@ -647,7 +684,7 @@ export class InspectionVerificationsService {
|
||||
status: visit.status,
|
||||
plannedStartAt: visit.plannedStartAt,
|
||||
},
|
||||
company: { id: companyId, code: rows[0]?.companyCode ?? '', name: companyName },
|
||||
company: { id: companyId, code: operator.companyCode, name: companyName },
|
||||
area: { id: areaId, code: rows[0]?.areaCode ?? '', name: areaName },
|
||||
findingCount: findingIds.length,
|
||||
assetCount: assetIds.length,
|
||||
|
||||
Reference in New Issue
Block a user