diff --git a/server/src/contexts/users/application/CreateUser.useCase.ts b/server/src/contexts/users/application/CreateUser.useCase.ts index 43dedc1..41248cb 100644 --- a/server/src/contexts/users/application/CreateUser.useCase.ts +++ b/server/src/contexts/users/application/CreateUser.useCase.ts @@ -121,35 +121,22 @@ export class CreateUserUseCase switch (domainError.code) { case User.ERROR_USER_WITHOUT_NAME: - return Result.fail( - UseCaseError.create( - UseCaseError.INVALID_INPUT_DATA, - "El usuario debe tener un nombre.", - domainError, - ), - ); + errorCode = UseCaseError.INVALID_INPUT_DATA; + message = "El usuario debe tener un nombre."; break; case DomainError.INVALID_INPUT_DATA: errorCode = UseCaseError.INVALID_INPUT_DATA; - message = domainError.message; - return Result.fail( - UseCaseError.create( - UseCaseError.INVALID_INPUT_DATA, - "El usuario tiene algún dato erróneo.", - domainError, - ), - ); + message = "El usuario tiene algún dato erróneo."; break; default: errorCode = UseCaseError.UNEXCEPTED_ERROR; message = domainError.message; - return Result.fail( - UseCaseError.create(errorCode, message, domainError), - ); break; } + + return Result.fail(UseCaseError.create(errorCode, message, domainError)); } return this._saveUser(userOrError.object); diff --git a/server/src/contexts/users/application/UpdateUser.useCase.ts b/server/src/contexts/users/application/UpdateUser.useCase.ts index 063ae6f..2a847a1 100644 --- a/server/src/contexts/users/application/UpdateUser.useCase.ts +++ b/server/src/contexts/users/application/UpdateUser.useCase.ts @@ -3,45 +3,20 @@ import { IUseCaseError, IUseCaseRequest, UseCaseError, -} from "@/contexts/common/application/useCases"; -import { IRepositoryManager } from "@/contexts/common/domain"; +} from "@/contexts/common/application"; +import { IRepositoryManager, Password } from "@/contexts/common/domain"; +import { IInfrastructureError } from "@/contexts/common/infrastructure"; import { ISequelizeAdapter } from "@/contexts/common/infrastructure/sequelize"; import { - AddressTitle, - City, - Collection, - Country, DomainError, + Email, IDomainError, - IUpdateUser_DTO, IUpdateUser_Request_DTO, - Note, - PostalCode, - Province, + Name, Result, - ResultCollection, - Street, UniqueID, - UserEmail, - UserJobTitle, - UserName, - UserPhone, - UserTIN, - ensureIdIsValid, } from "@shared/contexts"; - -import { IInfrastructureError } from "@/contexts/common/infrastructure"; -import { - IBillingAddressUser_DTO, - IShippingAddressUser_DTO, -} from "@shared/contexts/users/application/dto/IUserAddressDTO"; -import { - IUserRepository, - User, - UserAddressType, - UserShippingAddress, -} from "../domain"; -import { existsUserByID } from "./userServices"; +import { IUserRepository, User } from "../domain"; export interface IUpdateUserUseCaseRequest extends IUseCaseRequest { id: UniqueID; @@ -67,277 +42,64 @@ export class UpdateUserUseCase this._repositoryManager = props.repositoryManager; } - private getRepositoryByName(name: string) { - return this._repositoryManager.getRepository(name); - } - async execute( request: IUpdateUserUseCaseRequest, ): Promise { const { id, userDTO } = request; - const userRepository = this.getRepositoryByName("User"); - - // Validaciones de datos - const userIdOrError = ensureIdIsValid(userDTO.id); - if (userIdOrError.isFailure) { - return Result.fail( - UseCaseError.create( - UseCaseError.INVALID_INPUT_DATA, - "User ID is not valid", - userIdOrError.error, - ), - ); - } + const userRepository = this._getUserRepository(); // Comprobar que existe el user - const idExists = await existsUserByID( - userIdOrError.object, - this._adapter, - userRepository, - ); + const idExists = await userRepository().existsUserWithId(id); if (!idExists) { - const message = `User with ID ${id.toString()} not found`; - return Result.fail( - UseCaseError.create(UseCaseError.NOT_FOUND_ERROR, message, [ - { path: "id" }, - ]), + const message = `User ID not found`; + return Result.fail( + UseCaseError.create(UseCaseError.NOT_FOUND_ERROR, message, { + path: "id", + }), ); } - // Crear user + // Crear usuario const userOrError = this._tryCreateUserInstance(userDTO, id); if (userOrError.isFailure) { const { error: domainError } = userOrError; let errorCode = ""; let message = ""; - let payload = {}; switch (domainError.code) { // Errores manuales - case User.ERROR_CUSTOMER_WITHOUT_NAME: + case User.ERROR_USER_WITHOUT_NAME: errorCode = UseCaseError.INVALID_INPUT_DATA; - message = "El usuario debe ser una compañía o tener nombre."; - payload = [{ path: "first_name" }, { path: "company_name" }]; + message = "El usuario debe tener un nombre."; break; - // Value object error case DomainError.INVALID_INPUT_DATA: errorCode = UseCaseError.INVALID_INPUT_DATA; - message = domainError.message; - payload = domainError.payload; + message = "El usuario tiene algún dato erróneo."; break; default: errorCode = UseCaseError.UNEXCEPTED_ERROR; message = domainError.message; - payload = domainError.payload; break; } - return Result.fail( - UseCaseError.create(errorCode, message, payload), - ); + return Result.fail(UseCaseError.create(errorCode, message, domainError)); } return this._updateUser(userOrError.object); } - private _tryCreateUserAddress( - addressDTO: IBillingAddressUser_DTO | IShippingAddressUser_DTO | undefined, - addressType: UserAddressType, - ) { - const titleOrError = AddressTitle.create(addressDTO?.title); - if (titleOrError.isFailure) { - return Result.fail(titleOrError.error); - } - - const streetOrError = Street.create(addressDTO?.street); - if (streetOrError.isFailure) { - return Result.fail(streetOrError.error); - } - - const postalCodeOrError = PostalCode.create(addressDTO?.postal_code); - if (postalCodeOrError.isFailure) { - return Result.fail(postalCodeOrError.error); - } - - const cityOrError = City.create(addressDTO?.city); - if (cityOrError.isFailure) { - return Result.fail(cityOrError.error); - } - - const provinceOrError = Province.create(addressDTO?.province); - if (provinceOrError.isFailure) { - return Result.fail(provinceOrError.error); - } - - const countryOrError = Country.create(addressDTO?.country); - if (countryOrError.isFailure) { - return Result.fail(countryOrError.error); - } - - const emailOrError = UserEmail.create(addressDTO?.email); - if (emailOrError.isFailure) { - return Result.fail(emailOrError.error); - } - - const phoneOrError = UserPhone.create(addressDTO?.phone); - if (phoneOrError.isFailure) { - return Result.fail(phoneOrError.error); - } - - const notesOrError = Note.create(addressDTO?.notes); - if (notesOrError.isFailure) { - return Result.fail(notesOrError.error); - } - - const addressProps = { - title: titleOrError.object, - street: streetOrError.object, - city: cityOrError.object, - province: provinceOrError.object, - postalCode: postalCodeOrError.object, - country: countryOrError.object, - email: emailOrError.object, - phone: phoneOrError.object, - notes: notesOrError.object, - }; - - return addressType === "billing" - ? UserShippingAddress.create(addressProps) - : UserShippingAddress.create(addressProps); - } - - private _tryCreateUserShippingAddresses( - addressesDTO: IShippingAddressUser_DTO[] | undefined, - ) { - const shippingAddressesOrError = new ResultCollection< - UserShippingAddress, - DomainError - >(); - - if (addressesDTO) { - addressesDTO.map((value) => { - const result = this._tryCreateUserAddress(value, "shipping"); - shippingAddressesOrError.add(result); - }); - } - - if (shippingAddressesOrError.hasSomeFaultyResult()) { - return Result.fail(shippingAddressesOrError.getFirstFaultyResult().error); - } - - return Result.ok(new Collection(shippingAddressesOrError.objects)); - } - - private _tryCreateUserInstance( - userDTO: IUpdateUser_DTO, - userId: UniqueID, - ): Result { - const userTINOrError = UserTIN.create(userDTO.tin, { - label: "tin", - path: "tin", - }); - if (userTINOrError.isFailure) { - return Result.fail(userTINOrError.error); - } - - const companyNameOrError = UserName.create(userDTO.company_name); - if (companyNameOrError.isFailure) { - return Result.fail(companyNameOrError.error); - } - - const firstNameOrError = UserName.create(userDTO.first_name); - if (firstNameOrError.isFailure) { - return Result.fail(firstNameOrError.error); - } - - const lastNameOrError = UserName.create(userDTO.last_name); - if (lastNameOrError.isFailure) { - return Result.fail(lastNameOrError.error); - } - - const jobTitleOrError = UserJobTitle.create(userDTO.job_title); - if (jobTitleOrError.isFailure) { - return Result.fail(jobTitleOrError.error); - } - - const emailOrError = UserEmail.create(userDTO.email); - if (emailOrError.isFailure) { - return Result.fail(emailOrError.error); - } - - const phoneOrError = UserPhone.create(userDTO.phone); - if (phoneOrError.isFailure) { - return Result.fail(phoneOrError.error); - } - - /*const taxIdOrError = UniqueID.create(userDTO.tax_id); - if (taxIdOrError.isFailure) { - return Result.fail(taxIdOrError.error); - }*/ - - const notesOrError = Note.create(userDTO.notes); - if (notesOrError.isFailure) { - return Result.fail(notesOrError.error); - } - - // Billing address - const billingAddressOrError = this._tryCreateUserAddress( - userDTO.billing_address, - "billing", - ); - if (billingAddressOrError.isFailure) { - return Result.fail(billingAddressOrError.error); - } - - // Shipping address - const shippingAddressesOrError = this._tryCreateUserShippingAddresses( - userDTO.shipping_addresses, - ); - - if (shippingAddressesOrError.isFailure) { - return Result.fail(shippingAddressesOrError.error); - } - - return User.create( - { - tin: userTINOrError.object, - companyName: companyNameOrError.object, - firstName: firstNameOrError.object, - lastName: lastNameOrError.object, - jobTitle: jobTitleOrError.object, - email: emailOrError.object, - phone: phoneOrError.object, - //taxId: taxIdOrError.object, - notes: notesOrError.object, - - billingAddress: billingAddressOrError.object, - shippingAddresses: shippingAddressesOrError.object, - }, - userId, - ); - } - - private async _findUserTIN(tin: UserTIN) { - const userRepoBuilder = this.getRepositoryByName("User"); - return await userRepoBuilder().existsWithSameTIN(tin); - } - - private async _findUserID(id: UniqueID) { - const userRepoBuilder = this.getRepositoryByName("User"); - return await userRepoBuilder().exists(id); - } - private async _updateUser(user: User) { // Guardar el contacto const transaction = this._adapter.startTransaction(); - const userRepoBuilder = this.getRepositoryByName("User"); + const userRepository = this._getUserRepository(); + let userRepo: IUserRepository; try { await transaction.complete(async (t) => { - const userRepo = userRepoBuilder({ transaction: t }); + userRepo = userRepository({ transaction: t }); await userRepo.update(user); }); @@ -345,12 +107,43 @@ export class UpdateUserUseCase } catch (error: unknown) { const _error = error as IInfrastructureError; return Result.fail( - UseCaseError.create( - UseCaseError.REPOSITORY_ERROR, - "Error al guardar el usuario", - _error, - ), + UseCaseError.create(UseCaseError.REPOSITORY_ERROR, _error.message), ); } } + + private _tryCreateUserInstance( + userDTO: IUpdateUser_Request_DTO, + userId: UniqueID, + ): Result { + const nameOrError = Name.create(userDTO.name); + if (nameOrError.isFailure) { + return Result.fail(nameOrError.error); + } + + const emailOrError = Email.create(userDTO.email); + if (emailOrError.isFailure) { + return Result.fail(emailOrError.error); + } + + const passwordOrError = Password.createFromPlainTextPassword( + userDTO.password, + ); + if (passwordOrError.isFailure) { + return Result.fail(passwordOrError.error); + } + + return User.create( + { + name: nameOrError.object, + email: emailOrError.object, + password: passwordOrError.object, + }, + userId, + ); + } + + private _getUserRepository() { + return this._repositoryManager.getRepository("User"); + } } diff --git a/server/src/contexts/users/infrastructure/User.repository.ts b/server/src/contexts/users/infrastructure/User.repository.ts index c272c45..471e78e 100644 --- a/server/src/contexts/users/infrastructure/User.repository.ts +++ b/server/src/contexts/users/infrastructure/User.repository.ts @@ -45,7 +45,7 @@ export class UserRepository const userData = this.mapper.mapToPersistence(user); // borrando y luego creando - await this.removeById(user.id, true); + // await this.removeById(user.id, true); await this._save("User_Model", user.id, userData, {}); } diff --git a/server/src/contexts/users/infrastructure/express/controllers/createUser/CreateUser.controller.ts b/server/src/contexts/users/infrastructure/express/controllers/createUser/CreateUser.controller.ts index 6f2a331..d4d691c 100644 --- a/server/src/contexts/users/infrastructure/express/controllers/createUser/CreateUser.controller.ts +++ b/server/src/contexts/users/infrastructure/express/controllers/createUser/CreateUser.controller.ts @@ -35,7 +35,7 @@ export class CreateUserController extends ExpressController { this.context = context; } - async executeImpl(): Promise { + async executeImpl() { try { const userDTO: ICreateUser_Request_DTO = this.req.body; diff --git a/server/src/contexts/users/infrastructure/express/controllers/updateUser/UpdateUser.controller.ts b/server/src/contexts/users/infrastructure/express/controllers/updateUser/UpdateUser.controller.ts index 569d734..4aacdc9 100644 --- a/server/src/contexts/users/infrastructure/express/controllers/updateUser/UpdateUser.controller.ts +++ b/server/src/contexts/users/infrastructure/express/controllers/updateUser/UpdateUser.controller.ts @@ -39,7 +39,7 @@ export class UpdateUserController extends ExpressController { this.context = context; } - async executeImpl(): Promise { + async executeImpl() { try { const { userId } = this.req.params; const userDTO: IUpdateUser_Request_DTO = this.req.body; @@ -76,7 +76,7 @@ export class UpdateUserController extends ExpressController { }); if (result.isFailure) { - return this.handleExecuteError(result.error); + return this._handleExecuteError(result.error); } const user = result.object; @@ -89,7 +89,7 @@ export class UpdateUserController extends ExpressController { } } - private handleExecuteError(error: IUseCaseError) { + private _handleExecuteError(error: IUseCaseError) { let errorMessage: string; let infraError: IInfrastructureError; @@ -117,6 +117,16 @@ export class UpdateUserController extends ExpressController { return this.invalidInputError(errorMessage, infraError); break; + case UseCaseError.REPOSITORY_ERROR: + errorMessage = "Error updating user"; + infraError = InfrastructureError.create( + InfrastructureError.UNEXCEPTED_ERROR, + errorMessage, + error, + ); + return this.conflictError(errorMessage, infraError); + break; + case UseCaseError.UNEXCEPTED_ERROR: errorMessage = error.message; diff --git a/shared/lib/contexts/users/application/dto/UpdateUser.dto/IUpdateUser_Request.dto.ts b/shared/lib/contexts/users/application/dto/UpdateUser.dto/IUpdateUser_Request.dto.ts index 9d25999..fdc6df3 100644 --- a/shared/lib/contexts/users/application/dto/UpdateUser.dto/IUpdateUser_Request.dto.ts +++ b/shared/lib/contexts/users/application/dto/UpdateUser.dto/IUpdateUser_Request.dto.ts @@ -2,18 +2,18 @@ import Joi from "joi"; import { Result, RuleValidator } from "../../../../common"; export interface IUpdateUser_Request_DTO { - id: string; name: string; email: string; + password: string; } export function ensureUpdateUser_Request_DTOIsValid( userDTO: IUpdateUser_Request_DTO, -): Result { +) { const schema = Joi.object({ - id: Joi.string(), name: Joi.string(), email: Joi.string(), + password: Joi.string(), }).unknown(true); const result = RuleValidator.validate(