2026-10-04 19:04:14 +00:00
|
|
|
import { UniqueID } from "@repo/rdx-ddd";
|
|
|
|
|
import { Maybe, Result } from "@repo/rdx-utils";
|
|
|
|
|
|
|
|
|
|
import type { RelationshipInputDTO } from "../../common/relationships";
|
|
|
|
|
import { AssetCatalogError } from "../domain/asset-definition";
|
|
|
|
|
import { AssetRelationship } from "../domain/asset-relationship.aggregate";
|
2026-10-09 08:38:19 +00:00
|
|
|
import { AssetRelationshipValues } from "../domain/value-objects/asset-relationship-values.vo";
|
2026-10-04 19:04:14 +00:00
|
|
|
|
|
|
|
|
import type { IAssetRepository, InventoryContext } from "./asset.repository";
|
|
|
|
|
|
|
|
|
|
export class AssetRelationshipUseCases {
|
|
|
|
|
constructor(private readonly repository: IAssetRepository) {}
|
|
|
|
|
save(companyId: string, input: RelationshipInputDTO, actorId: string) {
|
|
|
|
|
const company = UniqueID.create(companyId);
|
|
|
|
|
const actor = UniqueID.create(actorId);
|
|
|
|
|
if (!(company.isSuccess && actor.isSuccess)) {
|
|
|
|
|
return Promise.resolve(Result.fail(new AssetCatalogError("INVALID_REQUEST")));
|
|
|
|
|
}
|
|
|
|
|
return this.repository.saveRelationship(company.data, (context) => {
|
|
|
|
|
const mapped = mapRelationshipInput(input, company.data, context);
|
|
|
|
|
if (!mapped.isSuccess) {
|
|
|
|
|
return Result.fail(mapped.error);
|
|
|
|
|
}
|
|
|
|
|
const previous = context.relationships.find(
|
|
|
|
|
(item) => item.active && item.values.key() === mapped.data.key()
|
|
|
|
|
);
|
|
|
|
|
if (previous) {
|
|
|
|
|
return previous.values.notes === mapped.data.notes
|
|
|
|
|
? Result.ok(previous)
|
|
|
|
|
: Result.fail(new AssetCatalogError("RELATIONSHIP_EXISTS"));
|
|
|
|
|
}
|
|
|
|
|
return AssetRelationship.create(
|
|
|
|
|
company.data,
|
|
|
|
|
mapped.data,
|
|
|
|
|
actor.data,
|
|
|
|
|
new Date().toISOString()
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
}
|
2026-10-09 22:19:35 +00:00
|
|
|
remove(companyId: string, id: string) {
|
|
|
|
|
const company = UniqueID.create(companyId);
|
|
|
|
|
const identity = UniqueID.create(id);
|
|
|
|
|
if (!(company.isSuccess && identity.isSuccess)) {
|
|
|
|
|
return Promise.resolve(Result.fail(new AssetCatalogError("INVALID_REQUEST")));
|
|
|
|
|
}
|
|
|
|
|
return this.repository.removeRelationship(company.data, identity.data);
|
|
|
|
|
}
|
2026-10-04 19:04:14 +00:00
|
|
|
end(companyId: string, id: string, actorId: string) {
|
|
|
|
|
const company = UniqueID.create(companyId);
|
|
|
|
|
const identity = UniqueID.create(id);
|
|
|
|
|
const actor = UniqueID.create(actorId);
|
|
|
|
|
if (!(company.isSuccess && identity.isSuccess && actor.isSuccess)) {
|
|
|
|
|
return Promise.resolve(Result.fail(new AssetCatalogError("INVALID_REQUEST")));
|
|
|
|
|
}
|
|
|
|
|
return this.repository.saveRelationship(company.data, (context) => {
|
|
|
|
|
const item = context.relationships.find((entry) => entry.id.equals(identity.data));
|
|
|
|
|
return item
|
|
|
|
|
? item.end(actor.data, new Date().toISOString())
|
|
|
|
|
: Result.fail(new AssetCatalogError("RELATIONSHIP_NOT_FOUND"));
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
export function mapRelationshipInput(
|
|
|
|
|
input: RelationshipInputDTO,
|
|
|
|
|
company: UniqueID,
|
|
|
|
|
context: InventoryContext
|
|
|
|
|
) {
|
|
|
|
|
if (
|
|
|
|
|
![input.sourceId, input.targetId].every((id) =>
|
|
|
|
|
context.assets.some((asset) => asset.id.toPrimitive() === id)
|
|
|
|
|
)
|
|
|
|
|
) {
|
|
|
|
|
return Result.fail(new AssetCatalogError("ASSET_NOT_FOUND"));
|
|
|
|
|
}
|
|
|
|
|
const scope = Maybe.some(company);
|
|
|
|
|
const type = context.catalog
|
|
|
|
|
.visible(scope)
|
|
|
|
|
.find((item) => item.id.toPrimitive() === input.typeId);
|
|
|
|
|
if (!(type && type.values.data.kind === "relation" && context.catalog.active(type, scope))) {
|
|
|
|
|
return Result.fail(new AssetCatalogError("RELATION_TYPE_UNAVAILABLE"));
|
|
|
|
|
}
|
|
|
|
|
return AssetRelationshipValues.create({
|
|
|
|
|
...input,
|
|
|
|
|
name: type.values.data.name,
|
|
|
|
|
inverseName: type.values.data.inverseName,
|
|
|
|
|
symmetric: type.values.data.symmetric,
|
|
|
|
|
});
|
|
|
|
|
}
|