F4: include technical function in merged inventory dossier
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { AssetsService } from './assets.service';
|
import { AssetsService } from './assets.service';
|
||||||
|
import { InventoryFunctionService } from './inventory-function.service';
|
||||||
import { InventoryMergeService } from './inventory-merge.service';
|
import { InventoryMergeService } from './inventory-merge.service';
|
||||||
|
|
||||||
type LooseRecord = Record<string, any>;
|
type LooseRecord = Record<string, any>;
|
||||||
@@ -29,6 +30,7 @@ export class MergedInventoryDossierService {
|
|||||||
constructor(
|
constructor(
|
||||||
private readonly assets: AssetsService,
|
private readonly assets: AssetsService,
|
||||||
private readonly merges: InventoryMergeService,
|
private readonly merges: InventoryMergeService,
|
||||||
|
private readonly functions: InventoryFunctionService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async dossier(requestedAssetId: string): Promise<Record<string, unknown>> {
|
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 dossiers = await Promise.all(inventoryIds.map(async (assetId) => {
|
||||||
const dossier = await this.assets.dossier(assetId) as LooseRecord;
|
const dossier = await this.assets.dossier(assetId) as LooseRecord;
|
||||||
const identity = dossier.asset 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 => ({
|
const enrich = (entry: LooseRecord, identity: LooseRecord): LooseRecord => ({
|
||||||
@@ -75,6 +78,15 @@ export class MergedInventoryDossierService {
|
|||||||
const media = sortDesc(collect('media'), ['capturedAt', 'createdAt']);
|
const media = sortDesc(collect('media'), ['capturedAt', 'createdAt']);
|
||||||
const versions = sortDesc(collect('versions'), ['occurredAt']);
|
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 }) =>
|
const timelineSource: LooseRecord[] = dossiers.flatMap(({ identity, dossier }) =>
|
||||||
((dossier.timeline ?? []) as LooseRecord[]).map((event): LooseRecord => ({
|
((dossier.timeline ?? []) as LooseRecord[]).map((event): LooseRecord => ({
|
||||||
...event,
|
...event,
|
||||||
@@ -91,6 +103,25 @@ export class MergedInventoryDossierService {
|
|||||||
);
|
);
|
||||||
const timeline: LooseRecord[] = dedupeById<LooseRecord>(timelineSource);
|
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) {
|
for (const alias of aliases) {
|
||||||
timeline.push({
|
timeline.push({
|
||||||
id: `merge:${String(alias.id)}:${String(alias.mergedAt)}`,
|
id: `merge:${String(alias.id)}:${String(alias.mergedAt)}`,
|
||||||
@@ -121,6 +152,7 @@ export class MergedInventoryDossierService {
|
|||||||
code: canonical.code,
|
code: canonical.code,
|
||||||
name: canonical.name,
|
name: canonical.name,
|
||||||
commonName: dossiers.find((item) => item.assetId === canonical.id)?.identity?.commonName ?? null,
|
commonName: dossiers.find((item) => item.assetId === canonical.id)?.identity?.commonName ?? null,
|
||||||
|
currentFunction,
|
||||||
},
|
},
|
||||||
requestedAsset: {
|
requestedAsset: {
|
||||||
id: requested.id,
|
id: requested.id,
|
||||||
@@ -146,7 +178,10 @@ export class MergedInventoryDossierService {
|
|||||||
documents: documents.length + media.filter((item) => item.kind === 'DOCUMENT').length,
|
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,
|
photos: evidence.filter((item) => item.kind === 'PHOTO').length + media.filter((item) => item.kind === 'PHOTO').length,
|
||||||
reports: reports.length + inspectionReports.length,
|
reports: reports.length + inspectionReports.length,
|
||||||
|
functionChanges: functionHistory.length,
|
||||||
},
|
},
|
||||||
|
currentFunction,
|
||||||
|
functionHistory,
|
||||||
visits,
|
visits,
|
||||||
acts,
|
acts,
|
||||||
findings,
|
findings,
|
||||||
|
|||||||
Reference in New Issue
Block a user