Presupuestador_web/server/src/contexts/profile/application/UpdateProfile.useCase.ts

131 lines
4.4 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 {
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<never, IUseCaseError> // Misc errors (value objects)
| Result<Profile, never>; // Success!
export class UpdateProfileUseCase
implements IUseCase<IUpdateProfileUseCaseRequest, Promise<UpdateProfileResponseOrError>>
{
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<UpdateProfileResponseOrError> {
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<Profile>(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>(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<IProfileRepository>("Profile");
}
}