metis-desk/modules/assets/src/api/application/workstation-input.mapper.ts

88 lines
2.6 KiB
TypeScript
Raw Normal View History

2026-10-04 19:04:14 +00:00
import { Result } from "@repo/rdx-utils";
import { AssetCatalogError } from "../domain/asset-definition";
import { canAssignAsset } from "../domain/asset-state";
2026-10-09 08:38:19 +00:00
import { WorkstationValues } from "../domain/value-objects/workstation-values.vo";
2026-10-04 19:04:14 +00:00
import type { Workstation } from "../domain/workstation.aggregate";
import type { WorkstationInput } from "../domain/workstation-values";
import type { InventoryContext } from "./asset.repository";
2026-10-10 10:01:58 +00:00
2026-10-04 19:04:14 +00:00
export function mapWorkstationInput(
input: WorkstationInput,
context: InventoryContext,
previous?: Workstation
) {
const mapped = WorkstationValues.create(input);
2026-10-10 10:01:58 +00:00
2026-10-04 19:04:14 +00:00
if (!mapped.isSuccess) {
return mapped;
}
const values = mapped.data.toPrimitive();
2026-10-10 10:01:58 +00:00
2026-10-04 19:04:14 +00:00
if (values.siteId && !context.sites.some((id) => id.toPrimitive() === values.siteId)) {
return Result.fail(new AssetCatalogError("SITE_NOT_FOUND"));
}
const person = context.people.find((item) => item.id.toPrimitive() === values.personId);
2026-10-10 10:01:58 +00:00
2026-10-04 19:04:14 +00:00
if (
values.personId &&
(!person || (!person.active && previous?.values.toPrimitive().personId !== values.personId))
) {
return Result.fail(new AssetCatalogError("PERSON_UNAVAILABLE"));
}
2026-10-05 07:53:29 +00:00
for (const id of [...values.assetIds, ...values.sharedAssetIds]) {
const error = memberError(id, values, context, previous);
2026-10-10 10:01:58 +00:00
if (error) {
return Result.fail(new AssetCatalogError(error));
2026-10-04 19:04:14 +00:00
}
}
2026-10-10 10:01:58 +00:00
2026-10-04 19:04:14 +00:00
return mapped;
}
function memberError(
id: string,
values: WorkstationInput,
context: InventoryContext,
previous: Workstation | undefined
) {
const asset = context.assets.find((item) => item.id.toPrimitive() === id);
if (!asset) {
return "ASSET_NOT_FOUND";
}
if (!values.active) {
return undefined;
}
const exclusive = values.assetIds.includes(id);
const previousMembers = exclusive ? previous?.values.assetIds : previous?.values.sharedAssetIds;
const retained =
previous?.values.active && previousMembers?.some((item) => item.toPrimitive() === id);
if (
!(
retained ||
canAssignAsset(asset.values.technicalStatus, exclusive ? "exclusive" : "shared", false, false)
)
) {
return "ASSET_NOT_OPERATIONAL";
}
const others = context.workstations.filter(
(item) => item.values.active && item.id.toPrimitive() !== previous?.id.toPrimitive()
);
const exclusiveElsewhere = others.some((item) =>
item.values.assetIds.some((assetId) => assetId.toPrimitive() === id)
);
const sharedElsewhere = others.some((item) =>
item.values.sharedAssetIds.some((assetId) => assetId.toPrimitive() === id)
);
if (exclusiveElsewhere || (exclusive && sharedElsewhere)) {
return "ASSET_IN_WORKSTATION";
}
return undefined;
}