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 // Misc errors (value objects) | Result; // Success! export class UpdateQuoteUseCase implements IUseCase> { 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 { 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); } 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 { 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( 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("Quote"); } }