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 { WorkProfileValues } from "./value-objects/work-profile-values.vo"; import { WorkProfileRevision } from "./work-profile-revision.entity"; import { WorkProfileError } from "./work-profile-values"; type WorkProfileProps = Readonly<{ companyId: UniqueID; values: WorkProfileValues; history: readonly WorkProfileRevision[]; }>; export class WorkProfile extends AggregateRoot { private constructor(props: WorkProfileProps, id?: UniqueID) { super(Object.freeze({ ...props, history: Object.freeze([...props.history]) }), id); } static create( companyId: UniqueID, values: WorkProfileValues, actorId: UniqueID, recordedAt: string ): Result { if (!z.iso.datetime().safeParse(recordedAt).success) { return Result.fail(new WorkProfileError("INVALID_REQUEST")); } return Result.ok( new WorkProfile({ companyId, values, history: [WorkProfileRevision.create({ values, actorId, recordedAt })], }) ); } static rehydrate(props: WorkProfileProps, id: UniqueID) { return new WorkProfile(props, id); } get companyId() { return this.props.companyId; } get values() { return this.props.values; } get history() { return this.props.history; } deactivate(actorId: UniqueID, recordedAt: string): Result { const values = WorkProfileValues.create({ ...this.values.toPrimitive(), active: false }); return values.isSuccess ? this.update(values.data, actorId, recordedAt) : values; } checkRemoval({ hasConfigurations, }: { hasConfigurations: boolean; }): Result { if (this.values.active) { return Result.fail(new WorkProfileError("PROFILE_ACTIVE")); } if (hasConfigurations) { return Result.fail(new WorkProfileError("PROFILE_IN_USE")); } return Result.ok(undefined); } update( values: WorkProfileValues, actorId: UniqueID, recordedAt: string ): Result { if (this.values.equals(values)) { return Result.ok(this); } if (!this.values.sameTarget(values)) { return Result.fail(new WorkProfileError("PROFILE_TARGET_IMMUTABLE")); } if ( !z.iso.datetime().safeParse(recordedAt).success || recordedAt < (this.history.at(-1)?.recordedAt ?? "") ) { return Result.fail(new WorkProfileError("INVALID_REQUEST")); } return Result.ok( new WorkProfile( { ...this.props, values, history: [...this.history, WorkProfileRevision.create({ values, actorId, recordedAt })], }, this.id ) ); } }