import { DuplicateEntityError, ITransactionManager } from "@erp/core/api"; import { UniqueID } from "@repo/rdx-ddd"; import { Result } from "@repo/rdx-utils"; import { Transaction } from "sequelize"; import { CreateCustomerRequestDTO } from "../../../common"; import { CustomerService } from "../../domain"; import { CreateCustomersAssembler } from "./assembler"; import { mapDTOToCreateCustomerProps } from "./map-dto-to-create-customer-props"; type CreateCustomerUseCaseInput = { dto: CreateCustomerRequestDTO; companyId: UniqueID; }; export class CreateCustomerUseCase { constructor( private readonly service: CustomerService, private readonly transactionManager: ITransactionManager, private readonly assembler: CreateCustomersAssembler ) {} public execute(params: CreateCustomerUseCaseInput) { const { dto, companyId } = params; // 1) Mapear DTO → props de dominio const dtoResult = mapDTOToCreateCustomerProps(dto); if (dtoResult.isFailure) { return Result.fail(dtoResult.error); } const { props, id } = dtoResult.data; console.debug("Creating customer with props:", props); // 3) Construir entidad de dominio const buildResult = this.service.buildCustomerInCompany(companyId, props, id); if (buildResult.isFailure) { return Result.fail(buildResult.error); } const newCustomer = buildResult.data; console.debug("Built new customer entity:", newCustomer); // 4) Ejecutar bajo transacción: verificar duplicado → persistir → ensamblar vista return this.transactionManager.complete(async (tx: Transaction) => { const existsGuard = await this.ensureNotExists(companyId, id, tx); if (existsGuard.isFailure) { return Result.fail(existsGuard.error); } console.debug("No existing customer with same ID found, proceeding to save."); const saveResult = await this.service.saveCustomer(newCustomer, tx); if (saveResult.isFailure) { return Result.fail(saveResult.error); } const viewDTO = this.assembler.toDTO(saveResult.data); console.debug("Assembled view DTO:", viewDTO); return Result.ok(viewDTO); }); } /** Verifica que no exista un Customer con el mismo id en la companyId. */ private async ensureNotExists( companyId: UniqueID, id: UniqueID, transaction: Transaction ): Promise> { const existsResult = await this.service.existsByIdInCompany(companyId, id, transaction); if (existsResult.isFailure) { return Result.fail(existsResult.error); } if (existsResult.data) { return Result.fail(new DuplicateEntityError("Customer", "id", String(id))); } return Result.ok(undefined); } }