FactuGES_ERP/modules/customer-invoices/src/api/application/update-customer-invoice.use-case.ts

402 lines
14 KiB
TypeScript
Raw Normal View History

2025-06-11 15:13:44 +00:00
import { UniqueID } from "@/core/common/domain";
import { ITransactionManager } from "@/core/common/infrastructure/database";
import { Result } from "@repo/rdx-utils";
import { IUpdateCustomerInvoiceRequestDTO } from "../../common/dto";
import { ICustomerInvoiceService, CustomerInvoice } from "../domain";
export class CreateCustomerInvoiceUseCase {
constructor(
private readonly customerCustomerInvoiceService: ICustomerInvoiceService,
private readonly transactionManager: ITransactionManager
) {}
public execute(
customerCustomerInvoiceID: UniqueID,
dto: Partial<IUpdateCustomerInvoiceRequestDTO>
): Promise<Result<CustomerInvoice, Error>> {
return this.transactionManager.complete(async (transaction) => {
return Result.fail(new Error("No implementado"));
/*
try {
const validOrErrors = this.validateCustomerInvoiceData(dto);
if (validOrErrors.isFailure) {
return Result.fail(validOrErrors.error);
}
const data = validOrErrors.data;
// Update customerCustomerInvoice with dto
return await this.customerCustomerInvoiceService.updateCustomerInvoiceById(customerCustomerInvoiceID, data, transaction);
} catch (error: unknown) {
logger.error(error as Error);
return Result.fail(error as Error);
}
*/
});
}
/* private validateCustomerInvoiceData(
dto: Partial<IUpdateCustomerInvoiceRequestDTO>
): Result<Partial<ICustomerInvoiceProps>, Error> {
const errors: Error[] = [];
const validatedData: Partial<ICustomerInvoiceProps> = {};
// Create customerCustomerInvoice
let customerCustomerInvoice_status = CustomerInvoiceStatus.create(customerCustomerInvoiceDTO.status).object;
if (customerCustomerInvoice_status.isEmpty()) {
customerCustomerInvoice_status = CustomerInvoiceStatus.createDraft();
}
let customerCustomerInvoice_series = CustomerInvoiceSeries.create(customerCustomerInvoiceDTO.customerCustomerInvoice_series).object;
if (customerCustomerInvoice_series.isEmpty()) {
customerCustomerInvoice_series = CustomerInvoiceSeries.create(customerCustomerInvoiceDTO.customerCustomerInvoice_series).object;
}
let issue_date = CustomerInvoiceDate.create(customerCustomerInvoiceDTO.issue_date).object;
if (issue_date.isEmpty()) {
issue_date = CustomerInvoiceDate.createCurrentDate().object;
}
let operation_date = CustomerInvoiceDate.create(customerCustomerInvoiceDTO.operation_date).object;
if (operation_date.isEmpty()) {
operation_date = CustomerInvoiceDate.createCurrentDate().object;
}
let customerCustomerInvoiceCurrency = Currency.createFromCode(customerCustomerInvoiceDTO.currency).object;
if (customerCustomerInvoiceCurrency.isEmpty()) {
customerCustomerInvoiceCurrency = Currency.createDefaultCode().object;
}
let customerCustomerInvoiceLanguage = Language.createFromCode(customerCustomerInvoiceDTO.language_code).object;
if (customerCustomerInvoiceLanguage.isEmpty()) {
customerCustomerInvoiceLanguage = Language.createDefaultCode().object;
}
const items = new Collection<CustomerInvoiceItem>(
customerCustomerInvoiceDTO.items?.map(
(item) =>
CustomerInvoiceSimpleItem.create({
description: Description.create(item.description).object,
quantity: Quantity.create(item.quantity).object,
unitPrice: UnitPrice.create({
amount: item.unit_price.amount,
currencyCode: item.unit_price.currency,
precision: item.unit_price.precision,
}).object,
}).object
)
);
if (!customerCustomerInvoice_status.isDraft()) {
throw Error("Error al crear una factura que no es borrador");
}
return DraftCustomerInvoice.create(
{
customerCustomerInvoiceSeries: customerCustomerInvoice_series,
issueDate: issue_date,
operationDate: operation_date,
customerCustomerInvoiceCurrency,
language: customerCustomerInvoiceLanguage,
customerCustomerInvoiceNumber: CustomerInvoiceNumber.create(undefined).object,
//notes: Note.create(customerCustomerInvoiceDTO.notes).object,
//senderId: UniqueID.create(null).object,
recipient,
items,
},
customerCustomerInvoiceId
);
} */
}
/* export type UpdateCustomerInvoiceResponseOrError =
| Result<never, IUseCaseError> // Misc errors (value objects)
| Result<CustomerInvoice, never>; // Success!
export class UpdateCustomerInvoiceUseCase2
implements
IUseCase<{ id: UniqueID; data: IUpdateCustomerInvoice_DTO }, Promise<UpdateCustomerInvoiceResponseOrError>>
{
private _context: IInvoicingContext;
private _adapter: ISequelizeAdapter;
private _repositoryManager: IRepositoryManager;
constructor(context: IInvoicingContext) {
this._context = context;
this._adapter = context.adapter;
this._repositoryManager = context.repositoryManager;
}
private getRepository<T>(name: string) {
return this._repositoryManager.getRepository<T>(name);
}
private handleValidationFailure(
validationError: Error,
message?: string
): Result<never, IUseCaseError> {
return Result.fail<IUseCaseError>(
UseCaseError.create(
UseCaseError.INVALID_INPUT_DATA,
message ? message : validationError.message,
validationError
)
);
}
async execute(request: {
id: UniqueID;
data: IUpdateCustomerInvoice_DTO;
}): Promise<UpdateCustomerInvoiceResponseOrError> {
const { id, data: customerCustomerInvoiceDTO } = request;
// Validaciones
const customerCustomerInvoiceDTOOrError = ensureUpdateCustomerInvoice_DTOIsValid(customerCustomerInvoiceDTO);
if (customerCustomerInvoiceDTOOrError.isFailure) {
return this.handleValidationFailure(customerCustomerInvoiceDTOOrError.error);
}
const transaction = this._adapter.startTransaction();
const customerCustomerInvoiceRepoBuilder = this.getRepository<ICustomerInvoiceRepository>("CustomerInvoice");
let customerCustomerInvoice: CustomerInvoice | null = null;
try {
await transaction.complete(async (t) => {
customerCustomerInvoice = await customerCustomerInvoiceRepoBuilder({ transaction: t }).getById(id);
});
if (customerCustomerInvoice === null) {
return Result.fail<IUseCaseError>(
UseCaseError.create(UseCaseError.NOT_FOUND_ERROR, `CustomerInvoice not found`, {
id: request.id.toString(),
entity: "customerCustomerInvoice",
})
);
}
return Result.ok<CustomerInvoice>(customerCustomerInvoice);
} catch (error: unknown) {
const _error = error as Error;
if (customerCustomerInvoiceRepoBuilder().isRepositoryError(_error)) {
return this.handleRepositoryError(error as BaseError, customerCustomerInvoiceRepoBuilder());
} else {
return this.handleUnexceptedError(error);
}
}
// Recipient validations
const recipientIdOrError = ensureParticipantIdIsValid(
customerCustomerInvoiceDTO?.recipient?.id,
);
if (recipientIdOrError.isFailure) {
return this.handleValidationFailure(
recipientIdOrError.error,
"Recipient ID not valid",
);
}
const recipientId = recipientIdOrError.object;
const recipientBillingIdOrError = ensureParticipantAddressIdIsValid(
customerCustomerInvoiceDTO?.recipient?.billing_address_id,
);
if (recipientBillingIdOrError.isFailure) {
return this.handleValidationFailure(
recipientBillingIdOrError.error,
"Recipient billing address ID not valid",
);
}
const recipientBillingId = recipientBillingIdOrError.object;
const recipientShippingIdOrError = ensureParticipantAddressIdIsValid(
customerCustomerInvoiceDTO?.recipient?.shipping_address_id,
);
if (recipientShippingIdOrError.isFailure) {
return this.handleValidationFailure(
recipientShippingIdOrError.error,
"Recipient shipping address ID not valid",
);
}
const recipientShippingId = recipientShippingIdOrError.object;
const recipientContact = await this.findContact(
recipientId,
recipientBillingId,
recipientShippingId,
);
if (!recipientContact) {
return this.handleValidationFailure(
new Error(`Recipient with ID ${recipientId.toString()} does not exist`),
);
}
// Crear customerCustomerInvoice
const customerCustomerInvoiceOrError = await this.tryUpdateCustomerInvoiceInstance(
customerCustomerInvoiceDTO,
customerCustomerInvoiceIdOrError.object,
//senderId,
//senderBillingId,
//senderShippingId,
recipientContact,
);
if (customerCustomerInvoiceOrError.isFailure) {
const { error: domainError } = customerCustomerInvoiceOrError;
let errorCode = "";
let message = "";
switch (domainError.code) {
case CustomerInvoice.ERROR_CUSTOMER_WITHOUT_NAME:
errorCode = UseCaseError.INVALID_INPUT_DATA;
message =
"El cliente debe ser una compañía o tener nombre y apellidos.";
break;
default:
errorCode = UseCaseError.UNEXCEPTED_ERROR;
message = "";
break;
}
return Result.fail<IUseCaseError>(
UseCaseError.create(errorCode, message, domainError),
);
}
return this.saveCustomerInvoice(customerCustomerInvoiceOrError.object);
}
private async tryUpdateCustomerInvoiceInstance(customerCustomerInvoiceDTO, customerCustomerInvoiceId, recipient) {
// Create customerCustomerInvoice
let customerCustomerInvoice_status = CustomerInvoiceStatus.create(customerCustomerInvoiceDTO.status).object;
if (customerCustomerInvoice_status.isEmpty()) {
customerCustomerInvoice_status = CustomerInvoiceStatus.createDraft();
}
let customerCustomerInvoice_series = CustomerInvoiceSeries.create(customerCustomerInvoiceDTO.customerCustomerInvoice_series).object;
if (customerCustomerInvoice_series.isEmpty()) {
customerCustomerInvoice_series = CustomerInvoiceSeries.create(customerCustomerInvoiceDTO.customerCustomerInvoice_series).object;
}
let issue_date = CustomerInvoiceDate.create(customerCustomerInvoiceDTO.issue_date).object;
if (issue_date.isEmpty()) {
issue_date = CustomerInvoiceDate.createCurrentDate().object;
}
let operation_date = CustomerInvoiceDate.create(customerCustomerInvoiceDTO.operation_date).object;
if (operation_date.isEmpty()) {
operation_date = CustomerInvoiceDate.createCurrentDate().object;
}
let customerCustomerInvoiceCurrency = Currency.createFromCode(customerCustomerInvoiceDTO.currency).object;
if (customerCustomerInvoiceCurrency.isEmpty()) {
customerCustomerInvoiceCurrency = Currency.createDefaultCode().object;
}
let customerCustomerInvoiceLanguage = Language.createFromCode(customerCustomerInvoiceDTO.language_code).object;
if (customerCustomerInvoiceLanguage.isEmpty()) {
customerCustomerInvoiceLanguage = Language.createDefaultCode().object;
}
const items = new Collection<CustomerInvoiceItem>(
customerCustomerInvoiceDTO.items?.map(
(item) =>
CustomerInvoiceSimpleItem.create({
description: Description.create(item.description).object,
quantity: Quantity.create(item.quantity).object,
unitPrice: UnitPrice.create({
amount: item.unit_price.amount,
currencyCode: item.unit_price.currency,
precision: item.unit_price.precision,
}).object,
}).object
)
);
if (!customerCustomerInvoice_status.isDraft()) {
throw Error("Error al crear una factura que no es borrador");
}
return DraftCustomerInvoice.create(
{
customerCustomerInvoiceSeries: customerCustomerInvoice_series,
issueDate: issue_date,
operationDate: operation_date,
customerCustomerInvoiceCurrency,
language: customerCustomerInvoiceLanguage,
customerCustomerInvoiceNumber: CustomerInvoiceNumber.create(undefined).object,
//notes: Note.create(customerCustomerInvoiceDTO.notes).object,
//senderId: UniqueID.create(null).object,
recipient,
items,
},
customerCustomerInvoiceId
);
}
private async findContact(
contactId: UniqueID,
billingAddressId: UniqueID,
shippingAddressId: UniqueID
) {
const contactRepoBuilder = this.getRepository<IContactRepository>("Contact");
const contact = await contactRepoBuilder().getById2(
contactId,
billingAddressId,
shippingAddressId
);
return contact;
}
private async saveCustomerInvoice(customerCustomerInvoice: DraftCustomerInvoice) {
const transaction = this._adapter.startTransaction();
const customerCustomerInvoiceRepoBuilder = this.getRepository<ICustomerInvoiceRepository>("CustomerInvoice");
try {
await transaction.complete(async (t) => {
const customerCustomerInvoiceRepo = customerCustomerInvoiceRepoBuilder({ transaction: t });
await customerCustomerInvoiceRepo.save(customerCustomerInvoice);
});
return Result.ok<DraftCustomerInvoice>(customerCustomerInvoice);
} catch (error: unknown) {
const _error = error as Error;
if (customerCustomerInvoiceRepoBuilder().isRepositoryError(_error)) {
return this.handleRepositoryError(error as BaseError, customerCustomerInvoiceRepoBuilder());
} else {
return this.handleUnexceptedError(error);
}
}
}
private handleUnexceptedError(error): Result<never, IUseCaseError> {
return Result.fail<IUseCaseError>(
UseCaseError.create(UseCaseError.UNEXCEPTED_ERROR, error.message, error)
);
}
private handleRepositoryError(
error: BaseError,
repository: ICustomerInvoiceRepository
): Result<never, IUseCaseError> {
const { message, details } = repository.handleRepositoryError(error);
return Result.fail<IUseCaseError>(
UseCaseError.create(UseCaseError.REPOSITORY_ERROR, message, details)
);
}
}
*/