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 { DomainError, IUpdateProfile_Request_DTO, Result, UniqueID } from "@shared/contexts"; import { IProfileRepository, Profile } from "../domain"; export interface IUpdateProfileUseCaseRequest extends IUseCaseRequest { userId: UniqueID; profileDTO: IUpdateProfile_Request_DTO; } export type UpdateProfileResponseOrError = | Result // Misc errors (value objects) | Result; // Success! export class UpdateProfileUseCase 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: IUpdateProfileUseCaseRequest): Promise { const { userId, profileDTO } = request; const profileRepository = this._getProfileRepository(); // Comprobar que existe el profile const exitsOrError = await this._getProfileDealer(userId); if (exitsOrError.isFailure) { const message = `Profile not found`; return Result.fail( UseCaseError.create(UseCaseError.NOT_FOUND_ERROR, message, { path: "userId", }) ); } const oldProfile = exitsOrError.object; // Crear perfil con datos actualizados const profileOrError = Profile.create( { contactInformation: profileDTO.contact_information, defaultPaymentMethod: profileDTO.default_payment_method, defaultLegalTerms: profileDTO.default_legal_terms, defaultNotes: profileDTO.default_notes, defaultQuoteValidity: profileDTO.default_quote_validity, }, oldProfile.id ); if (profileOrError.isFailure) { const { error: domainError } = profileOrError; let errorCode = ""; let message = ""; switch (domainError.code) { // Errores manuales case DomainError.INVALID_INPUT_DATA: errorCode = UseCaseError.INVALID_INPUT_DATA; message = "The profile has some incorrect data"; break; default: errorCode = UseCaseError.UNEXCEPTED_ERROR; message = domainError.message; break; } return Result.fail(UseCaseError.create(errorCode, message, domainError)); } // Guardar los cambios return this._saveProfile(profileOrError.object); } private async _saveProfile(updatedProfile: Profile) { // Guardar el contacto const transaction = this._adapter.startTransaction(); const profileRepository = this._getProfileRepository(); try { await transaction.complete(async (t) => { const profileRepo = profileRepository({ transaction: t }); await profileRepo.update(updatedProfile); }); return Result.ok(updatedProfile); } catch (error: unknown) { const _error = error as IInfrastructureError; return Result.fail(UseCaseError.create(UseCaseError.REPOSITORY_ERROR, _error.message)); } } private async _getProfileDealer(userId: UniqueID) { const transaction = this._adapter.startTransaction(); const dealerRepoBuilder = this._getProfileRepository(); let profile: Profile | null = null; try { await transaction.complete(async (t) => { const dealerRepo = dealerRepoBuilder({ transaction: t }); profile = await dealerRepo.getByUserId(userId); }); if (!profile) { return Result.fail(UseCaseError.create(UseCaseError.NOT_FOUND_ERROR, "Profile not found")); } return Result.ok(profile!); } catch (error: unknown) { const _error = error as IInfrastructureError; return Result.fail( UseCaseError.create(UseCaseError.REPOSITORY_ERROR, "Error al consultar el usuario", _error) ); } } private _getProfileRepository() { return this._repositoryManager.getRepository("Profile"); } }