F3.2: resolver Hallazgos contra Acta explícita
This commit is contained in:
@@ -36,9 +36,15 @@ export class FieldFindingsService {
|
|||||||
private readonly findings: InspectionFindingsService,
|
private readonly findings: InspectionFindingsService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async options(visitId: string, assetId: string, principal: AuthPrincipal) {
|
async options(
|
||||||
|
visitId: string,
|
||||||
|
assetId: string,
|
||||||
|
actId: string | undefined,
|
||||||
|
principal: AuthPrincipal,
|
||||||
|
) {
|
||||||
const gate = await this.requireGate(visitId, assetId, principal);
|
const gate = await this.requireGate(visitId, assetId, principal);
|
||||||
const act = await this.requireDraftAct(visitId);
|
const act = await this.requireDraftAct(visitId, actId);
|
||||||
|
const assetIncludedInAct = await this.actContainsAsset(act.id, assetId);
|
||||||
const [catalog, findings] = await Promise.all([
|
const [catalog, findings] = await Promise.all([
|
||||||
this.catalog.listApplicableForAsset(assetId, {}),
|
this.catalog.listApplicableForAsset(assetId, {}),
|
||||||
this.findings.listForAct(act.id),
|
this.findings.listForAct(act.id),
|
||||||
@@ -48,21 +54,30 @@ export class FieldFindingsService {
|
|||||||
context: gate.context,
|
context: gate.context,
|
||||||
act,
|
act,
|
||||||
capture: gate.capture,
|
capture: gate.capture,
|
||||||
|
assetIncludedInAct,
|
||||||
catalog,
|
catalog,
|
||||||
findings: findings.data.filter((finding) => finding.assetId === assetId),
|
findings: findings.data.filter((finding) => finding.assetId === assetId),
|
||||||
canAddAnother: true,
|
canAddAnother: assetIncludedInAct,
|
||||||
|
actSelectionMode: actId ? 'EXPLICIT' : 'LEGACY_SINGLE_DRAFT',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async list(visitId: string, assetId: string, principal: AuthPrincipal) {
|
async list(
|
||||||
|
visitId: string,
|
||||||
|
assetId: string,
|
||||||
|
actId: string | undefined,
|
||||||
|
principal: AuthPrincipal,
|
||||||
|
) {
|
||||||
const gate = await this.requireGate(visitId, assetId, principal);
|
const gate = await this.requireGate(visitId, assetId, principal);
|
||||||
const act = await this.requireDraftAct(visitId);
|
const act = await this.requireDraftAct(visitId, actId);
|
||||||
const findings = await this.findings.listForAct(act.id);
|
const findings = await this.findings.listForAct(act.id);
|
||||||
return {
|
return {
|
||||||
context: gate.context,
|
context: gate.context,
|
||||||
act,
|
act,
|
||||||
capture: gate.capture,
|
capture: gate.capture,
|
||||||
|
assetIncludedInAct: await this.actContainsAsset(act.id, assetId),
|
||||||
data: findings.data.filter((finding) => finding.assetId === assetId),
|
data: findings.data.filter((finding) => finding.assetId === assetId),
|
||||||
|
actSelectionMode: actId ? 'EXPLICIT' : 'LEGACY_SINGLE_DRAFT',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +89,15 @@ export class FieldFindingsService {
|
|||||||
request: RequestWithContext,
|
request: RequestWithContext,
|
||||||
) {
|
) {
|
||||||
const gate = await this.requireGate(visitId, assetId, principal);
|
const gate = await this.requireGate(visitId, assetId, principal);
|
||||||
const act = await this.requireDraftAct(visitId);
|
const act = await this.requireDraftAct(visitId, dto.actId);
|
||||||
|
if (!await this.actContainsAsset(act.id, assetId)) {
|
||||||
|
throw new ConflictException({
|
||||||
|
code: 'FIELD_FINDING_ASSET_NOT_IN_ACT',
|
||||||
|
message: 'Agregá este Inventario al Acta seleccionada antes de registrar el Hallazgo',
|
||||||
|
actId: act.id,
|
||||||
|
assetId,
|
||||||
|
});
|
||||||
|
}
|
||||||
const payload: CreateInspectionFindingDto = {
|
const payload: CreateInspectionFindingDto = {
|
||||||
assetId,
|
assetId,
|
||||||
catalogItemId: dto.catalogItemId ?? null,
|
catalogItemId: dto.catalogItemId ?? null,
|
||||||
@@ -91,6 +114,7 @@ export class FieldFindingsService {
|
|||||||
capture: gate.capture,
|
capture: gate.capture,
|
||||||
finding,
|
finding,
|
||||||
canAddAnother: true,
|
canAddAnother: true,
|
||||||
|
actSelectionMode: dto.actId ? 'EXPLICIT' : 'LEGACY_SINGLE_DRAFT',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,7 +292,40 @@ export class FieldFindingsService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private async requireDraftAct(visitId: string): Promise<DraftActRow> {
|
private async actContainsAsset(actId: string, assetId: string): Promise<boolean> {
|
||||||
|
const [row] = await this.dataSource.query(`
|
||||||
|
SELECT EXISTS (
|
||||||
|
SELECT 1 FROM inspection_act_assets
|
||||||
|
WHERE act_id=$1::uuid AND asset_id=$2::uuid AND included=true
|
||||||
|
) AS included
|
||||||
|
`, [actId, assetId]) as Array<{ included: boolean }>;
|
||||||
|
return Boolean(row?.included);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async requireDraftAct(visitId: string, requestedActId?: string): Promise<DraftActRow> {
|
||||||
|
if (requestedActId) {
|
||||||
|
const [act] = await this.dataSource.query(`
|
||||||
|
SELECT id,code,status
|
||||||
|
FROM inspection_acts
|
||||||
|
WHERE id=$1::uuid AND visit_id=$2::uuid
|
||||||
|
`, [requestedActId, visitId]) as DraftActRow[];
|
||||||
|
if (!act) {
|
||||||
|
throw new NotFoundException({
|
||||||
|
code: 'FIELD_FINDING_ACT_NOT_FOUND',
|
||||||
|
message: 'El Acta seleccionada no pertenece a esta inspección',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (act.status !== 'DRAFT') {
|
||||||
|
throw new ConflictException({
|
||||||
|
code: 'FIELD_FINDING_ACT_NOT_DRAFT',
|
||||||
|
message: 'Los Hallazgos nuevos sólo pueden agregarse a un Acta en borrador',
|
||||||
|
actId: act.id,
|
||||||
|
actStatus: act.status,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return act;
|
||||||
|
}
|
||||||
|
|
||||||
const rows = await this.dataSource.query(`
|
const rows = await this.dataSource.query(`
|
||||||
SELECT id, code, status
|
SELECT id, code, status
|
||||||
FROM inspection_acts
|
FROM inspection_acts
|
||||||
|
|||||||
Reference in New Issue
Block a user