import { IUseCase, IUseCaseError, 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 { CurrencyData, DomainError, ICreateDealer_Request_DTO, IDomainError, Language, Name, Result, UniqueID, ensureIdIsValid, ensureNameIsValid, } from "@shared/contexts"; import { Dealer, DealerStatus, IDealerRepository } from "../../domain"; export type CreateDealerResponseOrError = | Result // Misc errors (value objects) | Result; // Success! export class CreateDealerUseCase 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: ICreateDealer_Request_DTO) { const { id, name } = request; // Validaciones de datos const idOrError = ensureIdIsValid(id); if (idOrError.isFailure) { const message = idOrError.error.message; //`Dealer ID ${dealerDTO.id} is not valid`; return Result.fail( UseCaseError.create(UseCaseError.INVALID_INPUT_DATA, message, [{ path: "id" }]) ); } const nameOrError = ensureNameIsValid(name); if (nameOrError.isFailure) { const message = nameOrError.error.message; //`Dealer ID ${dealerDTO.id} is not valid`; return Result.fail( UseCaseError.create(UseCaseError.INVALID_INPUT_DATA, message, [{ path: "name" }]) ); } // Comprobar que no existe un usuario previo con esos datos const dealerRepository = this._getDealerRepository(); const idExists = await dealerRepository().exists(idOrError.object); if (idExists) { const message = `Another dealer with same ID exists`; return Result.fail( UseCaseError.create(UseCaseError.RESOURCE_ALREADY_EXITS, message, { path: "id", }) ); } // Crear dealer const dealerOrError = this._tryCreateDealerInstance(request, idOrError.object); if (dealerOrError.isFailure) { const { error: domainError } = dealerOrError; let errorCode = ""; let message = ""; switch (domainError.code) { case DomainError.INVALID_INPUT_DATA: errorCode = UseCaseError.INVALID_INPUT_DATA; message = "El distribuidor 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._saveDealer(dealerOrError.object); } private async _saveDealer(dealer: Dealer) { // Guardar el contacto const transaction = this._adapter.startTransaction(); const dealerRepository = this._getDealerRepository(); let dealerRepo: IDealerRepository; try { await transaction.complete(async (t) => { dealerRepo = dealerRepository({ transaction: t }); await dealerRepo.create(dealer); }); return Result.ok(dealer); } catch (error: unknown) { const _error = error as IInfrastructureError; return Result.fail(UseCaseError.create(UseCaseError.REPOSITORY_ERROR, _error.message)); } } private _tryCreateDealerInstance( dealerDTO: ICreateDealer_Request_DTO, dealerId: UniqueID ): Result { const nameOrError = Name.create(dealerDTO.name); if (nameOrError.isFailure) { return Result.fail(nameOrError.error); } return Dealer.create( { name: nameOrError.object, currency: CurrencyData.createDefaultCode().object, language: Language.createDefaultCode().object, status: DealerStatus.createActive(), //user_id: user }, dealerId ); } private _getDealerRepository() { return this._repositoryManager.getRepository("Dealer"); } }