Presupuestador_web/server/src/contexts/sales/application/Quote/UpdateQuote.useCase.ts

163 lines
4.7 KiB
TypeScript
Raw Normal View History

2024-05-26 17:09:43 +00:00
import {
IUseCase,
IUseCaseError,
IUseCaseRequest,
UseCaseError,
} from "@/contexts/common/application";
import { IRepositoryManager } from "@/contexts/common/domain";
import { IInfrastructureError } from "@/contexts/common/infrastructure";
import { ISequelizeAdapter } from "@/contexts/common/infrastructure/sequelize";
import {
Collection,
Currency,
Description,
DomainError,
IDomainError,
Language,
Quantity,
Result,
UTCDateValue,
UniqueID,
UnitPrice,
} from "@shared/contexts";
import { IUpdateQuote_Request_DTO } from "@shared/contexts";
import { IQuoteRepository, Quote, QuoteItem, QuoteStatus } from "../../domain";
export interface IUpdateQuoteUseCaseRequest extends IUseCaseRequest {
id: UniqueID;
QuoteDTO: IUpdateQuote_Request_DTO;
}
export type UpdateQuoteResponseOrError =
| Result<never, IUseCaseError> // Misc errors (value objects)
| Result<Quote, never>; // Success!
export class UpdateQuoteUseCase
implements IUseCase<IUpdateQuoteUseCaseRequest, Promise<UpdateQuoteResponseOrError>>
{
private _adapter: ISequelizeAdapter;
private _repositoryManager: IRepositoryManager;
constructor(props: { adapter: ISequelizeAdapter; repositoryManager: IRepositoryManager }) {
this._adapter = props.adapter;
this._repositoryManager = props.repositoryManager;
}
async execute(request: IUpdateQuoteUseCaseRequest): Promise<UpdateQuoteResponseOrError> {
const { id, QuoteDTO } = request;
const QuoteRepository = this._getQuoteRepository();
// Comprobar que existe el Quote
const idExists = await QuoteRepository().exists(id);
if (!idExists) {
const message = `Quote ID not found`;
return Result.fail(
UseCaseError.create(UseCaseError.NOT_FOUND_ERROR, message, {
path: "id",
})
);
}
// Crear usuario
const QuoteOrError = this._tryCreateQuoteInstance(QuoteDTO, id);
if (QuoteOrError.isFailure) {
const { error: domainError } = QuoteOrError;
let errorCode = "";
let message = "";
switch (domainError.code) {
// Errores manuales
case DomainError.INVALID_INPUT_DATA:
errorCode = UseCaseError.INVALID_INPUT_DATA;
message = "El usuario tiene algún dato erróneo.";
break;
default:
errorCode = UseCaseError.UNEXCEPTED_ERROR;
message = domainError.message;
break;
}
return Result.fail(UseCaseError.create(errorCode, message, domainError));
}
return this._updateQuote(QuoteOrError.object);
}
private async _updateQuote(Quote: Quote) {
// Guardar el contacto
const transaction = this._adapter.startTransaction();
const QuoteRepository = this._getQuoteRepository();
let QuoteRepo: IQuoteRepository;
try {
await transaction.complete(async (t) => {
QuoteRepo = QuoteRepository({ transaction: t });
await QuoteRepo.update(Quote);
});
return Result.ok<Quote>(Quote);
} catch (error: unknown) {
const _error = error as IInfrastructureError;
return Result.fail(UseCaseError.create(UseCaseError.REPOSITORY_ERROR, _error.message));
}
}
private _tryCreateQuoteInstance(
quoteDTO: IUpdateQuote_Request_DTO,
quoteId: UniqueID
): Result<Quote, IDomainError> {
const statusOrError = QuoteStatus.create(quoteDTO.status);
if (statusOrError.isFailure) {
return Result.fail(statusOrError.error);
}
const dateOrError = UTCDateValue.create(quoteDTO.date);
if (dateOrError.isFailure) {
return Result.fail(dateOrError.error);
}
const languageOrError = Language.createFromCode(quoteDTO.language_code);
if (languageOrError.isFailure) {
return Result.fail(languageOrError.error);
}
const currencyOrError = Currency.createFromCode(quoteDTO.currency_code);
if (currencyOrError.isFailure) {
return Result.fail(currencyOrError.error);
}
const items = new Collection<QuoteItem>(
quoteDTO.items?.map(
(item) =>
QuoteItem.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
)
);
return Quote.create(
{
status: statusOrError.object,
date: dateOrError.object,
language: languageOrError.object,
currency: currencyOrError.object,
items,
},
quoteId
);
}
private _getQuoteRepository() {
return this._repositoryManager.getRepository<IQuoteRepository>("Quote");
}
}