Uecko_ERP/modules/customers/src/api/application/create-customer/create-customer.use-case.ts

86 lines
2.7 KiB
TypeScript
Raw Normal View History

2025-08-11 17:49:52 +00:00
import { DuplicateEntityError, ITransactionManager } from "@erp/core/api";
2025-08-26 18:55:59 +00:00
import { UniqueID } from "@repo/rdx-ddd";
2025-08-11 17:49:52 +00:00
import { Result } from "@repo/rdx-utils";
import { Transaction } from "sequelize";
2025-08-26 18:55:59 +00:00
import { CreateCustomerRequestDTO } from "../../../common";
2025-09-01 14:07:59 +00:00
import { CustomerService } from "../../domain";
import { CreateCustomersAssembler } from "./assembler";
2025-09-01 14:07:59 +00:00
import { mapDTOToCreateCustomerProps } from "./map-dto-to-create-customer-props";
2025-08-11 17:49:52 +00:00
2025-08-25 17:42:56 +00:00
type CreateCustomerUseCaseInput = {
2025-08-26 18:55:59 +00:00
dto: CreateCustomerRequestDTO;
2025-09-01 16:38:00 +00:00
companyId: UniqueID;
2025-08-25 17:42:56 +00:00
};
2025-08-11 17:49:52 +00:00
export class CreateCustomerUseCase {
constructor(
2025-09-01 14:07:59 +00:00
private readonly service: CustomerService,
2025-08-11 17:49:52 +00:00
private readonly transactionManager: ITransactionManager,
private readonly assembler: CreateCustomersAssembler
2025-08-11 17:49:52 +00:00
) {}
2025-08-25 17:42:56 +00:00
public execute(params: CreateCustomerUseCaseInput) {
2025-09-01 16:38:00 +00:00
const { dto, companyId } = params;
2025-08-25 17:42:56 +00:00
2025-08-26 18:55:59 +00:00
// 1) Mapear DTO → props de dominio
2025-09-01 14:07:59 +00:00
const dtoResult = mapDTOToCreateCustomerProps(dto);
2025-08-26 18:55:59 +00:00
if (dtoResult.isFailure) {
return Result.fail(dtoResult.error);
2025-08-11 17:49:52 +00:00
}
2025-09-01 16:38:00 +00:00
const { props, id } = dtoResult.data;
2025-08-11 17:49:52 +00:00
2025-09-01 16:38:00 +00:00
console.debug("Creating customer with props:", props);
2025-08-11 17:49:52 +00:00
2025-08-26 18:55:59 +00:00
// 3) Construir entidad de dominio
2025-09-01 16:38:00 +00:00
const buildResult = this.service.buildCustomerInCompany(companyId, props, id);
2025-08-26 18:55:59 +00:00
if (buildResult.isFailure) {
return Result.fail(buildResult.error);
2025-08-11 17:49:52 +00:00
}
2025-08-26 18:55:59 +00:00
const newCustomer = buildResult.data;
2025-08-11 17:49:52 +00:00
2025-08-26 18:55:59 +00:00
console.debug("Built new customer entity:", newCustomer);
2025-08-11 17:49:52 +00:00
2025-08-26 18:55:59 +00:00
// 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);
}
2025-08-11 17:49:52 +00:00
2025-08-26 18:55:59 +00:00
console.debug("No existing customer with same ID found, proceeding to save.");
2025-08-11 17:49:52 +00:00
2025-08-26 18:55:59 +00:00
const saveResult = await this.service.saveCustomer(newCustomer, tx);
if (saveResult.isFailure) {
return Result.fail(saveResult.error);
2025-08-11 17:49:52 +00:00
}
2025-08-26 18:55:59 +00:00
const viewDTO = this.assembler.toDTO(saveResult.data);
console.debug("Assembled view DTO:", viewDTO);
return Result.ok(viewDTO);
2025-08-11 17:49:52 +00:00
});
}
2025-08-26 18:55:59 +00:00
/**
Verifica que no exista un Customer con el mismo id en la companyId.
*/
private async ensureNotExists(
companyId: UniqueID,
id: UniqueID,
transaction: Transaction
): Promise<Result<void, Error>> {
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<void>(undefined);
}
2025-08-11 17:49:52 +00:00
}