Presupuestador_web/server/src/contexts/profile/application/UpdateProfile.useCase.ts
2024-06-17 22:58:08 +02:00

134 lines
4.3 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 { 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<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;
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<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");
}
}