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 { TeleworkAuthorizationRevision } from "./telework-authorization-revision.entity"; import { TeleworkAuthorizationError } from "./telework-authorization-values"; import type { TeleworkAuthorizationValues } from "./value-objects/telework-authorization-values.vo"; type TeleworkAuthorizationProps = Readonly<{ companyId: UniqueID; values: TeleworkAuthorizationValues; history: readonly TeleworkAuthorizationRevision[]; }>; export class TeleworkAuthorization extends AggregateRoot { private constructor(props: TeleworkAuthorizationProps, id?: UniqueID) { super(Object.freeze({ ...props, history: Object.freeze([...props.history]) }), id); } static create( companyId: UniqueID, values: TeleworkAuthorizationValues, actorId: UniqueID, recordedAt: string ): Result { if (!z.iso.datetime().safeParse(recordedAt).success) { return Result.fail(new TeleworkAuthorizationError("INVALID_REQUEST")); } return Result.ok( new TeleworkAuthorization({ companyId, values, history: [TeleworkAuthorizationRevision.create({ values, actorId, recordedAt })], }) ); } static rehydrate(props: TeleworkAuthorizationProps, id: UniqueID) { return new TeleworkAuthorization(props, id); } get companyId() { return this.props.companyId; } get values() { return this.props.values; } get history() { return this.props.history; } update( values: TeleworkAuthorizationValues, actorId: UniqueID, recordedAt: string ): Result { if (this.values.equals(values)) { return Result.ok(this); } if (!this.values.sameTarget(values)) { return Result.fail(new TeleworkAuthorizationError("TELEWORK_PERSON_IMMUTABLE")); } if ( !z.iso.datetime().safeParse(recordedAt).success || recordedAt < (this.history.at(-1)?.recordedAt ?? "") ) { return Result.fail(new TeleworkAuthorizationError("INVALID_REQUEST")); } return Result.ok( new TeleworkAuthorization( { ...this.props, values, history: [ ...this.history, TeleworkAuthorizationRevision.create({ values, actorId, recordedAt }), ], }, this.id ) ); } }