metis-desk/modules/assets/src/api/domain/asset-relationship.aggregate.ts

80 lines
2.1 KiB
TypeScript
Raw Normal View History

2026-10-08 14:43:34 +00:00
import type { UniqueID } from "@repo/rdx-ddd";
import { AggregateRoot } from "@repo/rdx-ddd";
2026-10-04 19:04:14 +00:00
import { Maybe, Result } from "@repo/rdx-utils";
import { z } from "zod/v4";
import { AssetCatalogError } from "./asset-definition";
import type { AssetRelationshipValues } from "./value-objects/asset-relationship-values";
type RelationshipProps = Readonly<{
companyId: UniqueID;
values: AssetRelationshipValues;
createdBy: UniqueID;
createdAt: string;
endedBy: Maybe<UniqueID>;
endedAt: Maybe<string>;
}>;
export class AssetRelationship extends AggregateRoot<RelationshipProps> {
private constructor(props: RelationshipProps, id?: UniqueID) {
super(Object.freeze({ ...props }), id);
}
static create(
companyId: UniqueID,
values: AssetRelationshipValues,
actor: UniqueID,
now: string
): Result<AssetRelationship, AssetCatalogError> {
if (!z.iso.datetime().safeParse(now).success) {
return Result.fail(new AssetCatalogError("INVALID_REQUEST"));
}
return Result.ok(
new AssetRelationship({
companyId,
values,
createdBy: actor,
createdAt: now,
endedBy: Maybe.none(),
endedAt: Maybe.none(),
})
);
}
static rehydrate(props: RelationshipProps, id: UniqueID) {
return new AssetRelationship(props, id);
}
get companyId() {
return this.props.companyId;
}
get values() {
return this.props.values;
}
get createdBy() {
return this.props.createdBy;
}
get createdAt() {
return this.props.createdAt;
}
get endedBy() {
return this.props.endedBy;
}
get endedAt() {
return this.props.endedAt;
}
get active() {
return !this.endedAt.getOrUndefined();
}
end(actor: UniqueID, now: string): Result<AssetRelationship, AssetCatalogError> {
if (!this.active) {
return Result.ok(this);
}
if (!z.iso.datetime().safeParse(now).success || now < this.createdAt) {
return Result.fail(new AssetCatalogError("INVALID_REQUEST"));
}
return Result.ok(
new AssetRelationship(
{ ...this.props, endedBy: Maybe.some(actor), endedAt: Maybe.some(now) },
this.id
)
);
}
}