import type { UniqueID } from "@repo/rdx-ddd"; import { AggregateRoot } from "@repo/rdx-ddd"; import { Result } from "@repo/rdx-utils"; import { z } from "zod/v4"; import { AssetCatalogError } from "./asset-definition"; import { WorkstationValues } from "./value-objects/workstation-values.vo"; import { WorkstationRevision } from "./workstation-revision.entity"; type WorkstationProps = Readonly<{ companyId: UniqueID; values: WorkstationValues; history: readonly WorkstationRevision[]; }>; export class Workstation extends AggregateRoot { private constructor(props: WorkstationProps, id?: UniqueID) { super(Object.freeze({ ...props, history: Object.freeze([...props.history]) }), id); } static create( companyId: UniqueID, values: WorkstationValues, actorId: UniqueID, recordedAt: string ): Result { if (!z.iso.datetime().safeParse(recordedAt).success) { return Result.fail(new AssetCatalogError("INVALID_REQUEST")); } return Result.ok( new Workstation({ companyId, values, history: [WorkstationRevision.create({ values, actorId, recordedAt })], }) ); } static rehydrate(props: WorkstationProps, id: UniqueID) { return new Workstation(props, id); } get companyId() { return this.props.companyId; } get values() { return this.props.values; } get history() { return this.props.history; } decommission(actorId: UniqueID, recordedAt: string): Result { const values = WorkstationValues.create({ ...this.values.toPrimitive(), active: false, computerAssetId: null, personId: null, assetIds: [], sharedAssetIds: [], }); return values.isSuccess ? this.update(values.data, actorId, recordedAt) : values; } update( values: WorkstationValues, actorId: UniqueID, recordedAt: string ): Result { if (this.values.equals(values)) { return Result.ok(this); } if ( !z.iso.datetime().safeParse(recordedAt).success || recordedAt < (this.history.at(-1)?.recordedAt ?? "") ) { return Result.fail(new AssetCatalogError("INVALID_REQUEST")); } return Result.ok( new Workstation( { ...this.props, values, history: [...this.history, WorkstationRevision.create({ values, actorId, recordedAt })], }, this.id ) ); } }