Uecko_ERP/modules/customers/src/api/application/services/customer-creator.ts
2026-04-21 19:13:59 +02:00

75 lines
1.8 KiB
TypeScript

import { DuplicateEntityError } from "@erp/core/api";
import type { UniqueID } from "@repo/rdx-ddd";
import { Result } from "@repo/rdx-utils";
import { Customer, type ICustomerCreateProps } from "../../domain";
import type { ICustomerRepository } from "../repositories";
import { CustomerNotExistsInCompanySpecification } from "../specs";
export interface ICustomerCreator {
create(params: {
companyId: UniqueID;
id: UniqueID;
props: ICustomerCreateProps;
transaction?: unknown;
}): Promise<Result<Customer, Error>>;
}
type CustomerCreatorDeps = {
repository: ICustomerRepository;
};
export class CustomerCreator implements ICustomerCreator {
private readonly repository: ICustomerRepository;
constructor(deps: CustomerCreatorDeps) {
this.repository = deps.repository;
}
async create(params: {
companyId: UniqueID;
id: UniqueID;
props: ICustomerCreateProps;
transaction?: unknown;
}): Promise<Result<Customer, Error>> {
const { companyId, id, props, transaction } = params;
// 1. Verificar unicidad
const spec = new CustomerNotExistsInCompanySpecification(
this.repository,
companyId,
transaction
);
const isNew = await spec.isSatisfiedBy(id);
if (!isNew) {
return Result.fail(new DuplicateEntityError("Customer", "id", String(id)));
}
// 2. Crear agregado
const createResult = Customer.create(
{
...props,
companyId,
},
id
);
if (createResult.isFailure) {
return createResult;
}
const newCustomer = createResult.data;
// 3. Persistir agregado
const saveResult = await this.repository.create(newCustomer, transaction);
if (saveResult.isFailure) {
return Result.fail(saveResult.error);
}
return Result.ok(newCustomer);
}
}