From 533b22dd983e8f3561c2cade3552add896d3a269 Mon Sep 17 00:00:00 2001 From: David Arranz Date: Fri, 12 Jul 2024 18:13:53 +0200 Subject: [PATCH] . --- client/src/app/dashboard/index.tsx | 4 +- client/src/app/quotes/edit.tsx | 10 +- .../Layout/components/UserButton.tsx | 4 +- .../src/lib/axios/createAxiosAuthActions.ts | 14 +- client/src/lib/hooks/useAuth/AuthActions.ts | 6 +- client/src/lib/hooks/useAuth/index.ts | 2 +- .../src/lib/hooks/useAuth/useGetIdentity.ts | 16 -- client/src/lib/hooks/useAuth/useGetProfile.ts | 16 ++ client/src/lib/hooks/useAuth/useLogin.tsx | 2 +- .../useLocalization/usePreferredLanguage.tsx | 4 +- .../src/lib/hooks/useQueryKey/KeyBuilder.ts | 2 +- client/src/locales/en.json | 251 ++++++++++++++++-- .../contexts/auth/domain/entities/AuthUser.ts | 5 + .../identity/presenter/Identity.presenter.ts | 4 +- .../profile/domain/entities/Profile.ts | 68 +++-- .../infrastructure/Profile.repository.ts | 2 +- .../getProfile/GetProfile.controller.ts | 14 +- .../presenter/GetProfile.presenter.ts | 28 +- .../infrastructure/mappers/profile.mapper.ts | 32 ++- .../sales/domain/entities/Dealer/Dealer.ts | 9 +- .../infrastructure/mappers/dealer.mapper.ts | 9 +- .../infrastructure/sequelize/dealer.model.ts | 7 + .../express/api/routes/auth.routes.ts | 6 +- .../application/dto/IIdentity_Response.dto.ts | 2 +- .../IGetProfile_Response.dto.ts | 22 +- 25 files changed, 424 insertions(+), 115 deletions(-) delete mode 100644 client/src/lib/hooks/useAuth/useGetIdentity.ts create mode 100644 client/src/lib/hooks/useAuth/useGetProfile.ts diff --git a/client/src/app/dashboard/index.tsx b/client/src/app/dashboard/index.tsx index 975f789..5c2c84b 100644 --- a/client/src/app/dashboard/index.tsx +++ b/client/src/app/dashboard/index.tsx @@ -10,7 +10,7 @@ import { } from "lucide-react"; import { Layout, LayoutContent, LayoutHeader } from "@/components"; -import { useGetIdentity } from "@/lib/hooks"; +import { useGetProfile } from "@/lib/hooks"; import { Badge, Button, @@ -49,7 +49,7 @@ import { useNavigate } from "react-router-dom"; export const DashboardPage = () => { const navigate = useNavigate(); - const { data: userIdentity, status } = useGetIdentity(); + const { data: userIdentity, status } = useGetProfile(); return ( diff --git a/client/src/app/quotes/edit.tsx b/client/src/app/quotes/edit.tsx index c1efbdc..3cd5854 100644 --- a/client/src/app/quotes/edit.tsx +++ b/client/src/app/quotes/edit.tsx @@ -202,14 +202,8 @@ export const QuoteEdit = () => { - + + diff --git a/client/src/components/Layout/components/UserButton.tsx b/client/src/components/Layout/components/UserButton.tsx index fe1b949..8cb7dae 100644 --- a/client/src/components/Layout/components/UserButton.tsx +++ b/client/src/components/Layout/components/UserButton.tsx @@ -1,4 +1,4 @@ -import { useCustomDialog, useGetIdentity } from "@/lib/hooks"; +import { useCustomDialog, useGetProfile } from "@/lib/hooks"; import { Button, DropdownMenu, @@ -32,7 +32,7 @@ export const UserButton = () => { navigate("/logout"); }, }); - const { data, status } = useGetIdentity(); + const { data, status } = useGetProfile(); const openUserMenu = (event: SyntheticEvent) => { event.preventDefault(); diff --git a/client/src/lib/axios/createAxiosAuthActions.ts b/client/src/lib/axios/createAxiosAuthActions.ts index 96ba693..5964d55 100644 --- a/client/src/lib/axios/createAxiosAuthActions.ts +++ b/client/src/lib/axios/createAxiosAuthActions.ts @@ -24,7 +24,7 @@ export const createAxiosAuthActions = ( return { success: true, data, - redirectTo: "/", + redirectTo: "/home", }; } catch (error) { return { @@ -61,10 +61,18 @@ export const createAxiosAuthActions = ( ); }, - getIdentity: async () => { + getProfile: async () => { + /** + * id: string; + * name: string; + * email: string; + * lang_code: string; + * roles: string[]; + */ + try { const result = await httpClient.request({ - url: `${apiUrl}/auth/identity`, + url: `${apiUrl}/profile`, method: "GET", }); diff --git a/client/src/lib/hooks/useAuth/AuthActions.ts b/client/src/lib/hooks/useAuth/AuthActions.ts index 142d648..6220c7a 100644 --- a/client/src/lib/hooks/useAuth/AuthActions.ts +++ b/client/src/lib/hooks/useAuth/AuthActions.ts @@ -1,4 +1,4 @@ -import { IIdentity_Response_DTO } from "@shared/contexts"; +import { IGetProfileResponse_DTO } from "@shared/contexts"; export type SuccessNotificationResponse = { message: string; @@ -7,7 +7,7 @@ export type SuccessNotificationResponse = { export type PermissionResponse = unknown; -export type IdentityResponse = IIdentity_Response_DTO | null; +export type ProfileResponse = IGetProfileResponse_DTO | null; export type AuthActionCheckResponse = { authenticated: boolean; @@ -39,5 +39,5 @@ export interface IAuthActions { forgotPassword?: (params: unknown) => Promise; updatePassword?: (params: unknown) => Promise; getPermissions?: (params?: Record) => Promise; - getIdentity?: (params?: unknown) => Promise; + getProfile?: (params?: unknown) => Promise; } diff --git a/client/src/lib/hooks/useAuth/index.ts b/client/src/lib/hooks/useAuth/index.ts index 121c4d7..8ab4565 100644 --- a/client/src/lib/hooks/useAuth/index.ts +++ b/client/src/lib/hooks/useAuth/index.ts @@ -1,6 +1,6 @@ export * from "./AuthActions"; export * from "./AuthContext"; export * from "./useAuth"; -export * from "./useGetIdentity"; +export * from "./useGetProfile"; export * from "./useIsLoggedIn"; export * from "./useLogin"; diff --git a/client/src/lib/hooks/useAuth/useGetIdentity.ts b/client/src/lib/hooks/useAuth/useGetIdentity.ts deleted file mode 100644 index f8fa29c..0000000 --- a/client/src/lib/hooks/useAuth/useGetIdentity.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { IdentityResponse, useAuth } from "@/lib/hooks"; -import { UseQueryOptions, useQuery } from "@tanstack/react-query"; -import { useQueryKey } from "../useQueryKey"; - -export const useGetIdentity = (queryOptions?: UseQueryOptions) => { - const keys = useQueryKey(); - const { getIdentity } = useAuth(); - - const result = useQuery({ - queryKey: keys().auth().action("identity").get(), - queryFn: getIdentity, - ...queryOptions, - }); - - return result; -}; diff --git a/client/src/lib/hooks/useAuth/useGetProfile.ts b/client/src/lib/hooks/useAuth/useGetProfile.ts new file mode 100644 index 0000000..c320b89 --- /dev/null +++ b/client/src/lib/hooks/useAuth/useGetProfile.ts @@ -0,0 +1,16 @@ +import { ProfileResponse, useAuth } from "@/lib/hooks"; +import { UseQueryOptions, useQuery } from "@tanstack/react-query"; +import { useQueryKey } from "../useQueryKey"; + +export const useGetProfile = (queryOptions?: UseQueryOptions) => { + const keys = useQueryKey(); + const { getProfile } = useAuth(); + + const result = useQuery({ + queryKey: keys().auth().action("profile").get(), + queryFn: getProfile, + ...queryOptions, + }); + + return result; +}; diff --git a/client/src/lib/hooks/useAuth/useLogin.tsx b/client/src/lib/hooks/useAuth/useLogin.tsx index c480dc4..c51a226 100644 --- a/client/src/lib/hooks/useAuth/useLogin.tsx +++ b/client/src/lib/hooks/useAuth/useLogin.tsx @@ -17,7 +17,7 @@ export const useLogin = (params?: UseMutationOptions { const { success, redirectTo } = data; if (success && redirectTo) { - navigate(redirectTo || "/", { replace: true }); + navigate(redirectTo || "/home", { replace: false }); } if (onSuccess) { onSuccess(data, variables, context); diff --git a/client/src/lib/hooks/useLocalization/usePreferredLanguage.tsx b/client/src/lib/hooks/useLocalization/usePreferredLanguage.tsx index b87b669..f30d62c 100644 --- a/client/src/lib/hooks/useLocalization/usePreferredLanguage.tsx +++ b/client/src/lib/hooks/useLocalization/usePreferredLanguage.tsx @@ -1,7 +1,7 @@ -import { useGetIdentity } from "../useAuth"; +import { useGetProfile } from "../useAuth"; export const usePreferredLanguage = () => { - const { data } = useGetIdentity(); + const { data } = useGetProfile(); if (!data || !data.language) { return navigator.languages && navigator.languages.length diff --git a/client/src/lib/hooks/useQueryKey/KeyBuilder.ts b/client/src/lib/hooks/useQueryKey/KeyBuilder.ts index ce784a6..6152614 100644 --- a/client/src/lib/hooks/useQueryKey/KeyBuilder.ts +++ b/client/src/lib/hooks/useQueryKey/KeyBuilder.ts @@ -16,7 +16,7 @@ type DataMutationActions = type AuthActionType = | "login" | "logout" - | "identity" + | "profile" | "register" | "forgotPassword" | "check" diff --git a/client/src/locales/en.json b/client/src/locales/en.json index 80fcd4e..ef370bc 100644 --- a/client/src/locales/en.json +++ b/client/src/locales/en.json @@ -4,36 +4,243 @@ "cancel": "Cancel", "no": "No", "yes": "Yes", - "Accept": "Accept" + "save": "Save", + "accept": "OK", + "hide": "Ocultar", + "back": "Back", + "upload": "Upload", + "continue": "Continue", + "sort_asc": "Asc", + "sort_asc_description": "En order ascendente. Click para ordenar descendentemente.", + "sort_desc": "Desc", + "sort_desc_description": "En orden descendente. Click para ordenar ascendentemente.", + "sort_none_description": "Sin orden. Click para ordenar ascendentemente.", + "rows_selected": "{{count}} de {{total}} fila(s) seleccionadas.", + "rows_per_page": "Filas por página", + "num_page_of_total": "Página {{count}} de {{total}}", + "go_to_first_page": "Ir a la primera página", + "go_to_prev_page": "Ir a la página anterior", + "go_to_next_page": "Ir a la página siguiente", + "go_to_last_page": "Ir a la última página", + "filter_placeholder": "Escribe aquí para filtrar...", + "reset_filter": "Quitar el filtro", + "error": "Error", + "actions": "Acciones", + "open_menu": "Abrir el menú", + "duplicate_rows": "Duplicar", + "duplicate_rows_tooltip": "Duplica las fila(s) seleccionadas(s)", + "pick_date": "Elige una fecha", + "required_field": "Este campo es obligatorio", + "unsaved_changes_prompt": "Los últimos cambios no se han guardado. Si continúas, se perderán", + "edit": "Editar" }, "main_menu": { - "home": "Home", - "settings": "Settings", - "dealers": "Dealers", - "catalog": "Catalog", - "quotes": "Quotes", - "search_placeholder": "Search product, quotes, etc...", + "home": "Inicio", + "settings": "Ajustes", + "dealers": "Distribuidores", + "catalog": "Catálogo", + "quotes": "Cotizaciones", + "search_placeholder": "Buscar productos, cotizaciones, etc...", "user": { - "user_menu": "User menu", - "my_account": "My account", - "profile": "Profile", - "settings": "Settings", - "support": "Support", - "logout": "Logout" + "user_menu": "Menú del usuario", + "my_account": "Mi cuenta", + "profile": "Perfil", + "settings": "Ajustes", + "support": "Soporte", + "logout": "Salir" }, "logout": {} }, "login_page": { - "title": "Uecko Quotes", - "description": "Enter your email address and password to login", + "title": "Presupuestador para distribuidores", + "description": "Introduzca su dirección de correo electrónico y contraseña para acceder", "email_label": "Email", - "email_placeholder": "user@sample.com", - "password_label": "Password", - "forgotten_password": "Forgot your password?", - "become_dealer": "Do you want to become a Uecko dealer?", - "contact_us": "Contact us", - "login": "Login", - "error": "Error" + "email_placeholder": "micorreo@ejemplo.com", + "password_label": "Contraseña", + "forgotten_password": "¿Has olvidado tu contraseña?", + "become_dealer": "¿Quieres ser distribuidor de Uecko?", + "contact_us": "Contacta con nosotros", + "login": "Entrar" + }, + "dashboard": { + "welcome": "Bienvenido" + }, + "catalog": { + "list": { + "title": "Catálogo de artículos", + "columns": { + "description": "Descripción", + "points": "Puntos", + "retail_price": "PVP" + } + } + }, + "quotes": { + "list": { + "title": "Quotes", + "subtitle": "", + "tabs": { + "all": "All", + "draft": "Draft", + "archived": "Archive" + }, + "columns": { + "date": "Date", + "reference": "Reference", + "status": "Status", + "customer_information": "Customer", + "total_price": "Imp. total" + } + }, + "create": { + "title": "New quote", + "buttons": { + "save_quote": "Guardar cotización", + "discard": "Descartar" + }, + "tabs": { + "general": "Datos generales", + "items": "Contenido", + "documents": "Documentos", + "history": "Historial" + }, + "form_groups": { + "general": { + "title": "Datos generales", + "desc": "Datos generales y cliente al que va la cotización" + }, + "status": { + "title": "Estado", + "desc": "Estado de la cotización" + }, + "items": { + "title": "Contenido de la cotización", + "desc": "Líneas de detalle de la cotización. Ayúdese del catálogo para rellenar más fácilmente el contenido." + }, + "documents": { + "title": "Documentos", + "desc": "Añada adjuntar con su cotización documentos como fotos, planos, croquis, etc." + }, + "history": { + "title": "", + "desc": "" + } + }, + "edit": { + "title": "Cotización" + } + }, + "edit": { + "title": "Cotización" + }, + "status": { + "draft": "Borrador" + }, + "form_fields": { + "date": { + "label": "Fecha", + "desc": "Fecha de esta cotización", + "placeholder": "" + }, + "reference": { + "label": "Referencia", + "desc": "Referencia para esta cotización", + "placeholder": "" + }, + "lang_code": { + "label": "Idioma", + "desc": "Idioma de la cotización", + "placeholder": "" + }, + "currency_code": { + "label": "Moneda", + "desc": "Moneda de la cotización", + "placeholder": "" + }, + "customer_information": { + "label": "Datos del cliente", + "desc": "Escriba el nombre del cliente en la primera línea, la direccion en la segunda y el código postal y ciudad en la tercera.", + "placeholder": "Nombre y apellidos\nCalle y número\nCódigo postal y ciudad..." + }, + "payment_method": { + "label": "Forma de pago", + "placeholder": "placeholder", + "desc": "desc" + }, + "notes": { + "label": "Notas", + "placeholder": "", + "desc": "desc" + }, + "validity": { + "label": "Validez de la cotización", + "placeholder": "", + "desc": "desc" + }, + "items": { + "quantity": { + "label": "Cantidad", + "placeholder": "", + "desc": "" + }, + "description": { + "label": "Descripción", + "placeholder": "", + "desc": "" + }, + "unit_price": { + "label": "Imp. unitario", + "placeholder": "", + "desc": "Importe unitario del artículo" + }, + "subtotal_price": { + "label": "Subtotal", + "placeholder": "", + "desc": "" + }, + "discount": { + "label": "Dto (%)", + "placeholder": "", + "desc": "Porcentaje de descuento" + }, + "total_price": { + "label": "Imp. total", + "placeholder": "", + "desc": "Importe total con el descuento ya aplicado" + } + } + } + }, + "settings": { + "title": "Ajustes", + "quotes": { + "title": "Cotizaciones", + "contact_information": { + "label": "Información de contacto", + "placeholder": "placeholder", + "desc": "Información de contacto" + }, + "default_payment_method": { + "label": "Forma de pago", + "placeholder": "placeholder", + "desc": "desc" + }, + "default_notes": { + "label": "Notas", + "placeholder": "", + "desc": "desc" + }, + "default_legal_terms": { + "label": "Cláusulas legales", + "placeholder": "", + "desc": "desc" + }, + "default_quote_validity": { + "label": "Validez por defecto", + "placeholder": "", + "desc": "" + } + } } } } diff --git a/server/src/contexts/auth/domain/entities/AuthUser.ts b/server/src/contexts/auth/domain/entities/AuthUser.ts index 5eb42ec..729a0ac 100644 --- a/server/src/contexts/auth/domain/entities/AuthUser.ts +++ b/server/src/contexts/auth/domain/entities/AuthUser.ts @@ -27,6 +27,7 @@ export interface IAuthUser { isUser: boolean; isAdmin: boolean; getRoles: () => AuthUserRole[]; + getRolesArray: () => string[]; verifyPassword: (candidatePassword: string) => boolean; } @@ -77,6 +78,10 @@ export class AuthUser extends AggregateRoot implements IAuthUser return this.roles; } + public getRolesArray(): string[] { + return this.getRoles()?.map((rol) => rol.toString()); + } + public verifyPassword(candidatePassword: string): boolean { return this.props.password.verifyPassword(candidatePassword); } diff --git a/server/src/contexts/auth/infrastructure/express/controllers/identity/presenter/Identity.presenter.ts b/server/src/contexts/auth/infrastructure/express/controllers/identity/presenter/Identity.presenter.ts index 7c5b64a..8921c85 100644 --- a/server/src/contexts/auth/infrastructure/express/controllers/identity/presenter/Identity.presenter.ts +++ b/server/src/contexts/auth/infrastructure/express/controllers/identity/presenter/Identity.presenter.ts @@ -15,8 +15,8 @@ export const identityPresenter: IIdentityPresenter = { id: user.id.toString(), name: user.name.toString(), email: user.email.toString(), - language: user.language.toString(), - roles: user.getRoles()?.map((rol) => rol.toString()), + lang_code: user.language.toString(), + roles: user.getRolesArray(), }; }, }; diff --git a/server/src/contexts/profile/domain/entities/Profile.ts b/server/src/contexts/profile/domain/entities/Profile.ts index 55ce5d0..4738fe2 100644 --- a/server/src/contexts/profile/domain/entities/Profile.ts +++ b/server/src/contexts/profile/domain/entities/Profile.ts @@ -1,20 +1,40 @@ -import { AggregateRoot, IDomainError, Result, UniqueID } from "@shared/contexts"; +import { DealerStatus } from "@/contexts/sales/domain"; +import { + AggregateRoot, + CurrencyData, + IDomainError, + Language, + Name, + Note, + Result, + UniqueID, +} from "@shared/contexts"; export interface IProfileProps { - contactInformation: string; - defaultPaymentMethod: string; - defaultNotes: string; - defaultLegalTerms: string; - defaultQuoteValidity: string; + name: Name; + language: Language; + status: DealerStatus; + currency: CurrencyData; + + contactInformation: Note; + defaultPaymentMethod: Note; + defaultNotes: Note; + defaultLegalTerms: Note; + defaultQuoteValidity: Note; } export interface IProfile { id: UniqueID; - contactInformation: string; - defaultPaymentMethod: string; - defaultNotes: string; - defaultLegalTerms: string; - defaultQuoteValidity: string; + name: Name; + language: Language; + status: DealerStatus; + currency: CurrencyData; + + contactInformation: Note; + defaultPaymentMethod: Note; + defaultNotes: Note; + defaultLegalTerms: Note; + defaultQuoteValidity: Note; } export class Profile extends AggregateRoot implements IProfile { @@ -23,23 +43,39 @@ export class Profile extends AggregateRoot implements IProfile { return Result.ok(profile); } - get contactInformation(): string { + get name(): Name { + return this.props.name; + } + + get language(): Language { + return this.props.language; + } + + get status(): DealerStatus { + return this.props.status; + } + + get currency(): CurrencyData { + return this.props.currency; + } + + get contactInformation(): Note { return this.props.contactInformation; } - get defaultPaymentMethod(): string { + get defaultPaymentMethod(): Note { return this.props.defaultPaymentMethod; } - get defaultNotes(): string { + get defaultNotes(): Note { return this.props.defaultNotes; } - get defaultLegalTerms(): string { + get defaultLegalTerms(): Note { return this.props.defaultLegalTerms; } - get defaultQuoteValidity(): string { + get defaultQuoteValidity(): Note { return this.props.defaultQuoteValidity; } } diff --git a/server/src/contexts/profile/infrastructure/Profile.repository.ts b/server/src/contexts/profile/infrastructure/Profile.repository.ts index e127432..3d83409 100644 --- a/server/src/contexts/profile/infrastructure/Profile.repository.ts +++ b/server/src/contexts/profile/infrastructure/Profile.repository.ts @@ -41,7 +41,7 @@ export class ProfileRepository extends SequelizeRepository implements I } public async getByUserId(userId: UniqueID): Promise { - const rawDealer: any = await this._getBy("Profile_Model", "user_id", userId.toPrimitive()); + const rawDealer: any = await this._getBy("Dealer_Model", "user_id", userId.toPrimitive()); if (!rawDealer === true) { return null; diff --git a/server/src/contexts/profile/infrastructure/express/controllers/getProfile/GetProfile.controller.ts b/server/src/contexts/profile/infrastructure/express/controllers/getProfile/GetProfile.controller.ts index 437ded5..9eef328 100644 --- a/server/src/contexts/profile/infrastructure/express/controllers/getProfile/GetProfile.controller.ts +++ b/server/src/contexts/profile/infrastructure/express/controllers/getProfile/GetProfile.controller.ts @@ -1,8 +1,8 @@ import { IUseCaseError, UseCaseError } from "@/contexts/common/application/useCases"; import { ExpressController } from "@/contexts/common/infrastructure/express"; -import { User } from "@/contexts/users/domain/entities/User"; import { IGetProfileResponse_DTO } from "@shared/contexts"; +import { AuthUser } from "@/contexts/auth/domain"; import { IServerError } from "@/contexts/common/domain/errors"; import { IInfrastructureError, InfrastructureError } from "@/contexts/common/infrastructure"; import { GetProfileUseCase } from "@/contexts/profile/application/GetProfile.useCase"; @@ -30,7 +30,7 @@ export class GetProfileController extends ExpressController { } async executeImpl(): Promise { - const user = this.req.user; + const user = this.req.user; if (!user) { const errorMessage = "Unexpected missing user data"; @@ -42,17 +42,17 @@ export class GetProfileController extends ExpressController { } try { - const result = await this.useCase.execute({ + const profileOrError = await this.useCase.execute({ userId: user.id, }); - if (result.isFailure) { - return this._handleExecuteError(result.error); + if (profileOrError.isFailure) { + return this._handleExecuteError(profileOrError.error); } - const profile = result.object; + const profile = profileOrError.object; - return this.ok(this.presenter.map(profile, this.context)); + return this.ok(this.presenter.map(profile, user, this.context)); } catch (e: unknown) { return this.fail(e as IServerError); } diff --git a/server/src/contexts/profile/infrastructure/express/controllers/getProfile/presenter/GetProfile.presenter.ts b/server/src/contexts/profile/infrastructure/express/controllers/getProfile/presenter/GetProfile.presenter.ts index 73d5fb3..c058a05 100644 --- a/server/src/contexts/profile/infrastructure/express/controllers/getProfile/presenter/GetProfile.presenter.ts +++ b/server/src/contexts/profile/infrastructure/express/controllers/getProfile/presenter/GetProfile.presenter.ts @@ -1,20 +1,32 @@ +import { AuthUser } from "@/contexts/auth/domain"; import { Profile } from "@/contexts/profile/domain"; import { IProfileContext } from "@/contexts/profile/infrastructure/Profile.context"; import { IGetProfileResponse_DTO } from "@shared/contexts"; export interface IGetProfilePresenter { - map: (profile: Profile, context: IProfileContext) => IGetProfileResponse_DTO; + map: (profile: Profile, user: AuthUser, context: IProfileContext) => IGetProfileResponse_DTO; } export const GetProfilePresenter: IGetProfilePresenter = { - map: (profile: Profile, context: IProfileContext): IGetProfileResponse_DTO => { + map: (profile: Profile, user: AuthUser, context: IProfileContext): IGetProfileResponse_DTO => { return { - dealer_id: profile.id.toString(), - contact_information: profile.contactInformation, - default_payment_method: profile.defaultPaymentMethod, - default_notes: profile.defaultNotes, - default_legal_terms: profile.defaultLegalTerms, - default_quote_validity: profile.defaultQuoteValidity, + name: user.name.toString(), + email: user.email.toString(), + lang_code: user.language.code, + roles: user.getRolesArray(), + dealer: { + id: profile.id.toString(), + name: profile.name.toString(), + status: profile.status.toString(), + lang_code: profile.language.toString(), + currency_code: profile.currency.toString(), + + contact_information: profile.contactInformation.toString(), + default_payment_method: profile.defaultPaymentMethod.toString(), + default_notes: profile.defaultNotes.toString(), + default_legal_terms: profile.defaultLegalTerms.toString(), + default_quote_validity: profile.defaultQuoteValidity.toString(), + }, }; }, }; diff --git a/server/src/contexts/profile/infrastructure/mappers/profile.mapper.ts b/server/src/contexts/profile/infrastructure/mappers/profile.mapper.ts index 50a37b0..ee817b1 100644 --- a/server/src/contexts/profile/infrastructure/mappers/profile.mapper.ts +++ b/server/src/contexts/profile/infrastructure/mappers/profile.mapper.ts @@ -3,7 +3,9 @@ import { MapperParamsType, SequelizeMapper, } from "@/contexts/common/infrastructure"; -import { UniqueID } from "@shared/contexts"; +import { DealerStatus } from "@/contexts/sales/domain"; +import { Dealer_Model } from "@/contexts/sales/infrastructure/sequelize"; +import { CurrencyData, Language, Name, Note, UniqueID } from "@shared/contexts"; import { IProfileProps, Profile } from "../../domain"; import { IProfileContext } from "../Profile.context"; import { ProfileCreationAttributes, Profile_Model } from "../sequelize"; @@ -19,13 +21,29 @@ class ProfileMapper super(props); } - protected toDomainMappingImpl(source: Profile_Model, params: any): Profile { + protected toDomainMappingImpl(source: Dealer_Model, params: any): Profile { + const name = this.mapsValue(source, "name", Name.create); + const status = this.mapsValue(source, "status", DealerStatus.create); + const language = this.mapsValue(source, "lang_code", Language.createFromCode); + const currency = this.mapsValue(source, "currency_code", CurrencyData.createFromCode); + + const contactInformation = this.mapsValue(source, "contact_information", Note.create); + const defaultPaymentMethod = this.mapsValue(source, "default_payment_method", Note.create); + const defaultNotes = this.mapsValue(source, "default_notes", Note.create); + const defaultLegalTerms = this.mapsValue(source, "default_legal_terms", Note.create); + const defaultQuoteValidity = this.mapsValue(source, "default_quote_validity", Note.create); + const props: IProfileProps = { - contactInformation: source.contact_information, - defaultPaymentMethod: source.default_payment_method, - defaultNotes: source.default_notes, - defaultLegalTerms: source.default_legal_terms, - defaultQuoteValidity: source.default_quote_validity, + name, + status, + language, + currency, + + contactInformation, + defaultPaymentMethod, + defaultNotes, + defaultLegalTerms, + defaultQuoteValidity, }; const id = this.mapsValue(source, "id", UniqueID.create); diff --git a/server/src/contexts/sales/domain/entities/Dealer/Dealer.ts b/server/src/contexts/sales/domain/entities/Dealer/Dealer.ts index ebe2d89..8e8d35f 100644 --- a/server/src/contexts/sales/domain/entities/Dealer/Dealer.ts +++ b/server/src/contexts/sales/domain/entities/Dealer/Dealer.ts @@ -1,5 +1,6 @@ import { AggregateRoot, + CurrencyData, IDomainError, KeyValueMap, Language, @@ -12,10 +13,11 @@ import { DealerStatus } from "./DealerStatus"; export interface IDealerProps { user_id: UniqueID; name: Name; - logo: string; + //logo: string; language: Language; additionalInfo: KeyValueMap; status: DealerStatus; + currency: CurrencyData; } export interface IDealer { @@ -26,6 +28,7 @@ export interface IDealer { additionalInfo: KeyValueMap; status: DealerStatus; + currency: CurrencyData; } export class Dealer extends AggregateRoot implements IDealer { @@ -53,4 +56,8 @@ export class Dealer extends AggregateRoot implements IDealer { get additionalInfo(): KeyValueMap { return this.props.additionalInfo; } + + get currency(): CurrencyData { + return this.props.currency; + } } diff --git a/server/src/contexts/sales/infrastructure/mappers/dealer.mapper.ts b/server/src/contexts/sales/infrastructure/mappers/dealer.mapper.ts index 864ed3e..cfaf407 100644 --- a/server/src/contexts/sales/infrastructure/mappers/dealer.mapper.ts +++ b/server/src/contexts/sales/infrastructure/mappers/dealer.mapper.ts @@ -3,7 +3,7 @@ import { MapperParamsType, SequelizeMapper, } from "@/contexts/common/infrastructure"; -import { KeyValueMap, Language, Name, UniqueID } from "@shared/contexts"; +import { CurrencyData, KeyValueMap, Language, Name, UniqueID } from "@shared/contexts"; import { Dealer, DealerStatus, IDealerProps } from "../../domain/entities"; import { ISalesContext } from "../Sales.context"; import { DealerCreationAttributes, Dealer_Model } from "../sequelize"; @@ -24,6 +24,7 @@ class DealerMapper const user_id = this.mapsValue(source, "user_id", UniqueID.create); const status = this.mapsValue(source, "status", DealerStatus.create); const language = this.mapsValue(source, "lang_code", Language.createFromCode); + const currency = this.mapsValue(source, "currency_code", CurrencyData.createFromCode); const additionalInfoOrError = KeyValueMap.create([ ["contact_information", source.contact_information], @@ -35,10 +36,11 @@ class DealerMapper const props: IDealerProps = { user_id, - logo: "", + //logo: "", name, status, language, + currency, additionalInfo: additionalInfoOrError.object, }; @@ -57,7 +59,8 @@ class DealerMapper id: source.id.toPrimitive(), user_id: source.user_id.toPrimitive(), //contact_id: undefined, - logo: "", + currency_code: source.currency.toPrimitive(), + //logo: "", name: source.name.toPrimitive(), status: source.status.toPrimitive(), lang_code: source.language.toPrimitive(), diff --git a/server/src/contexts/sales/infrastructure/sequelize/dealer.model.ts b/server/src/contexts/sales/infrastructure/sequelize/dealer.model.ts index f8a7bcf..c663b2a 100644 --- a/server/src/contexts/sales/infrastructure/sequelize/dealer.model.ts +++ b/server/src/contexts/sales/infrastructure/sequelize/dealer.model.ts @@ -55,6 +55,7 @@ export class Dealer_Model extends Model< declare default_quote_validity: CreationOptional; declare status: CreationOptional; declare lang_code: CreationOptional; + declare currency_code: CreationOptional; declare user: NonAttribute; declare quotes: NonAttribute; @@ -90,6 +91,12 @@ export default (sequelize: Sequelize) => { defaultValue: "es", }, + currency_code: { + type: new DataTypes.STRING(3), + allowNull: false, + defaultValue: "EUR", + }, + status: { type: DataTypes.STRING, allowNull: false, diff --git a/server/src/infrastructure/express/api/routes/auth.routes.ts b/server/src/infrastructure/express/api/routes/auth.routes.ts index 1ef95ba..dce4eda 100644 --- a/server/src/infrastructure/express/api/routes/auth.routes.ts +++ b/server/src/infrastructure/express/api/routes/auth.routes.ts @@ -1,5 +1,4 @@ import { checkUser, createLoginController } from "@/contexts/auth"; -import { createIdentityController } from "@/contexts/auth/infrastructure/express/controllers/identity"; import Express from "express"; import passport from "passport"; @@ -27,12 +26,15 @@ export const authRouter = (appRouter: Express.Router) => { authRoutes.post("/register"); + /* + -> Sustituido por /profile + authRoutes.get( "/identity", checkUser, (req: Express.Request, res: Express.Response, next: Express.NextFunction) => createIdentityController(res.locals["context"]).execute(req, res, next) - ); + );*/ appRouter.use("/auth", authRoutes); }; diff --git a/shared/lib/contexts/auth/application/dto/IIdentity_Response.dto.ts b/shared/lib/contexts/auth/application/dto/IIdentity_Response.dto.ts index cf69779..9816e29 100644 --- a/shared/lib/contexts/auth/application/dto/IIdentity_Response.dto.ts +++ b/shared/lib/contexts/auth/application/dto/IIdentity_Response.dto.ts @@ -2,6 +2,6 @@ export interface IIdentity_Response_DTO { id: string; name: string; email: string; - language: string; + lang_code: string; roles: string[]; } diff --git a/shared/lib/contexts/profile/application/dto/GetProfile.dto/IGetProfile_Response.dto.ts b/shared/lib/contexts/profile/application/dto/GetProfile.dto/IGetProfile_Response.dto.ts index 5a03850..5679fbf 100644 --- a/shared/lib/contexts/profile/application/dto/GetProfile.dto/IGetProfile_Response.dto.ts +++ b/shared/lib/contexts/profile/application/dto/GetProfile.dto/IGetProfile_Response.dto.ts @@ -1,8 +1,18 @@ export interface IGetProfileResponse_DTO { - dealer_id: string; - contact_information: string; - default_payment_method: string; - default_notes: string; - default_legal_terms: string; - default_quote_validity: string; + name: string; + email: string; + lang_code: string; + roles: string[]; + dealer: { + id: string; + name: string; + contact_information: string; + default_payment_method: string; + default_notes: string; + default_legal_terms: string; + default_quote_validity: string; + status: string; + lang_code: string; + currency_code: string; + }; }