diff --git a/api-v3/src/asset-master/merged-inventory-dossier.service.ts b/api-v3/src/asset-master/merged-inventory-dossier.service.ts index 7a09038..7309767 100644 --- a/api-v3/src/asset-master/merged-inventory-dossier.service.ts +++ b/api-v3/src/asset-master/merged-inventory-dossier.service.ts @@ -1,5 +1,6 @@ import { Injectable } from '@nestjs/common'; import { AssetsService } from './assets.service'; +import { InventoryFunctionService } from './inventory-function.service'; import { InventoryMergeService } from './inventory-merge.service'; type LooseRecord = Record; @@ -29,6 +30,7 @@ export class MergedInventoryDossierService { constructor( private readonly assets: AssetsService, private readonly merges: InventoryMergeService, + private readonly functions: InventoryFunctionService, ) {} async dossier(requestedAssetId: string): Promise> { @@ -44,7 +46,8 @@ export class MergedInventoryDossierService { const dossiers = await Promise.all(inventoryIds.map(async (assetId) => { const dossier = await this.assets.dossier(assetId) as LooseRecord; const identity = dossier.asset as LooseRecord; - return { assetId, identity, dossier }; + const functionDossier = await this.functions.getForAsset(assetId).catch(() => null) as LooseRecord | null; + return { assetId, identity, dossier, functionDossier }; })); const enrich = (entry: LooseRecord, identity: LooseRecord): LooseRecord => ({ @@ -75,6 +78,15 @@ export class MergedInventoryDossierService { const media = sortDesc(collect('media'), ['capturedAt', 'createdAt']); const versions = sortDesc(collect('versions'), ['occurredAt']); + const functionHistory = sortDesc( + dossiers.flatMap(({ identity, functionDossier }) => + (((functionDossier?.history ?? []) as LooseRecord[]).map((entry) => enrich(entry, identity))), + ), + ['validFrom', 'createdAt'], + ); + const canonicalFunctionDossier = dossiers.find((item) => item.assetId === canonical.id)?.functionDossier ?? null; + const currentFunction = canonicalFunctionDossier?.currentFunction ?? null; + const timelineSource: LooseRecord[] = dossiers.flatMap(({ identity, dossier }) => ((dossier.timeline ?? []) as LooseRecord[]).map((event): LooseRecord => ({ ...event, @@ -91,6 +103,25 @@ export class MergedInventoryDossierService { ); const timeline: LooseRecord[] = dedupeById(timelineSource); + for (const assignment of functionHistory) { + timeline.push({ + id: `function:${String(assignment.id)}`, + kind: 'FUNCTION_CHANGED', + occurredAt: assignment.validFrom, + title: `Cambio de función · ${String(assignment.functionName)}`, + description: assignment.reason ?? null, + meta: { + functionId: assignment.functionId, + functionCode: assignment.functionCode, + functionName: assignment.functionName, + validFrom: assignment.validFrom, + validUntil: assignment.validUntil, + changedByUsername: assignment.changedByUsername, + historicalInventory: assignment.historicalInventory, + }, + }); + } + for (const alias of aliases) { timeline.push({ id: `merge:${String(alias.id)}:${String(alias.mergedAt)}`, @@ -121,6 +152,7 @@ export class MergedInventoryDossierService { code: canonical.code, name: canonical.name, commonName: dossiers.find((item) => item.assetId === canonical.id)?.identity?.commonName ?? null, + currentFunction, }, requestedAsset: { id: requested.id, @@ -146,7 +178,10 @@ export class MergedInventoryDossierService { documents: documents.length + media.filter((item) => item.kind === 'DOCUMENT').length, photos: evidence.filter((item) => item.kind === 'PHOTO').length + media.filter((item) => item.kind === 'PHOTO').length, reports: reports.length + inspectionReports.length, + functionChanges: functionHistory.length, }, + currentFunction, + functionHistory, visits, acts, findings,