402 lines
13 KiB
TypeScript
402 lines
13 KiB
TypeScript
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 { CustomerInvoice, ICustomerInvoiceService } from "../domain";
|
|
|
|
export class CreateCustomerInvoiceUseCase {
|
|
constructor(
|
|
private readonly customerInvoiceService: ICustomerInvoiceService,
|
|
private readonly transactionManager: ITransactionManager
|
|
) {}
|
|
|
|
public execute(
|
|
customerInvoiceID: 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 customerInvoice with dto
|
|
return await this.customerInvoiceService.updateCustomerInvoiceById(customerInvoiceID, 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 customerInvoice
|
|
let customerInvoice_status = CustomerInvoiceStatus.create(customerInvoiceDTO.status).object;
|
|
if (customerInvoice_status.isEmpty()) {
|
|
customerInvoice_status = CustomerInvoiceStatus.createDraft();
|
|
}
|
|
|
|
let customerInvoice_series = CustomerInvoiceSeries.create(customerInvoiceDTO.customerInvoice_series).object;
|
|
if (customerInvoice_series.isEmpty()) {
|
|
customerInvoice_series = CustomerInvoiceSeries.create(customerInvoiceDTO.customerInvoice_series).object;
|
|
}
|
|
|
|
let invoice_date = CustomerInvoiceDate.create(customerInvoiceDTO.invoice_date).object;
|
|
if (invoice_date.isEmpty()) {
|
|
invoice_date = CustomerInvoiceDate.createCurrentDate().object;
|
|
}
|
|
|
|
let operation_date = CustomerInvoiceDate.create(customerInvoiceDTO.operation_date).object;
|
|
if (operation_date.isEmpty()) {
|
|
operation_date = CustomerInvoiceDate.createCurrentDate().object;
|
|
}
|
|
|
|
let customerInvoiceCurrency = Currency.createFromCode(customerInvoiceDTO.currency).object;
|
|
|
|
if (customerInvoiceCurrency.isEmpty()) {
|
|
customerInvoiceCurrency = Currency.createDefaultCode().object;
|
|
}
|
|
|
|
let customerInvoiceLanguage = Language.createFromCode(customerInvoiceDTO.language_code).object;
|
|
|
|
if (customerInvoiceLanguage.isEmpty()) {
|
|
customerInvoiceLanguage = Language.createDefaultCode().object;
|
|
}
|
|
|
|
const items = new Collection<CustomerInvoiceItem>(
|
|
customerInvoiceDTO.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 (!customerInvoice_status.isDraft()) {
|
|
throw Error("Error al crear una factura que no es borrador");
|
|
}
|
|
|
|
return DraftCustomerInvoice.create(
|
|
{
|
|
customerInvoiceSeries: customerInvoice_series,
|
|
invoiceDate: invoice_date,
|
|
operationDate: operation_date,
|
|
customerInvoiceCurrency,
|
|
language: customerInvoiceLanguage,
|
|
customerInvoiceNumber: CustomerInvoiceNumber.create(undefined).object,
|
|
//notes: Note.create(customerInvoiceDTO.notes).object,
|
|
|
|
//senderId: UniqueID.create(null).object,
|
|
recipient,
|
|
|
|
items,
|
|
},
|
|
customerInvoiceId
|
|
);
|
|
} */
|
|
}
|
|
|
|
/* 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: customerInvoiceDTO } = request;
|
|
|
|
// Validaciones
|
|
const customerInvoiceDTOOrError = ensureUpdateCustomerInvoice_DTOIsValid(customerInvoiceDTO);
|
|
if (customerInvoiceDTOOrError.isFailure) {
|
|
return this.handleValidationFailure(customerInvoiceDTOOrError.error);
|
|
}
|
|
|
|
const transaction = this._adapter.startTransaction();
|
|
|
|
const customerInvoiceRepoBuilder = this.getRepository<ICustomerInvoiceRepository>("CustomerInvoice");
|
|
|
|
let customerInvoice: CustomerInvoice | null = null;
|
|
|
|
try {
|
|
await transaction.complete(async (t) => {
|
|
customerInvoice = await customerInvoiceRepoBuilder({ transaction: t }).getById(id);
|
|
});
|
|
|
|
if (customerInvoice === null) {
|
|
return Result.fail<IUseCaseError>(
|
|
UseCaseError.create(UseCaseError.NOT_FOUND_ERROR, `CustomerInvoice not found`, {
|
|
id: request.id.toString(),
|
|
entity: "customerInvoice",
|
|
})
|
|
);
|
|
}
|
|
|
|
return Result.ok<CustomerInvoice>(customerInvoice);
|
|
} catch (error: unknown) {
|
|
const _error = error as Error;
|
|
if (customerInvoiceRepoBuilder().isRepositoryError(_error)) {
|
|
return this.handleRepositoryError(error as BaseError, customerInvoiceRepoBuilder());
|
|
} else {
|
|
return this.handleUnexceptedError(error);
|
|
}
|
|
}
|
|
|
|
// Recipient validations
|
|
const recipientIdOrError = ensureParticipantIdIsValid(
|
|
customerInvoiceDTO?.recipient?.id,
|
|
);
|
|
if (recipientIdOrError.isFailure) {
|
|
return this.handleValidationFailure(
|
|
recipientIdOrError.error,
|
|
"Recipient ID not valid",
|
|
);
|
|
}
|
|
const recipientId = recipientIdOrError.object;
|
|
|
|
const recipientBillingIdOrError = ensureParticipantAddressIdIsValid(
|
|
customerInvoiceDTO?.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(
|
|
customerInvoiceDTO?.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 customerInvoice
|
|
const customerInvoiceOrError = await this.tryUpdateCustomerInvoiceInstance(
|
|
customerInvoiceDTO,
|
|
customerInvoiceIdOrError.object,
|
|
//senderId,
|
|
//senderBillingId,
|
|
//senderShippingId,
|
|
recipientContact,
|
|
);
|
|
|
|
if (customerInvoiceOrError.isFailure) {
|
|
const { error: domainError } = customerInvoiceOrError;
|
|
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(customerInvoiceOrError.object);
|
|
|
|
}
|
|
|
|
private async tryUpdateCustomerInvoiceInstance(customerInvoiceDTO, customerInvoiceId, recipient) {
|
|
// Create customerInvoice
|
|
let customerInvoice_status = CustomerInvoiceStatus.create(customerInvoiceDTO.status).object;
|
|
if (customerInvoice_status.isEmpty()) {
|
|
customerInvoice_status = CustomerInvoiceStatus.createDraft();
|
|
}
|
|
|
|
let customerInvoice_series = CustomerInvoiceSeries.create(customerInvoiceDTO.customerInvoice_series).object;
|
|
if (customerInvoice_series.isEmpty()) {
|
|
customerInvoice_series = CustomerInvoiceSeries.create(customerInvoiceDTO.customerInvoice_series).object;
|
|
}
|
|
|
|
let invoice_date = CustomerInvoiceDate.create(customerInvoiceDTO.invoice_date).object;
|
|
if (invoice_date.isEmpty()) {
|
|
invoice_date = CustomerInvoiceDate.createCurrentDate().object;
|
|
}
|
|
|
|
let operation_date = CustomerInvoiceDate.create(customerInvoiceDTO.operation_date).object;
|
|
if (operation_date.isEmpty()) {
|
|
operation_date = CustomerInvoiceDate.createCurrentDate().object;
|
|
}
|
|
|
|
let customerInvoiceCurrency = Currency.createFromCode(customerInvoiceDTO.currency).object;
|
|
|
|
if (customerInvoiceCurrency.isEmpty()) {
|
|
customerInvoiceCurrency = Currency.createDefaultCode().object;
|
|
}
|
|
|
|
let customerInvoiceLanguage = Language.createFromCode(customerInvoiceDTO.language_code).object;
|
|
|
|
if (customerInvoiceLanguage.isEmpty()) {
|
|
customerInvoiceLanguage = Language.createDefaultCode().object;
|
|
}
|
|
|
|
const items = new Collection<CustomerInvoiceItem>(
|
|
customerInvoiceDTO.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 (!customerInvoice_status.isDraft()) {
|
|
throw Error("Error al crear una factura que no es borrador");
|
|
}
|
|
|
|
return DraftCustomerInvoice.create(
|
|
{
|
|
customerInvoiceSeries: customerInvoice_series,
|
|
invoiceDate: invoice_date,
|
|
operationDate: operation_date,
|
|
customerInvoiceCurrency,
|
|
language: customerInvoiceLanguage,
|
|
customerInvoiceNumber: CustomerInvoiceNumber.create(undefined).object,
|
|
//notes: Note.create(customerInvoiceDTO.notes).object,
|
|
|
|
//senderId: UniqueID.create(null).object,
|
|
recipient,
|
|
|
|
items,
|
|
},
|
|
customerInvoiceId
|
|
);
|
|
}
|
|
|
|
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(customerInvoice: DraftCustomerInvoice) {
|
|
const transaction = this._adapter.startTransaction();
|
|
const customerInvoiceRepoBuilder = this.getRepository<ICustomerInvoiceRepository>("CustomerInvoice");
|
|
|
|
try {
|
|
await transaction.complete(async (t) => {
|
|
const customerInvoiceRepo = customerInvoiceRepoBuilder({ transaction: t });
|
|
await customerInvoiceRepo.save(customerInvoice);
|
|
});
|
|
|
|
return Result.ok<DraftCustomerInvoice>(customerInvoice);
|
|
} catch (error: unknown) {
|
|
const _error = error as Error;
|
|
if (customerInvoiceRepoBuilder().isRepositoryError(_error)) {
|
|
return this.handleRepositoryError(error as BaseError, customerInvoiceRepoBuilder());
|
|
} 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)
|
|
);
|
|
}
|
|
}
|
|
*/
|