F4: include technical function in merged inventory dossier

This commit is contained in:
2026-09-07 21:17:33 -03:00
parent 88179eb67c
commit a836c7535a
@@ -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<string, any>;
@@ -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<Record<string, unknown>> {
@@ -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<LooseRecord>(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,