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 { IUpdateProfile_Request_DTO, Percentage, Result, TextValueObject, 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; // 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 profile = exitsOrError.object; // Actualizar el perfil con datos actualizados profile.contactInformation = TextValueObject.create(profileDTO.contact_information).object; profile.defaultPaymentMethod = TextValueObject.create(profileDTO.default_payment_method).object; profile.defaultLegalTerms = TextValueObject.create(profileDTO.default_legal_terms).object; profile.defaultNotes = TextValueObject.create(profileDTO.default_notes).object; profile.defaultQuoteValidity = TextValueObject.create(profileDTO.default_quote_validity).object; profile.defaultShowLineDiscountColumn = profileDTO.default_show_line_discount_column ?? profile.defaultShowLineDiscountColumn; if (profileDTO.default_tax_label !== undefined) { const taxLabelOrError = TextValueObject.create(profileDTO.default_tax_label); if (taxLabelOrError.isFailure) { return Result.fail(taxLabelOrError.error); } profile.defaultTaxLabel = taxLabelOrError.object; } const taxOrError = Percentage.create(profileDTO.default_tax); if (taxOrError.isFailure) { return Result.fail(taxOrError.error); } profile.defaultTax = taxOrError.object; // Guardar los cambios return this._saveProfile(profile); } 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"); } }