import { Name, UniqueID } from "@repo/rdx-ddd"; import { Maybe, Result } from "@repo/rdx-utils"; import type { SaveInterventionInput } from "../../common/interventions"; import { SaveInterventionSchema } from "../../common/interventions"; import { Intervention } from "../domain/intervention.aggregate"; import { InterventionError } from "../domain/intervention-values"; import { InterventionProcedure } from "../domain/value-objects/intervention-procedure"; import { InterventionValues } from "../domain/value-objects/intervention-values"; import type { IInterventionRepository, InterventionSaveContext } from "./intervention.repository"; import { mapInterventionInput } from "./intervention-input.mapper"; export class InterventionUseCases { constructor(private readonly repository: IInterventionRepository) {} list(companyId?: string) { const company = companyId ? UniqueID.create(companyId) : undefined; if (company && !company.isSuccess) { return Promise.resolve(Result.fail(new InterventionError("INVALID_REQUEST"))); } return this.repository.list(company?.isSuccess ? company.data : undefined); } lookups(companyId: string) { const company = UniqueID.create(companyId); return company.isSuccess ? this.repository.lookups(company.data) : Promise.resolve(Result.fail(new InterventionError("INVALID_REQUEST"))); } save(companyId: string, id: string | undefined, input: SaveInterventionInput, actorId: string) { const parsed = SaveInterventionSchema.safeParse(input); if (!parsed.success || (id && input.template !== null)) { return Promise.resolve(Result.fail(new InterventionError("INVALID_REQUEST"))); } const company = UniqueID.create(companyId); const actor = UniqueID.create(actorId); const key = UniqueID.create(input.requestKey); const identity = id ? UniqueID.create(id) : undefined; if ( !(company.isSuccess && actor.isSuccess && key.isSuccess) || (identity && !identity.isSuccess) || (!id && input.expectedRevisionId !== null) ) { return Promise.resolve(Result.fail(new InterventionError("INVALID_REQUEST"))); } const normalizedId = identity?.isSuccess ? identity.data.toPrimitive() : undefined; return this.repository.save(company.data, key.data, (context) => { const previous = context.interventions.find((item) => item.id.toPrimitive() === normalizedId); if (id && !previous) { return Result.fail(new InterventionError("INTERVENTION_NOT_FOUND")); } if (!id && context.requestIntervention) { return replayIntervention(context.requestIntervention, company.data, actor.data, input); } if (previous && previous.history.at(-1)?.id.toPrimitive() !== input.expectedRevisionId) { return Result.fail(new InterventionError("INTERVENTION_CHANGED")); } const values = mapInterventionInput(input.values, context, previous); if (!values.isSuccess) { return Result.fail(values.error); } const now = new Date().toISOString(); if (previous) { return previous.update(values.data, actor.data, now); } const procedure = appliedProcedure(input, context); if (!procedure.isSuccess) { return Result.fail(procedure.error); } return createIntervention( company.data, key.data, values.data, actor.data, context.nextNumber, now, procedure.data ); }); } } function replayIntervention( original: Intervention, company: UniqueID, actor: UniqueID, input: SaveInterventionInput ): Result { const values = InterventionValues.create(input.values); const first = original.history[0]; if ( !( sameProcedure(original, input) && original.companyId.equals(company) && first?.actorId.equals(actor) && values.isSuccess && first.values.equals(values.data) ) ) { return Result.fail(new InterventionError("REQUEST_KEY_REUSED")); } return Result.ok(original); } function createIntervention( company: UniqueID, key: UniqueID, values: InterventionValues, actor: UniqueID, number: number, now: string, procedure: Maybe ): Result { const reference = Name.create(`I-${String(number).padStart(6, "0")}`, 40); if (!reference.isSuccess) { return Result.fail(new InterventionError("INVALID_REQUEST")); } return Intervention.create(company, reference.data, key, values, procedure, actor, now); } function sameProcedure(intervention: Intervention, input: SaveInterventionInput) { const source = intervention.procedure.getOrUndefined(); return source ? source.templateId.toPrimitive() === input.template?.id.toLowerCase() && source.revisionId.toPrimitive() === input.template.revisionId.toLowerCase() : input.template === null; } function appliedProcedure( input: SaveInterventionInput, context: InterventionSaveContext ): Result, InterventionError> { if (!input.template) { return Result.ok(Maybe.none()); } const template = context.templates.find( (item) => item.id.toPrimitive() === input.template?.id.toLowerCase() ); if (!(template && template.values.active)) { return Result.fail(new InterventionError("TEMPLATE_UNAVAILABLE")); } if (template.history.at(-1)?.id.toPrimitive() !== input.template.revisionId.toLowerCase()) { return Result.fail(new InterventionError("TEMPLATE_CHANGED")); } const procedure = InterventionProcedure.create({ templateId: template.id.toPrimitive(), revisionId: input.template.revisionId, values: template.values.toPrimitive(), }); return procedure.isSuccess ? Result.ok(Maybe.some(procedure.data)) : Result.fail(procedure.error); }