diff --git a/apps/server/src/app.ts b/apps/server/src/app.ts index 6e8f3626..2add315b 100644 --- a/apps/server/src/app.ts +++ b/apps/server/src/app.ts @@ -4,6 +4,7 @@ import dotenv from "dotenv"; import express, { Application } from "express"; import helmet from "helmet"; import responseTime from "response-time"; +import { ENV } from "./config"; import { logger } from "./lib/logger"; dotenv.config(); @@ -25,7 +26,7 @@ export function createApp(): Application { // enable CORS - Cross Origin Resource Sharing app.use( cors({ - origin: process.env.FRONTEND_URL || "http://localhost:5173", + origin: ENV.NODE_ENV === "development" ? "*" : process.env.FRONTEND_URL, methods: "GET,POST,PUT,DELETE,OPTIONS", credentials: true, diff --git a/apps/web/package.json b/apps/web/package.json index 656b9cdd..b5f415f1 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -4,7 +4,7 @@ "version": "0.0.0", "type": "module", "scripts": { - "dev": "vite --clearScreen false", + "dev": "vite --host --clearScreen false", "build": "tsc && vite build", "preview": "vite preview", "clean": "rm -rf dist && rm -rf node_modules && rm -rf .turbo", @@ -19,6 +19,7 @@ "@tailwindcss/postcss": "^4.1.5", "@tailwindcss/vite": "^4.1.6", "@tanstack/react-query-devtools": "^5.74.11", + "@types/dinero.js": "^1.9.4", "@types/node": "^22.15.12", "@types/react": "^19.1.2", "@types/react-dom": "^19.1.3", @@ -37,6 +38,7 @@ "@repo/shadcn-ui": "workspace:*", "@tanstack/react-query": "^5.74.11", "axios": "^1.9.0", + "dinero.js": "^1.9.1", "i18next": "^25.0.2", "i18next-browser-languagedetector": "^8.1.0", "react": "^19.1.0", diff --git a/apps/web/src/app.tsx b/apps/web/src/app.tsx index 48732025..afbaa3e8 100644 --- a/apps/web/src/app.tsx +++ b/apps/web/src/app.tsx @@ -9,11 +9,14 @@ import { i18n } from "@/locales"; import { AuthProvider, createAuthService } from "@erp/auth/client"; import { DataSourceProvider, createAxiosDataSource, createAxiosInstance } from "@erp/core/client"; +import DineroFactory from "dinero.js"; import "./app.css"; import { clearAccessToken, getAccessToken, setAccessToken } from "./lib"; import { AppRoutes } from "./routes"; export const App = () => { + DineroFactory.globalLocale = "es-ES"; + const queryClient = new QueryClient({ defaultOptions: { queries: { diff --git a/modules/core/package.json b/modules/core/package.json index 654276ca..acbec806 100644 --- a/modules/core/package.json +++ b/modules/core/package.json @@ -6,10 +6,14 @@ "./api": "./src/api/index.ts", "./client": "./src/web/index.ts" }, + "peerDependencies": { + "dinero.js": "^1.9.1" + }, "devDependencies": { "@biomejs/biome": "1.9.4", "@testing-library/react-hooks": "^8.0.1", "@types/axios": "^0.14.4", + "@types/dinero.js": "^1.9.4", "@types/express": "^4.17.21", "@types/jest": "29.5.14", "@types/react": "^19.1.2", diff --git a/modules/core/src/common/types/index.ts b/modules/core/src/common/types/index.ts new file mode 100644 index 00000000..b38c7d74 --- /dev/null +++ b/modules/core/src/common/types/index.ts @@ -0,0 +1 @@ +export * from "./module-metadata.d"; diff --git a/modules/core/src/common/types.ts b/modules/core/src/common/types/module-metadata.d.ts similarity index 100% rename from modules/core/src/common/types.ts rename to modules/core/src/common/types/module-metadata.d.ts diff --git a/modules/core/src/web/lib/helpers/date-func.ts b/modules/core/src/web/lib/helpers/date-func.ts new file mode 100644 index 00000000..918d6a8e --- /dev/null +++ b/modules/core/src/web/lib/helpers/date-func.ts @@ -0,0 +1,3 @@ +export const formatDate = (value: string) => { + return new Date(value).toLocaleDateString(); +}; diff --git a/modules/core/src/web/lib/helpers/index.ts b/modules/core/src/web/lib/helpers/index.ts new file mode 100644 index 00000000..7e676d89 --- /dev/null +++ b/modules/core/src/web/lib/helpers/index.ts @@ -0,0 +1,2 @@ +export * from "./date-func"; +export * from "./money-funcs"; diff --git a/modules/core/src/web/lib/helpers/money-funcs.ts b/modules/core/src/web/lib/helpers/money-funcs.ts new file mode 100644 index 00000000..b035bb7f --- /dev/null +++ b/modules/core/src/web/lib/helpers/money-funcs.ts @@ -0,0 +1,12 @@ +import DineroFactory, { Currency } from "dinero.js"; +import { MoneyDTO } from "../../../common"; + +export const formatMoney = (value: MoneyDTO) => { + const money = DineroFactory({ + amount: Number(value.amount), + currency: value.currency_code as Currency, + precision: Number(value.scale), + }); + + return money.toFormat(); +}; diff --git a/modules/core/src/web/lib/index.ts b/modules/core/src/web/lib/index.ts index bef47972..18a96399 100644 --- a/modules/core/src/web/lib/index.ts +++ b/modules/core/src/web/lib/index.ts @@ -1,2 +1,3 @@ export * from "./data-source"; +export * from "./helpers"; export * from "./modules"; diff --git a/modules/customer-invoices/package.json b/modules/customer-invoices/package.json index 0af1e0dc..7119e221 100644 --- a/modules/customer-invoices/package.json +++ b/modules/customer-invoices/package.json @@ -8,8 +8,12 @@ "./api": "./src/api/index.ts", "./client": "./src/web/manifest.ts" }, + "peerDependencies": { + "dinero.js": "^1.9.1" + }, "devDependencies": { "@biomejs/biome": "1.9.4", + "@types/dinero.js": "^1.9.4", "@types/express": "^4.17.21", "@types/react": "^19.1.2", "@types/react-dom": "^19.1.3", @@ -17,6 +21,7 @@ "typescript": "^5.8.3" }, "dependencies": { + "@ag-grid-community/locale": "34.0.0", "@erp/core": "workspace:*", "@hookform/resolvers": "^5.0.1", "@repo/rdx-criteria": "workspace:*", diff --git a/modules/customer-invoices/src/api/domain/value-objects/customer-invoice-status.ts b/modules/customer-invoices/src/api/domain/value-objects/customer-invoice-status.ts index 3ea0d979..7ade4596 100644 --- a/modules/customer-invoices/src/api/domain/value-objects/customer-invoice-status.ts +++ b/modules/customer-invoices/src/api/domain/value-objects/customer-invoice-status.ts @@ -10,17 +10,19 @@ export enum INVOICE_STATUS { DRAFT = "draft", EMITTED = "emitted", SENT = "sent", + RECEIVED = "received", REJECTED = "rejected", } export class CustomerInvoiceStatus extends ValueObject { - private static readonly ALLOWED_STATUSES = ["draft", "emitted", "sent", "rejected"]; + private static readonly ALLOWED_STATUSES = ["draft", "emitted", "sent", "received", "rejected"]; private static readonly FIELD = "invoiceStatus"; private static readonly ERROR_CODE = "INVALID_INVOICE_STATUS"; private static readonly TRANSITIONS: Record = { draft: [INVOICE_STATUS.EMITTED], emitted: [INVOICE_STATUS.SENT, INVOICE_STATUS.REJECTED, INVOICE_STATUS.DRAFT], - sent: [INVOICE_STATUS.REJECTED], + sent: [INVOICE_STATUS.RECEIVED, INVOICE_STATUS.REJECTED], + received: [], rejected: [], }; @@ -43,7 +45,9 @@ export class CustomerInvoiceStatus extends ValueObject { // Column Definitions: Defines & controls grid columns. const [colDefs] = useState([ - { field: "invoice_number" }, - { field: "invoice_series" }, + { field: "invoice_number", headerName: "Num. factura" }, + { field: "invoice_series", headerName: "Serie" }, { - field: "status", + field: "invoice_status", + filter: true, + headerName: "Estado", }, - { field: "issue_date" }, - { field: "operation_date" }, { - field: "subtotal", + field: "issue_date", + headerName: "Fecha fact.", valueFormatter: (params: ValueFormatterParams) => { - return "0 €"; - //return `£${params.value.toLocaleString()}`; + return formatDate(params.value); }, }, { - field: "total", + field: "subtotal_price", valueFormatter: (params: ValueFormatterParams) => { - return "0 €"; - //return `£${params.value.toLocaleString()}`; + const rawValue: MoneyDTO = params.value; + return formatMoney(rawValue); + }, + }, + { + field: "total_price", + valueFormatter: (params: ValueFormatterParams) => { + const rawValue: MoneyDTO = params.value; + return formatMoney(rawValue); }, }, ]); - // Apply settings across all columns - const defaultColDef = useMemo(() => { - return { - filter: true, + const gridOptions: GridOptions = { + columnDefs: colDefs, + defaultColDef: { + editable: true, + flex: 1, + minWidth: 100, + filter: false, sortable: false, - resizable: false, - }; - }, []); + resizable: true, + }, + sideBar: true, + statusBar: { + statusPanels: [ + { statusPanel: "agTotalAndFilteredRowCountComponent", align: "left" }, + { statusPanel: "agAggregationComponent" }, + ], + }, + rowGroupPanelShow: "always", + pagination: true, + paginationPageSize: 10, + paginationPageSizeSelector: [10, 20, 30, 50], + enableCharts: true, + localeText: AG_GRID_LOCALE_ES, + rowSelection: { mode: "multiRow" }, + }; // Container: Defines the grid's theme & dimensions. return ( @@ -96,13 +122,7 @@ export const CustomerInvoicesGrid = () => { width: "100%", }} > - + ); }; diff --git a/modules/customer-invoices/src/web/hooks/use-customer-invoices-query.tsx b/modules/customer-invoices/src/web/hooks/use-customer-invoices-query.tsx index 32945b28..ab32da20 100644 --- a/modules/customer-invoices/src/web/hooks/use-customer-invoices-query.tsx +++ b/modules/customer-invoices/src/web/hooks/use-customer-invoices-query.tsx @@ -1,25 +1,21 @@ -import { IListResponseDTO } from "@erp/core"; import { useDataSource, useQueryKey } from "@erp/core/client"; import { useQuery } from "@tanstack/react-query"; -import { IListCustomerInvoicesResponseDTO } from "../../common/dto"; +import { ListCustomerInvoicesResultDTO } from "../../common/dto"; // Obtener todas las facturas export const useCustomerInvoicesQuery = (params: any) => { const dataSource = useDataSource(); const keys = useQueryKey(); - return useQuery({ + return useQuery({ queryKey: keys().data().resource("customer-invoices").action("list").params(params).get(), queryFn: (context) => { console.log(dataSource.getBaseUrl()); const { signal } = context; - return dataSource.getList>( - "customer-invoices", - { - signal, - ...params, - } - ); + return dataSource.getList("customer-invoices", { + signal, + ...params, + }); }, }); }; diff --git a/packages/rdx-utils/tsconfig.json b/packages/rdx-utils/tsconfig.json index 38f86a52..a625a4d0 100644 --- a/packages/rdx-utils/tsconfig.json +++ b/packages/rdx-utils/tsconfig.json @@ -3,6 +3,6 @@ "compilerOptions": { "composite": true }, - "include": ["src"], + "include": ["src", "../../modules/core/src/web/lib/helpers/money-funcs.ts"], "exclude": ["src/**/__tests__/*"] } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2cc7b34c..75f2a7b2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -213,6 +213,9 @@ importers: axios: specifier: ^1.9.0 version: 1.10.0 + dinero.js: + specifier: ^1.9.1 + version: 1.9.1 i18next: specifier: ^25.0.2 version: 25.2.1(typescript@5.8.3) @@ -274,6 +277,9 @@ importers: '@tanstack/react-query-devtools': specifier: ^5.74.11 version: 5.81.2(@tanstack/react-query@5.81.2(react@19.1.0))(react@19.1.0) + '@types/dinero.js': + specifier: ^1.9.4 + version: 1.9.4 '@types/node': specifier: ^22.15.12 version: 22.15.32 @@ -365,6 +371,9 @@ importers: axios: specifier: ^1.9.0 version: 1.10.0 + dinero.js: + specifier: ^1.9.1 + version: 1.9.1 http-status: specifier: ^2.1.0 version: 2.1.0 @@ -393,6 +402,9 @@ importers: '@types/axios': specifier: ^0.14.4 version: 0.14.4 + '@types/dinero.js': + specifier: ^1.9.4 + version: 1.9.4 '@types/express': specifier: ^4.17.21 version: 4.17.23 @@ -417,6 +429,9 @@ importers: modules/customer-invoices: dependencies: + '@ag-grid-community/locale': + specifier: 34.0.0 + version: 34.0.0 '@erp/core': specifier: workspace:* version: link:../core @@ -450,6 +465,9 @@ importers: date-fns: specifier: ^4.1.0 version: 4.1.0 + dinero.js: + specifier: ^1.9.1 + version: 1.9.1 express: specifier: ^4.18.2 version: 4.21.2 @@ -487,6 +505,9 @@ importers: '@biomejs/biome': specifier: 1.9.4 version: 1.9.4 + '@types/dinero.js': + specifier: ^1.9.4 + version: 1.9.4 '@types/express': specifier: ^4.17.21 version: 4.17.23 @@ -860,6 +881,9 @@ packages: '@adobe/css-tools@4.3.3': resolution: {integrity: sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==} + '@ag-grid-community/locale@34.0.0': + resolution: {integrity: sha512-F3Bs6wpT4CCOgN5wmzhimQz6GK5VUznsl8+SZXv0A7bA5aw8qLuVc/yEIpqNRykQwwt0vytcHhZzVDDMuZSy1g==} + '@alloc/quick-lru@5.2.0': resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} @@ -6245,6 +6269,8 @@ snapshots: '@adobe/css-tools@4.3.3': {} + '@ag-grid-community/locale@34.0.0': {} + '@alloc/quick-lru@5.2.0': {} '@ampproject/remapping@2.3.0':