163 lines
4.7 KiB
TypeScript
163 lines
4.7 KiB
TypeScript
|
|
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");
|
||
|
|
}
|
||
|
|
}
|