Uecko_ERP/modules/customers/src/api/application/create-customer/create-customer.use-case.ts
2025-09-04 19:57:04 +02:00

79 lines
2.5 KiB
TypeScript

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<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);
}
}