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 = { companyId: UniqueID; dto: CreateCustomerRequestDTO; }; 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; // 2) Construir entidad de dominio const buildResult = this.service.buildCustomerInCompany(companyId, props, id); if (buildResult.isFailure) { return Result.fail(buildResult.error); } const newCustomer = buildResult.data; // 3) Ejecutar bajo transacción: verificar duplicado → persistir → ensamblar vista return this.transactionManager.complete(async (transaction: Transaction) => { const existsGuard = await this.ensureNotExists(companyId, id, transaction); if (existsGuard.isFailure) { return Result.fail(existsGuard.error); } const saveResult = await this.service.saveCustomer(newCustomer, transaction); if (saveResult.isFailure) { return Result.fail(saveResult.error); } const viewDTO = this.assembler.toDTO(saveResult.data); 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); } }