This commit is contained in:
David Arranz 2024-06-17 22:58:08 +02:00
parent d405ce40d6
commit 7f363cd64a
14 changed files with 136 additions and 24 deletions

View File

@ -52,7 +52,7 @@ export class GetProfileUseCase
try { try {
await transaction.complete(async (t) => { await transaction.complete(async (t) => {
const dealerRepo = dealerRepoBuilder({ transaction: t }); const dealerRepo = dealerRepoBuilder({ transaction: t });
profile = await dealerRepo.getById(userId); profile = await dealerRepo.getByUserId(userId);
}); });
if (!profile) { if (!profile) {
@ -67,8 +67,4 @@ export class GetProfileUseCase
); );
} }
} }
private _getProfileRepository() {
return this._repositoryManager.getRepository<IProfileRepository>("Profile");
}
} }

View File

@ -0,0 +1,74 @@
import {
IUseCase,
IUseCaseError,
IUseCaseRequest,
UseCaseError,
} from "@/contexts/common/application/useCases";
import { IRepositoryManager } from "@/contexts/common/domain";
import { ISequelizeAdapter } from "@/contexts/common/infrastructure/sequelize";
import { Result, UniqueID } from "@shared/contexts";
import { IInfrastructureError } from "@/contexts/common/infrastructure";
import { IProfileRepository, Profile } from "../domain";
export interface IGetProfileUseCaseRequest extends IUseCaseRequest {
userId: UniqueID;
}
export type GetProfileResponseOrError =
| Result<never, IUseCaseError> // Misc errors (value objects)
| Result<Profile, never>; // Success!
export class GetProfileByUserIdUseCase
implements IUseCase<IGetProfileUseCaseRequest, Promise<GetProfileResponseOrError>>
{
private _adapter: ISequelizeAdapter;
private _repositoryManager: IRepositoryManager;
constructor(props: { adapter: ISequelizeAdapter; repositoryManager: IRepositoryManager }) {
this._adapter = props.adapter;
this._repositoryManager = props.repositoryManager;
}
private getRepositoryByName<T>(name: string) {
return this._repositoryManager.getRepository<T>(name);
}
async execute(request: IGetProfileUseCaseRequest): Promise<GetProfileResponseOrError> {
const { userId } = request;
// Validación de datos
// No hay en este caso
return await this._getProfileDealer(userId);
}
private async _getProfileDealer(userId: UniqueID) {
const transaction = this._adapter.startTransaction();
const dealerRepoBuilder = this.getRepositoryByName<IProfileRepository>("Profile");
let profile: Profile | null = null;
try {
await transaction.complete(async (t) => {
const dealerRepo = dealerRepoBuilder({ transaction: t });
profile = await dealerRepo.getById(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");
}
}

View File

@ -11,7 +11,7 @@ import { DomainError, IUpdateProfile_Request_DTO, Result, UniqueID } from "@shar
import { IProfileRepository, Profile } from "../domain"; import { IProfileRepository, Profile } from "../domain";
export interface IUpdateProfileUseCaseRequest extends IUseCaseRequest { export interface IUpdateProfileUseCaseRequest extends IUseCaseRequest {
id: UniqueID; userId: UniqueID;
profileDTO: IUpdateProfile_Request_DTO; profileDTO: IUpdateProfile_Request_DTO;
} }
@ -31,20 +31,22 @@ export class UpdateProfileUseCase
} }
async execute(request: IUpdateProfileUseCaseRequest): Promise<UpdateProfileResponseOrError> { async execute(request: IUpdateProfileUseCaseRequest): Promise<UpdateProfileResponseOrError> {
const { id, profileDTO } = request; const { userId, profileDTO } = request;
const profileRepository = this._getProfileRepository(); const profileRepository = this._getProfileRepository();
// Comprobar que existe el profile // Comprobar que existe el profile
const idExists = await profileRepository().exists(id); const exitsOrError = await this._getProfileDealer(userId);
if (!idExists) { if (exitsOrError.isFailure) {
const message = `Profile not found`; const message = `Profile not found`;
return Result.fail( return Result.fail(
UseCaseError.create(UseCaseError.NOT_FOUND_ERROR, message, { UseCaseError.create(UseCaseError.NOT_FOUND_ERROR, message, {
path: "id", path: "userId",
}) })
); );
} }
const oldProfile = exitsOrError.object;
// Crear perfil con datos actualizados // Crear perfil con datos actualizados
const profileOrError = Profile.create( const profileOrError = Profile.create(
{ {
@ -54,7 +56,7 @@ export class UpdateProfileUseCase
defaultNotes: profileDTO.default_notes, defaultNotes: profileDTO.default_notes,
defaultQuoteValidity: profileDTO.default_quote_validity, defaultQuoteValidity: profileDTO.default_quote_validity,
}, },
id oldProfile.id
); );
if (profileOrError.isFailure) { if (profileOrError.isFailure) {
@ -100,6 +102,31 @@ export class UpdateProfileUseCase
} }
} }
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() { private _getProfileRepository() {
return this._repositoryManager.getRepository<IProfileRepository>("Profile"); return this._repositoryManager.getRepository<IProfileRepository>("Profile");
} }

View File

@ -6,4 +6,6 @@ export interface IProfileRepository extends IRepository<any> {
exists(id: UniqueID): Promise<boolean>; exists(id: UniqueID): Promise<boolean>;
getById(id: UniqueID): Promise<Profile | null>; getById(id: UniqueID): Promise<Profile | null>;
update(profile: Profile): Promise<void>; update(profile: Profile): Promise<void>;
getByUserId(userId: UniqueID): Promise<Profile | null>;
} }

View File

@ -37,7 +37,17 @@ export class ProfileRepository extends SequelizeRepository<Profile> implements I
// borrando y luego creando // borrando y luego creando
// await this.removeById(user.id, true); // await this.removeById(user.id, true);
await this._save("Dealer_Model", profile.id, userData, {}); await this._save("Profile_Model", profile.id, userData, {});
}
public async getByUserId(userId: UniqueID): Promise<Profile | null> {
const rawDealer: any = await this._getBy("Profile_Model", "user_id", userId.toPrimitive());
if (!rawDealer === true) {
return null;
}
return this.mapper.mapToDomain(rawDealer);
} }
} }

View File

@ -9,7 +9,7 @@ export interface IGetProfilePresenter {
export const GetProfilePresenter: IGetProfilePresenter = { export const GetProfilePresenter: IGetProfilePresenter = {
map: (profile: Profile, context: IProfileContext): IGetProfileResponse_DTO => { map: (profile: Profile, context: IProfileContext): IGetProfileResponse_DTO => {
return { return {
id: profile.id.toString(), dealer_id: profile.id.toString(),
contact_information: profile.contactInformation, contact_information: profile.contactInformation,
default_payment_method: profile.defaultPaymentMethod, default_payment_method: profile.defaultPaymentMethod,
default_notes: profile.defaultNotes, default_notes: profile.defaultNotes,

View File

@ -1,2 +1,2 @@
export * from "./getProfile"; export * from "./getProfile";
//export * from "./updateProfile"; export * from "./updateProfile";

View File

@ -62,7 +62,7 @@ export class UpdateProfileController extends ExpressController {
// Llamar al caso de uso // Llamar al caso de uso
const result = await this.useCase.execute({ const result = await this.useCase.execute({
id: user.id, userId: user.id,
profileDTO, profileDTO,
}); });
@ -84,7 +84,7 @@ export class UpdateProfileController extends ExpressController {
switch (error.code) { switch (error.code) {
case UseCaseError.NOT_FOUND_ERROR: case UseCaseError.NOT_FOUND_ERROR:
errorMessage = "Profile has no associated profile"; errorMessage = "User has no associated profile";
infraError = InfrastructureError.create( infraError = InfrastructureError.create(
InfrastructureError.RESOURCE_NOT_FOUND_ERROR, InfrastructureError.RESOURCE_NOT_FOUND_ERROR,

View File

@ -1,11 +1,11 @@
import { UpdateProfileUseCase } from "@/contexts/profile/application"; import { UpdateProfileUseCase } from "@/contexts/profile/application";
import { registerDealerRepository } from "@/contexts/sales/infrastructure/Dealer.repository";
import { IProfileContext } from "../../../Profile.context"; import { IProfileContext } from "../../../Profile.context";
import { registerProfileRepository } from "../../../Profile.repository";
import { UpdateProfileController } from "./UpdateProfile.controller"; import { UpdateProfileController } from "./UpdateProfile.controller";
import { UpdateProfilePresenter } from "./presenter"; import { UpdateProfilePresenter } from "./presenter";
export const createUpdateProfileController = (context: IProfileContext) => { export const createUpdateProfileController = (context: IProfileContext) => {
registerDealerRepository(context); registerProfileRepository(context);
return new UpdateProfileController( return new UpdateProfileController(
{ {

View File

@ -9,7 +9,7 @@ export interface IUpdateProfilePresenter {
export const UpdateProfilePresenter: IUpdateProfilePresenter = { export const UpdateProfilePresenter: IUpdateProfilePresenter = {
map: (profile: Profile, context: IProfileContext): IUpdateProfileResponse_DTO => { map: (profile: Profile, context: IProfileContext): IUpdateProfileResponse_DTO => {
return { return {
id: profile.id.toString(), dealer_id: profile.id.toString(),
contact_information: profile.contactInformation, contact_information: profile.contactInformation,
default_payment_method: profile.defaultPaymentMethod, default_payment_method: profile.defaultPaymentMethod,
default_notes: profile.defaultNotes, default_notes: profile.defaultNotes,

View File

@ -44,9 +44,9 @@ export default (sequelize: Sequelize) => {
timestamps: true, timestamps: true,
//version: true, //version: true,
createdAt: false, createdAt: "created_at",
updatedAt: "updated_at", updatedAt: "updated_at",
deletedAt: false, deletedAt: "deleted_at",
} }
); );

View File

@ -1,5 +1,8 @@
import { checkUser } from "@/contexts/auth"; import { checkUser } from "@/contexts/auth";
import { createGetProfileController } from "@/contexts/profile/infrastructure"; import {
createGetProfileController,
createUpdateProfileController,
} from "@/contexts/profile/infrastructure";
import Express from "express"; import Express from "express";
export const profileRouter = (appRouter: Express.Router) => { export const profileRouter = (appRouter: Express.Router) => {

View File

@ -1,5 +1,5 @@
export interface IGetProfileResponse_DTO { export interface IGetProfileResponse_DTO {
id: string; dealer_id: string;
contact_information: string; contact_information: string;
default_payment_method: string; default_payment_method: string;
default_notes: string; default_notes: string;

View File

@ -1,5 +1,5 @@
export interface IUpdateProfileResponse_DTO { export interface IUpdateProfileResponse_DTO {
id: string; dealer_id: string;
contact_information: string; contact_information: string;
default_payment_method: string; default_payment_method: string;
default_notes: string; default_notes: string;