import { Name, UniqueID } from "@repo/rdx-ddd"; import { Result } from "@repo/rdx-utils"; import type { SaveTicketInput } from "../../common/tickets"; import { Ticket } from "../domain/ticket.aggregate"; import { TicketError } from "../domain/ticket-values"; import { TicketValues } from "../domain/value-objects/ticket-values"; import type { ITicketRepository } from "./ticket.repository"; import { mapTicketInput } from "./ticket-input.mapper"; export class TicketUseCases { constructor(private readonly repository: ITicketRepository) {} list(companyId?: string) { const company = companyId ? UniqueID.create(companyId) : undefined; if (company && !company.isSuccess) { return Promise.resolve(Result.fail(new TicketError("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 TicketError("INVALID_REQUEST"))); } save(companyId: string, id: string | undefined, input: SaveTicketInput, actorId: string) { 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 TicketError("INVALID_REQUEST"))); } const normalizedId = identity?.isSuccess ? identity.data.toPrimitive() : undefined; return this.repository.save(company.data, key.data, (context) => { const previous = context.tickets.find((item) => item.id.toPrimitive() === normalizedId); if (id && !previous) { return Result.fail(new TicketError("TICKET_NOT_FOUND")); } if (!id && context.requestTicket) { return replayTicket(context.requestTicket, company.data, actor.data, input); } if (previous && previous.history.at(-1)?.id.toPrimitive() !== input.expectedRevisionId) { return Result.fail(new TicketError("TICKET_CHANGED")); } const values = mapTicketInput(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); } return createTicket(company.data, key.data, values.data, actor.data, context.nextNumber, now); }); } } function replayTicket( original: Ticket, company: UniqueID, actor: UniqueID, input: SaveTicketInput ): Result { const values = TicketValues.create(input.values); const first = original.history[0]; if ( !( original.companyId.equals(company) && first?.actorId.equals(actor) && values.isSuccess && first.values.equals(values.data) ) ) { return Result.fail(new TicketError("REQUEST_KEY_REUSED")); } return Result.ok(original); } function createTicket( company: UniqueID, key: UniqueID, values: TicketValues, actor: UniqueID, number: number, now: string ): Result { const reference = Name.create(`T-${String(number).padStart(6, "0")}`, 40); if (!reference.isSuccess) { return Result.fail(new TicketError("INVALID_REQUEST")); } return Ticket.create(company, reference.data, key, values, actor, now); }