From 3846199cbe03ba7c476585fccc6e25c1bbc58776 Mon Sep 17 00:00:00 2001 From: david Date: Wed, 24 Sep 2025 19:30:35 +0200 Subject: [PATCH] Clientes y facturas de cliente --- apps/server/package.json | 2 +- apps/server/src/index.ts | 2 +- apps/server/src/lib/modules/module-loader.ts | 10 +- apps/server/src/register-modules.ts | 4 +- modules/core/package.json | 3 +- .../core/src/api/domain/value-objects/tax.ts | 2 +- .../validate-request.middleware.ts | 4 +- .../core/src/common/dto/amount-money.dto.ts | 2 +- modules/core/src/common/dto/base.schemas.ts | 2 +- modules/core/src/common/dto/critera.dto.ts | 2 +- .../src/common/dto/list-view.response.dto.ts | 2 +- modules/core/src/common/dto/metadata.dto.ts | 2 +- modules/core/src/common/dto/percentage.dto.ts | 2 +- modules/core/src/common/dto/quantity.dto.ts | 2 +- modules/core/src/web/hooks/index.ts | 1 + .../core/src/web/hooks/use-hook-form/index.ts | 1 + .../web/hooks/use-hook-form/use-hook-form.ts | 44 +++++ modules/customer-invoices/package.json | 2 +- .../customer-invoice-item-description.ts | 2 +- .../value-objects/customer-invoice-number.ts | 2 +- .../value-objects/customer-invoice-serie.ts | 2 +- modules/customer-invoices/src/api/index.ts | 26 ++- .../src/api/infrastructure/dependencies.ts | 6 +- .../create-customer-invoice.request.dto.ts | 2 +- .../customer-invoices-list.request.dto.ts | 2 +- ...lete-customer-invoice-by-id.request.dto.ts | 2 +- .../get-customer-invoice-by-id.request.dto.ts | 2 +- ...port-customer-invoice-by-id.request.dto.ts | 2 +- ...date-customer-invoice-by-id.request.dto.ts | 2 +- .../create-customer-invoice.response.dto.ts | 2 +- ...get-customer-invoice-by-id.response.dto.ts | 2 +- .../list-customer-invoices.response.dto.ts | 2 +- ...ate-customer-invoice-by-id.response.dto.ts | 2 +- .../customer-invoices/src/web/hooks/index.ts | 1 + .../web/hooks/use-customer-invoice-query.ts | 49 ++++++ .../pages/create/customer-invoice.schema.ts | 2 +- .../pages/update/customer-invoices-update.tsx | 152 ++++++++++++++++++ .../schemas/customer-invoices.api.schema.ts | 13 +- .../schemas/customer-invoices.form.schema.ts | 8 + modules/customers/package.json | 2 +- .../domain/value-objects/customer-number.ts | 2 +- .../domain/value-objects/customer-serie.ts | 2 +- .../express/customers.routes.ts | 3 +- .../request/create-customer.request.dto.ts | 2 +- .../dto/request/customer-list.request.dto.ts | 2 +- .../delete-customer-by-id.request.dto.ts | 2 +- .../request/get-customer-by-id.request.dto.ts | 2 +- .../update-customer-by-id.request.dto.ts | 2 +- .../response/create-customer.result.dto.ts | 2 +- .../get-customer-by-id.response.dto.ts | 2 +- .../response/list-customers.response.dto.ts | 2 +- .../update-customer-by-id.response.dto.ts | 2 +- modules/customers/src/web/hooks/index.ts | 1 - .../web/hooks/use-create-customer-mutation.ts | 2 +- .../src/web/hooks/use-customer-form.ts | 36 ----- .../src/web/hooks/use-customer-query.ts | 7 +- .../web/hooks/use-update-customer-mutation.ts | 2 +- .../src/web/pages/create/customer-create.tsx | 12 +- .../src/web/pages/update/customer-update.tsx | 17 +- .../src/web/schemas/customer.api.schema.ts | 2 +- .../src/web/schemas/customer.form.schema.ts | 2 +- modules/verifactu/package.json | 12 +- .../application/presenters/domain/index.ts | 2 + .../domain/verifactu-record.full.presenter.ts | 24 +++ .../use-cases/send/send-invoice.use-case.ts | 33 +++- .../value-objects/verifactu-record-url.ts | 2 +- .../services/verifactu-record.service.ts | 23 --- modules/verifactu/src/api/index.ts | 4 +- .../src/api/infrastructure/dependencies.ts | 125 ++++---------- .../send-invoice-verifactu.controller.ts | 2 - .../express/verifactu.routes.ts | 16 +- .../infrastructure/mappers/domain/index.ts | 1 + .../mappers/domain/verifactu-record.mapper.ts | 1 - .../src/api/infrastructure/mappers/index.ts | 2 + ...get-verifactu-record-by-id.response.dto.ts | 74 +++++++++ .../verifactu/src/common/dto/request/index.ts | 3 +- ...send-customer-invoice-by-id.request.dto.ts | 9 -- .../request/send-invoice-by-id.request.dto.ts | 7 + packages/rdx-ddd/package.json | 2 +- packages/rdx-ddd/src/value-objects/city.ts | 2 +- packages/rdx-ddd/src/value-objects/country.ts | 2 +- .../src/value-objects/currency-code.ts | 2 +- .../src/value-objects/email-address.ts | 2 +- .../src/value-objects/language-code.ts | 2 +- packages/rdx-ddd/src/value-objects/name.ts | 2 +- .../rdx-ddd/src/value-objects/percentage.ts | 2 +- .../rdx-ddd/src/value-objects/phone-number.ts | 2 +- .../rdx-ddd/src/value-objects/postal-code.ts | 2 +- .../rdx-ddd/src/value-objects/province.ts | 2 +- .../rdx-ddd/src/value-objects/quantity.ts | 2 +- packages/rdx-ddd/src/value-objects/slug.ts | 2 +- packages/rdx-ddd/src/value-objects/street.ts | 2 +- .../rdx-ddd/src/value-objects/tax-code.ts | 2 +- .../rdx-ddd/src/value-objects/text-value.ts | 2 +- .../rdx-ddd/src/value-objects/tin-number.ts | 2 +- .../rdx-ddd/src/value-objects/unique-id.ts | 2 +- .../rdx-ddd/src/value-objects/url-address.ts | 2 +- .../rdx-ddd/src/value-objects/utc-date.ts | 2 +- packages/rdx-ui/package.json | 4 +- .../src/components/layout/data-table.tsx | 2 +- pnpm-lock.yaml | 45 ++++-- 101 files changed, 623 insertions(+), 288 deletions(-) create mode 100644 modules/core/src/web/hooks/use-hook-form/index.ts create mode 100644 modules/core/src/web/hooks/use-hook-form/use-hook-form.ts create mode 100644 modules/customer-invoices/src/web/hooks/use-customer-invoice-query.ts create mode 100644 modules/customer-invoices/src/web/pages/update/customer-invoices-update.tsx delete mode 100644 modules/customers/src/web/hooks/use-customer-form.ts create mode 100644 modules/verifactu/src/api/application/presenters/domain/index.ts create mode 100644 modules/verifactu/src/api/application/presenters/domain/verifactu-record.full.presenter.ts create mode 100644 modules/verifactu/src/api/infrastructure/mappers/domain/index.ts create mode 100644 modules/verifactu/src/api/infrastructure/mappers/index.ts create mode 100644 modules/verifactu/src/common/dto/request/get-verifactu-record-by-id.response.dto.ts delete mode 100644 modules/verifactu/src/common/dto/request/send-customer-invoice-by-id.request.dto.ts create mode 100644 modules/verifactu/src/common/dto/request/send-invoice-by-id.request.dto.ts diff --git a/apps/server/package.json b/apps/server/package.json index 591baa38..b4aabb1a 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -75,7 +75,7 @@ "uuid": "^11.0.5", "winston": "^3.17.0", "winston-daily-rotate-file": "^5.0.0", - "zod": "^3.25.67" + "zod": "^4.1.11" }, "engines": { "node": ">=22" diff --git a/apps/server/src/index.ts b/apps/server/src/index.ts index 8681f3d0..c4cec492 100644 --- a/apps/server/src/index.ts +++ b/apps/server/src/index.ts @@ -1,7 +1,7 @@ import { DateTime } from "luxon"; import http from "node:http"; import os from "node:os"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; import { createApp } from "./app"; import { ENV } from "./config"; import { tryConnectToDatabase } from "./config/database"; diff --git a/apps/server/src/lib/modules/module-loader.ts b/apps/server/src/lib/modules/module-loader.ts index f9c3033e..0433612f 100644 --- a/apps/server/src/lib/modules/module-loader.ts +++ b/apps/server/src/lib/modules/module-loader.ts @@ -1,7 +1,7 @@ import { IModuleServer, ModuleParams } from "@erp/core/api"; import { logger } from "../logger"; import { initModels, registerModels } from "./model-loader"; -import { registerService } from "./service-registry"; +import { getService, listServices, registerService } from "./service-registry"; const registeredModules: Map = new Map(); const initializedModules = new Set(); @@ -81,7 +81,13 @@ async function loadModule(name: string, params: ModuleParams, stack: string[]) { // 3) Registrar dependencias que expone (permite async) const pkgApi = await withPhase(name, "registerDependencies", async () => { - return await Promise.resolve(pkg.registerDependencies?.(params)); + return await Promise.resolve( + pkg.registerDependencies?.({ + ...params, + listServices, + getService, + }) + ); }); // 4) Registrar modelos de Sequelize, si existen diff --git a/apps/server/src/register-modules.ts b/apps/server/src/register-modules.ts index 934dd0ed..6c7418fd 100644 --- a/apps/server/src/register-modules.ts +++ b/apps/server/src/register-modules.ts @@ -1,6 +1,6 @@ import customerInvoicesAPIModule from "@erp/customer-invoices/api"; import customersAPIModule from "@erp/customers/api"; -//import verifactuAPIModule from "@erp/verifactu/api"; +import verifactuAPIModule from "@erp/verifactu/api"; import { registerModule } from "./lib"; @@ -8,5 +8,5 @@ export const registerModules = () => { //registerModule(authAPIModule); registerModule(customersAPIModule); registerModule(customerInvoicesAPIModule); - //registerModule(verifactuAPIModule); + registerModule(verifactuAPIModule); }; diff --git a/modules/core/package.json b/modules/core/package.json index e061be4a..8af5a3ad 100644 --- a/modules/core/package.json +++ b/modules/core/package.json @@ -25,6 +25,7 @@ "@repo/rdx-utils": "workspace:*", "@repo/rdx-ui": "workspace:*", "@repo/shadcn-ui": "workspace:*", + "@hookform/resolvers": "^5.0.1", "@tanstack/react-query": "^5.75.4", "axios": "^1.9.0", "express": "^4.18.2", @@ -35,6 +36,6 @@ "react-i18next": "^15.5.1", "react-router-dom": "^6.26.0", "sequelize": "^6.37.5", - "zod": "^3.25.67" + "zod": "^4.1.11" } } diff --git a/modules/core/src/api/domain/value-objects/tax.ts b/modules/core/src/api/domain/value-objects/tax.ts index 1a43a463..d1027587 100644 --- a/modules/core/src/api/domain/value-objects/tax.ts +++ b/modules/core/src/api/domain/value-objects/tax.ts @@ -1,7 +1,7 @@ import { TaxCatalogProvider } from "@erp/core"; import { Percentage, ValueObject } from "@repo/rdx-ddd"; import { Result } from "@repo/rdx-utils"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; const DEFAULT_SCALE = 2; const DEFAULT_MIN_VALUE = 0; diff --git a/modules/core/src/api/infrastructure/express/middlewares/validate-request.middleware.ts b/modules/core/src/api/infrastructure/express/middlewares/validate-request.middleware.ts index 149079a9..ed57d9c3 100644 --- a/modules/core/src/api/infrastructure/express/middlewares/validate-request.middleware.ts +++ b/modules/core/src/api/infrastructure/express/middlewares/validate-request.middleware.ts @@ -1,5 +1,5 @@ import { RequestHandler } from "express"; -import { ZodSchema } from "zod/v4"; +import { z } from "zod/v4"; import { InternalApiError, ValidationApiError } from "../errors"; import { ExpressController } from "../express-controller"; @@ -35,7 +35,7 @@ export type ValidateRequestWithSchemaOptions = { }; export const validateRequest = ( - schema: ZodSchema, + schema: z.ZodObject, source: T = "body" as T, options: ValidateRequestWithSchemaOptions = { sanitize: true } ): RequestHandler => { diff --git a/modules/core/src/common/dto/amount-money.dto.ts b/modules/core/src/common/dto/amount-money.dto.ts index 8738a5f5..ec4c8dc9 100644 --- a/modules/core/src/common/dto/amount-money.dto.ts +++ b/modules/core/src/common/dto/amount-money.dto.ts @@ -1,4 +1,4 @@ -import * as z from "zod/v4"; +import { z } from "zod/v4"; import { AmountBaseSchema } from "./base.schemas"; /** diff --git a/modules/core/src/common/dto/base.schemas.ts b/modules/core/src/common/dto/base.schemas.ts index acf86435..a82d22a8 100644 --- a/modules/core/src/common/dto/base.schemas.ts +++ b/modules/core/src/common/dto/base.schemas.ts @@ -1,4 +1,4 @@ -import * as z from "zod/v4"; +import { z } from "zod/v4"; /** * Cadena con valor numérico: diff --git a/modules/core/src/common/dto/critera.dto.ts b/modules/core/src/common/dto/critera.dto.ts index b563ad47..f5f33047 100644 --- a/modules/core/src/common/dto/critera.dto.ts +++ b/modules/core/src/common/dto/critera.dto.ts @@ -1,4 +1,4 @@ -import * as z from "zod/v4"; +import { z } from "zod/v4"; /** Esquema del DTO para Criteria.fromPrimitives(...) diff --git a/modules/core/src/common/dto/list-view.response.dto.ts b/modules/core/src/common/dto/list-view.response.dto.ts index e9c29b8d..8d92c0db 100644 --- a/modules/core/src/common/dto/list-view.response.dto.ts +++ b/modules/core/src/common/dto/list-view.response.dto.ts @@ -1,4 +1,4 @@ -import * as z from "zod/v4"; +import { z } from "zod/v4"; import { MetadataSchema } from "./metadata.dto"; /** diff --git a/modules/core/src/common/dto/metadata.dto.ts b/modules/core/src/common/dto/metadata.dto.ts index bd1d2afd..93fd8b5b 100644 --- a/modules/core/src/common/dto/metadata.dto.ts +++ b/modules/core/src/common/dto/metadata.dto.ts @@ -1,4 +1,4 @@ -import * as z from "zod/v4"; +import { z } from "zod/v4"; export const MetadataSchema = z .object({ diff --git a/modules/core/src/common/dto/percentage.dto.ts b/modules/core/src/common/dto/percentage.dto.ts index d9b1d253..5984b53c 100644 --- a/modules/core/src/common/dto/percentage.dto.ts +++ b/modules/core/src/common/dto/percentage.dto.ts @@ -1,4 +1,4 @@ -import * as z from "zod/v4"; +import { z } from "zod/v4"; import { NumericStringSchema } from "./base.schemas"; /** diff --git a/modules/core/src/common/dto/quantity.dto.ts b/modules/core/src/common/dto/quantity.dto.ts index efc8845c..85942d2c 100644 --- a/modules/core/src/common/dto/quantity.dto.ts +++ b/modules/core/src/common/dto/quantity.dto.ts @@ -1,4 +1,4 @@ -import * as z from "zod/v4"; +import { z } from "zod/v4"; import { NumericStringSchema } from "./base.schemas"; /** diff --git a/modules/core/src/web/hooks/index.ts b/modules/core/src/web/hooks/index.ts index 47fd0604..0f6e6842 100644 --- a/modules/core/src/web/hooks/index.ts +++ b/modules/core/src/web/hooks/index.ts @@ -1,4 +1,5 @@ export * from "./use-datasource"; +export * from "./use-hook-form"; export * from "./use-pagination"; export * from "./use-query-key"; export * from "./use-toggle"; diff --git a/modules/core/src/web/hooks/use-hook-form/index.ts b/modules/core/src/web/hooks/use-hook-form/index.ts new file mode 100644 index 00000000..93ccc864 --- /dev/null +++ b/modules/core/src/web/hooks/use-hook-form/index.ts @@ -0,0 +1 @@ +export * from "./use-hook-form"; diff --git a/modules/core/src/web/hooks/use-hook-form/use-hook-form.ts b/modules/core/src/web/hooks/use-hook-form/use-hook-form.ts new file mode 100644 index 00000000..1e80bb75 --- /dev/null +++ b/modules/core/src/web/hooks/use-hook-form/use-hook-form.ts @@ -0,0 +1,44 @@ +import { zodResolver } from "@hookform/resolvers/zod"; +import { useEffect } from "react"; +import { FieldValues, UseFormProps, UseFormReturn, useForm } from "react-hook-form"; +import * as z4 from "zod/v4/core"; + +type UseHookFormProps = UseFormProps & { + resolverSchema: z4.$ZodType; + initialValues: UseFormProps["defaultValues"]; + onDirtyChange?: (isDirty: boolean) => void; +}; + +export function useHookForm({ + resolverSchema, + initialValues, + disabled, + onDirtyChange, + ...rest +}: UseHookFormProps): UseFormReturn { + const form = useForm({ + ...rest, + resolver: zodResolver(resolverSchema), + defaultValues: initialValues, + disabled, + }); + + const { + formState: { isDirty }, + } = form; + + useEffect(() => { + onDirtyChange?.(isDirty); + }, [isDirty, onDirtyChange]); + + useEffect(() => { + const applyReset = async () => { + const values = typeof initialValues === "function" ? await initialValues() : initialValues; + + form.reset(values); + }; + applyReset(); + }, [initialValues, form]); + + return form; +} diff --git a/modules/customer-invoices/package.json b/modules/customer-invoices/package.json index 20216039..f1e8e67f 100644 --- a/modules/customer-invoices/package.json +++ b/modules/customer-invoices/package.json @@ -20,7 +20,7 @@ "react-hook-form": "^7.58.1", "react-i18next": "^15.5.1", "sequelize": "^6.37.5", - "zod": "^3.25.67" + "zod": "^4.1.11" }, "devDependencies": { "@hookform/devtools": "^4.4.0", diff --git a/modules/customer-invoices/src/api/domain/value-objects/customer-invoice-item-description.ts b/modules/customer-invoices/src/api/domain/value-objects/customer-invoice-item-description.ts index a4daa601..be01fdc0 100644 --- a/modules/customer-invoices/src/api/domain/value-objects/customer-invoice-item-description.ts +++ b/modules/customer-invoices/src/api/domain/value-objects/customer-invoice-item-description.ts @@ -1,7 +1,7 @@ import { DomainValidationError } from "@erp/core/api"; import { ValueObject } from "@repo/rdx-ddd"; import { Maybe, Result } from "@repo/rdx-utils"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; interface CustomerInvoiceItemDescriptionProps { value: string; diff --git a/modules/customer-invoices/src/api/domain/value-objects/customer-invoice-number.ts b/modules/customer-invoices/src/api/domain/value-objects/customer-invoice-number.ts index aeff163c..910502e6 100644 --- a/modules/customer-invoices/src/api/domain/value-objects/customer-invoice-number.ts +++ b/modules/customer-invoices/src/api/domain/value-objects/customer-invoice-number.ts @@ -1,7 +1,7 @@ import { DomainValidationError } from "@erp/core/api"; import { ValueObject } from "@repo/rdx-ddd"; import { Result } from "@repo/rdx-utils"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; interface ICustomerInvoiceNumberProps { value: string; diff --git a/modules/customer-invoices/src/api/domain/value-objects/customer-invoice-serie.ts b/modules/customer-invoices/src/api/domain/value-objects/customer-invoice-serie.ts index 9c0cb50b..e31f7200 100644 --- a/modules/customer-invoices/src/api/domain/value-objects/customer-invoice-serie.ts +++ b/modules/customer-invoices/src/api/domain/value-objects/customer-invoice-serie.ts @@ -1,7 +1,7 @@ import { DomainValidationError } from "@erp/core/api"; import { ValueObject } from "@repo/rdx-ddd"; import { Maybe, Result } from "@repo/rdx-utils"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; interface ICustomerInvoiceSerieProps { value: string; diff --git a/modules/customer-invoices/src/api/index.ts b/modules/customer-invoices/src/api/index.ts index a46e8614..060080b9 100644 --- a/modules/customer-invoices/src/api/index.ts +++ b/modules/customer-invoices/src/api/index.ts @@ -1,5 +1,8 @@ import { IModuleServer, ModuleParams } from "@erp/core/api"; +import { UniqueID } from "@repo/rdx-ddd"; +import { Transaction } from "sequelize"; import { customerInvoicesRouter, models } from "./infrastructure"; +import { buildCustomerInvoiceDependencies } from "./infrastructure/dependencies"; export const customerInvoicesAPIModule: IModuleServer = { name: "customer-invoices", @@ -12,16 +15,33 @@ export const customerInvoicesAPIModule: IModuleServer = { customerInvoicesRouter(params); logger.info("🚀 CustomerInvoices module initialized", { label: this.name }); }, + async registerDependencies(params) { - const { database, logger } = params; + const { logger, listServices } = params; /* = ModuleParams & { + getService: (name: string) => any; + };*/ + logger.info("🚀 CustomerInvoices module dependencies registered", { label: this.name, }); + + logger.info(listServices()); + //getService() + + const deps = buildCustomerInvoiceDependencies(params); + return { models, services: { - getCustomerInvoice: () => {}, - /*...*/ + getInvoiceByIdInCompany: ( + companyId: UniqueID, + invoiceId: UniqueID, + transaction?: Transaction + ) => { + const { service } = deps; + + return service.getInvoiceByIdInCompany(companyId, invoiceId, transaction); + }, }, }; }, diff --git a/modules/customer-invoices/src/api/infrastructure/dependencies.ts b/modules/customer-invoices/src/api/infrastructure/dependencies.ts index 0be3461e..3ed0942a 100644 --- a/modules/customer-invoices/src/api/infrastructure/dependencies.ts +++ b/modules/customer-invoices/src/api/infrastructure/dependencies.ts @@ -45,10 +45,12 @@ export type CustomerInvoiceDeps = { //delete: () => DeleteCustomerInvoiceUseCase; report: () => ReportCustomerInvoiceUseCase; }; + getService: (name: string) => any; + listServices: () => string[]; }; export function buildCustomerInvoiceDependencies(params: ModuleParams): CustomerInvoiceDeps { - const { database } = params; + const { database, listServices, getService } = params; const transactionManager = new SequelizeTransactionManager(database); const catalogs = { taxes: spainTaxCatalogProvider }; @@ -157,5 +159,7 @@ export function buildCustomerInvoiceDependencies(params: ModuleParams): Customer report: () => new ReportCustomerInvoiceUseCase(service, transactionManager, presenterRegistry), }, + listServices, + getService, }; } diff --git a/modules/customer-invoices/src/common/dto/request/create-customer-invoice.request.dto.ts b/modules/customer-invoices/src/common/dto/request/create-customer-invoice.request.dto.ts index 1f183ac1..da17ee80 100644 --- a/modules/customer-invoices/src/common/dto/request/create-customer-invoice.request.dto.ts +++ b/modules/customer-invoices/src/common/dto/request/create-customer-invoice.request.dto.ts @@ -1,5 +1,5 @@ import { NumericStringSchema, PercentageSchema } from "@erp/core"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; export const CreateCustomerInvoiceItemRequestSchema = z.object({ id: z.uuid(), diff --git a/modules/customer-invoices/src/common/dto/request/customer-invoices-list.request.dto.ts b/modules/customer-invoices/src/common/dto/request/customer-invoices-list.request.dto.ts index 2b97caba..93c25a9b 100644 --- a/modules/customer-invoices/src/common/dto/request/customer-invoices-list.request.dto.ts +++ b/modules/customer-invoices/src/common/dto/request/customer-invoices-list.request.dto.ts @@ -1,5 +1,5 @@ import { CriteriaSchema } from "@erp/core"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; export const CustomerInvoiceListRequestSchema = CriteriaSchema; export type CustomerInvoiceListRequestDTO = z.infer; diff --git a/modules/customer-invoices/src/common/dto/request/delete-customer-invoice-by-id.request.dto.ts b/modules/customer-invoices/src/common/dto/request/delete-customer-invoice-by-id.request.dto.ts index aaa33a78..e0e8f27f 100644 --- a/modules/customer-invoices/src/common/dto/request/delete-customer-invoice-by-id.request.dto.ts +++ b/modules/customer-invoices/src/common/dto/request/delete-customer-invoice-by-id.request.dto.ts @@ -1,4 +1,4 @@ -import * as z from "zod/v4"; +import { z } from "zod/v4"; /** * Este DTO es utilizado por el endpoint: diff --git a/modules/customer-invoices/src/common/dto/request/get-customer-invoice-by-id.request.dto.ts b/modules/customer-invoices/src/common/dto/request/get-customer-invoice-by-id.request.dto.ts index b5eec449..6b915088 100644 --- a/modules/customer-invoices/src/common/dto/request/get-customer-invoice-by-id.request.dto.ts +++ b/modules/customer-invoices/src/common/dto/request/get-customer-invoice-by-id.request.dto.ts @@ -1,4 +1,4 @@ -import * as z from "zod/v4"; +import { z } from "zod/v4"; export const GetCustomerInvoiceByIdRequestSchema = z.object({ invoice_id: z.string(), diff --git a/modules/customer-invoices/src/common/dto/request/report-customer-invoice-by-id.request.dto.ts b/modules/customer-invoices/src/common/dto/request/report-customer-invoice-by-id.request.dto.ts index d99895b0..7f57648d 100644 --- a/modules/customer-invoices/src/common/dto/request/report-customer-invoice-by-id.request.dto.ts +++ b/modules/customer-invoices/src/common/dto/request/report-customer-invoice-by-id.request.dto.ts @@ -1,4 +1,4 @@ -import * as z from "zod/v4"; +import { z } from "zod/v4"; export const ReportCustomerInvoiceByIdRequestSchema = z.object({ invoice_id: z.string(), diff --git a/modules/customer-invoices/src/common/dto/request/update-customer-invoice-by-id.request.dto.ts b/modules/customer-invoices/src/common/dto/request/update-customer-invoice-by-id.request.dto.ts index 3457831c..f5a672f7 100644 --- a/modules/customer-invoices/src/common/dto/request/update-customer-invoice-by-id.request.dto.ts +++ b/modules/customer-invoices/src/common/dto/request/update-customer-invoice-by-id.request.dto.ts @@ -1,4 +1,4 @@ -import * as z from "zod/v4"; +import { z } from "zod/v4"; export const UpdateCustomerInvoiceByIdParamsRequestSchema = z.object({ customer_id: z.string(), diff --git a/modules/customer-invoices/src/common/dto/response/create-customer-invoice.response.dto.ts b/modules/customer-invoices/src/common/dto/response/create-customer-invoice.response.dto.ts index dcb95a82..c5cbb799 100644 --- a/modules/customer-invoices/src/common/dto/response/create-customer-invoice.response.dto.ts +++ b/modules/customer-invoices/src/common/dto/response/create-customer-invoice.response.dto.ts @@ -5,7 +5,7 @@ import { PercentageSchema, QuantitySchema, } from "@erp/core"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; export const CreateCustomerInvoiceResponseSchema = z.object({ id: z.uuid(), diff --git a/modules/customer-invoices/src/common/dto/response/get-customer-invoice-by-id.response.dto.ts b/modules/customer-invoices/src/common/dto/response/get-customer-invoice-by-id.response.dto.ts index c0edb8b8..0d994cc0 100644 --- a/modules/customer-invoices/src/common/dto/response/get-customer-invoice-by-id.response.dto.ts +++ b/modules/customer-invoices/src/common/dto/response/get-customer-invoice-by-id.response.dto.ts @@ -1,5 +1,5 @@ import { MetadataSchema, MoneySchema, PercentageSchema, QuantitySchema } from "@erp/core"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; export const GetCustomerInvoiceByIdResponseSchema = z.object({ id: z.uuid(), diff --git a/modules/customer-invoices/src/common/dto/response/list-customer-invoices.response.dto.ts b/modules/customer-invoices/src/common/dto/response/list-customer-invoices.response.dto.ts index 41394de6..64db0726 100644 --- a/modules/customer-invoices/src/common/dto/response/list-customer-invoices.response.dto.ts +++ b/modules/customer-invoices/src/common/dto/response/list-customer-invoices.response.dto.ts @@ -1,5 +1,5 @@ import { MetadataSchema, MoneySchema, createListViewResponseSchema } from "@erp/core"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; export const ListCustomerInvoicesResponseSchema = createListViewResponseSchema( z.object({ diff --git a/modules/customer-invoices/src/common/dto/response/update-customer-invoice-by-id.response.dto.ts b/modules/customer-invoices/src/common/dto/response/update-customer-invoice-by-id.response.dto.ts index 87255543..9d2f1941 100644 --- a/modules/customer-invoices/src/common/dto/response/update-customer-invoice-by-id.response.dto.ts +++ b/modules/customer-invoices/src/common/dto/response/update-customer-invoice-by-id.response.dto.ts @@ -1,5 +1,5 @@ import { AmountSchema, MetadataSchema, PercentageSchema, QuantitySchema } from "@erp/core"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; export const UpdateCustomerInvoiceByIdResponseSchema = z.object({ id: z.uuid(), diff --git a/modules/customer-invoices/src/web/hooks/index.ts b/modules/customer-invoices/src/web/hooks/index.ts index fdc73a2f..b22c5a35 100644 --- a/modules/customer-invoices/src/web/hooks/index.ts +++ b/modules/customer-invoices/src/web/hooks/index.ts @@ -1,4 +1,5 @@ export * from "./use-create-customer-invoice-mutation"; +export * from "./use-customer-invoice-query"; export * from "./use-customer-invoices-context"; export * from "./use-customer-invoices-query"; export * from "./use-detail-columns"; diff --git a/modules/customer-invoices/src/web/hooks/use-customer-invoice-query.ts b/modules/customer-invoices/src/web/hooks/use-customer-invoice-query.ts new file mode 100644 index 00000000..408e85ee --- /dev/null +++ b/modules/customer-invoices/src/web/hooks/use-customer-invoice-query.ts @@ -0,0 +1,49 @@ +import { useDataSource } from "@erp/core/hooks"; +import { DefaultError, type QueryKey, useQuery } from "@tanstack/react-query"; +import { CustomerInvoiceData } from "../schemas"; + +export const CUSTOMER_INVOICE_QUERY_KEY = (id: string): QueryKey => + ["customer_invoice", id] as const; + +type CustomerInvoiceQueryOptions = { + enabled?: boolean; +}; + +export function useCustomerInvoiceQuery(invoiceId?: string, options?: CustomerInvoiceQueryOptions) { + const dataSource = useDataSource(); + const enabled = (options?.enabled ?? true) && !!invoiceId; + + return useQuery({ + queryKey: CUSTOMER_INVOICE_QUERY_KEY(invoiceId ?? "unknown"), + queryFn: async (context) => { + const { signal } = context; + if (!invoiceId) { + if (!invoiceId) throw new Error("invoiceId is required"); + } + return await dataSource.getOne("customer-invoices", invoiceId, { + signal, + }); + }, + enabled, + }); +} + +/* + export function useQuery< + TQueryFnData = unknown, + TError = unknown, + TData = TQueryFnData, + TQueryKey extends QueryKey = QueryKey + > + + TQueryFnData: the type returned from the queryFn. + TError: the type of Errors to expect from the queryFn. + TData: the type our data property will eventually have. + Only relevant if you use the select option, + because then the data property can be different + from what the queryFn returns. + Otherwise, it will default to whatever the queryFn returns. + TQueryKey: the type of our queryKey, only relevant + if you use the queryKey that is passed to your queryFn. + +*/ diff --git a/modules/customer-invoices/src/web/pages/create/customer-invoice.schema.ts b/modules/customer-invoices/src/web/pages/create/customer-invoice.schema.ts index 6ccb1f68..f1979b86 100644 --- a/modules/customer-invoices/src/web/pages/create/customer-invoice.schema.ts +++ b/modules/customer-invoices/src/web/pages/create/customer-invoice.schema.ts @@ -1,4 +1,4 @@ -import * as z from "zod/v4"; +import { z } from "zod/v4"; import { CreateCustomerInvoiceRequestSchema } from "../../../common/dto"; export const CustomerInvoiceItemDataFormSchema = CreateCustomerInvoiceRequestSchema.extend({ diff --git a/modules/customer-invoices/src/web/pages/update/customer-invoices-update.tsx b/modules/customer-invoices/src/web/pages/update/customer-invoices-update.tsx new file mode 100644 index 00000000..286248b0 --- /dev/null +++ b/modules/customer-invoices/src/web/pages/update/customer-invoices-update.tsx @@ -0,0 +1,152 @@ +import { useHookForm, useUrlParamId } from "@erp/core/hooks"; +import { AppBreadcrumb, AppContent } from "@repo/rdx-ui/components"; +import { Button } from "@repo/shadcn-ui/components"; +import { useNavigate } from "react-router-dom"; +import { useCustomerInvoiceQuery } from "../../hooks"; +import { useTranslation } from "../../i18n"; + +export const CustomerInvoiceUpdate = () => { + const invoiceId = useUrlParamId(); + const { t } = useTranslation(); + const navigate = useNavigate(); + + // 1) Estado de carga del cliente (query) + const { + data: invoiceData, + isLoading: isLoadingInvoice, + isError: isLoadError, + error: loadError, + } = useCustomerInvoiceQuery(invoiceId, { enabled: !!invoiceId }); + + // 2) Estado de actualización (mutación) + const { + mutate, + isPending: isUpdating, + isError: isUpdateError, + error: updateError, + } = useUpdateCustomerInvoice(); + + // 3) Form hook + const form = useHookForm({ + resolverSchema: CustomerInvoiceFormSchema, + initialValues: customerInvoiceData ?? defaultCustomerInvoiceFormData, + disabled: isUpdating, + }); + + const handleSubmit = (data: any) => { + // Handle form submission logic here + console.log("Form submitted with data:", data); + mutate(data); + + // Navigate to the list page after submission + navigate("/customer-invoices/list"); + }; + + if (isError) { + console.error("Error creating customer invoice:", error); + // Optionally, you can show an error message to the user + } + + // Render the component + // You can also handle loading state if needed + // For example, you can disable the submit button while the mutation is in progress + // const isLoading = useCreateCustomerInvoiceMutation().isLoading; + + // Return the JSX for the component + // You can customize the form and its fields as needed + // For example, you can use a form library like react-hook-form or Formik to handle form state and validation + // Here, we are using a simple form with a submit button + + // Note: Make sure to replace the form fields with your actual invoice fields + // and handle validation as needed. + // This is just a basic example to demonstrate the structure of the component. + + // If you are using a form library, you can pass the handleSubmit function to the form's onSubmit prop + // and use the form library's methods to handle form state and validation. + + // Example of a simple form submission handler + // You can replace this with your actual form handling logic + // const handleSubmit = (event: React.FormEvent) => { + // event.preventDefault(); + // const formData = new FormData(event.currentTarget); + + return ( + <> + + +
+
+

{t("pages.create.title")}

+

{t("pages.create.description")}

+
+
+ +
+
+
+ +
+
+ + ); +}; + +/* + return ( + <> +
+
+

+ {t('customerInvoices.list.title' /> +

+

+ {t('CustomerInvoices.list.subtitle' /> +

+
+
+ +
+
+ + +
+
+ + {CustomerInvoiceStatuses.map((s) => ( + + {s.label} + + ))} + +
+ + +
+
+
+ {CustomerInvoiceStatuses.map((s) => ( + + + + ))} +
+ + ); +}; +*/ diff --git a/modules/customer-invoices/src/web/schemas/customer-invoices.api.schema.ts b/modules/customer-invoices/src/web/schemas/customer-invoices.api.schema.ts index 0d709a87..402c4436 100644 --- a/modules/customer-invoices/src/web/schemas/customer-invoices.api.schema.ts +++ b/modules/customer-invoices/src/web/schemas/customer-invoices.api.schema.ts @@ -1,13 +1,16 @@ -//import * as z from "zod/v4"; +import { z } from "zod/v4"; -import { ListCustomerInvoicesResponseDTO } from "@erp/customer-invoices/common"; +import { + GetCustomerInvoiceByIdResponseSchema, + ListCustomerInvoicesResponseDTO, +} from "@erp/customer-invoices/common"; /*export const CustomerCreateSchema = CreateCustomerRequestSchema; -export const CustomerUpdateSchema = UpdateCustomerByIdRequestSchema; -export const CustomerSchema = GetCustomerByIdResponseSchema.omit({ +export const CustomerUpdateSchema = UpdateCustomerByIdRequestSchema;*/ +export const CustomerSchema = GetCustomerInvoiceByIdResponseSchema.omit({ metadata: true, }); -export type CustomerData = z.infer;*/ +export type CustomerInvoiceData = z.infer; export type CustomerInvoicesListData = ListCustomerInvoicesResponseDTO; diff --git a/modules/customer-invoices/src/web/schemas/customer-invoices.form.schema.ts b/modules/customer-invoices/src/web/schemas/customer-invoices.form.schema.ts index 8b137891..38dc5bd3 100644 --- a/modules/customer-invoices/src/web/schemas/customer-invoices.form.schema.ts +++ b/modules/customer-invoices/src/web/schemas/customer-invoices.form.schema.ts @@ -1 +1,9 @@ +import { z } from "zod/v4"; +export const CustomerInvoiceFormSchema = z.object({ + invoice_number: z.string().optional(), + status: z.string().optional(), + series: z.string().optional(), +}); + +export const CustomerInvoiceFormData = z.infer; diff --git a/modules/customers/package.json b/modules/customers/package.json index c174b44f..9e8407a4 100644 --- a/modules/customers/package.json +++ b/modules/customers/package.json @@ -18,7 +18,7 @@ "react-hook-form": "^7.58.1", "react-i18next": "^15.5.1", "sequelize": "^6.37.5", - "zod": "^3.25.67" + "zod": "^4.1.11" }, "devDependencies": { "@types/express": "^4.17.21", diff --git a/modules/customers/src/api/domain/value-objects/customer-number.ts b/modules/customers/src/api/domain/value-objects/customer-number.ts index aa9a5f4b..d2e8c45a 100644 --- a/modules/customers/src/api/domain/value-objects/customer-number.ts +++ b/modules/customers/src/api/domain/value-objects/customer-number.ts @@ -1,6 +1,6 @@ import { DomainValidationError, ValueObject } from "@repo/rdx-ddd"; import { Result } from "@repo/rdx-utils"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; interface ICustomerNumberProps { value: string; diff --git a/modules/customers/src/api/domain/value-objects/customer-serie.ts b/modules/customers/src/api/domain/value-objects/customer-serie.ts index 618fafa4..c56ca9f3 100644 --- a/modules/customers/src/api/domain/value-objects/customer-serie.ts +++ b/modules/customers/src/api/domain/value-objects/customer-serie.ts @@ -1,6 +1,6 @@ import { DomainValidationError, ValueObject } from "@repo/rdx-ddd"; import { Maybe, Result } from "@repo/rdx-utils"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; interface ICustomerSerieProps { value: string; diff --git a/modules/customers/src/api/infrastructure/express/customers.routes.ts b/modules/customers/src/api/infrastructure/express/customers.routes.ts index 7678441d..c294f701 100644 --- a/modules/customers/src/api/infrastructure/express/customers.routes.ts +++ b/modules/customers/src/api/infrastructure/express/customers.routes.ts @@ -1,5 +1,6 @@ import { RequestWithAuth, enforceTenant, enforceUser, mockUser } from "@erp/auth/api"; -import { ILogger, ModuleParams, validateRequest } from "@erp/core/api"; +import { ModuleParams, validateRequest } from "@erp/core/api"; +import { ILogger } from "@repo/rdx-logger"; import { Application, NextFunction, Request, Response, Router } from "express"; import { Sequelize } from "sequelize"; import { diff --git a/modules/customers/src/common/dto/request/create-customer.request.dto.ts b/modules/customers/src/common/dto/request/create-customer.request.dto.ts index 64a610fd..027199f0 100644 --- a/modules/customers/src/common/dto/request/create-customer.request.dto.ts +++ b/modules/customers/src/common/dto/request/create-customer.request.dto.ts @@ -1,4 +1,4 @@ -import * as z from "zod/v4"; +import { z } from "zod/v4"; export const CreateCustomerRequestSchema = z.object({ id: z.string().nonempty(), diff --git a/modules/customers/src/common/dto/request/customer-list.request.dto.ts b/modules/customers/src/common/dto/request/customer-list.request.dto.ts index c0058271..c1385d1d 100644 --- a/modules/customers/src/common/dto/request/customer-list.request.dto.ts +++ b/modules/customers/src/common/dto/request/customer-list.request.dto.ts @@ -1,5 +1,5 @@ import { CriteriaSchema } from "@erp/core"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; export const CustomerListRequestSchema = CriteriaSchema; export type CustomerListRequestDTO = z.infer; diff --git a/modules/customers/src/common/dto/request/delete-customer-by-id.request.dto.ts b/modules/customers/src/common/dto/request/delete-customer-by-id.request.dto.ts index d8afc88d..b8c781ad 100644 --- a/modules/customers/src/common/dto/request/delete-customer-by-id.request.dto.ts +++ b/modules/customers/src/common/dto/request/delete-customer-by-id.request.dto.ts @@ -1,4 +1,4 @@ -import * as z from "zod/v4"; +import { z } from "zod/v4"; /** * Este DTO es utilizado por el endpoint: diff --git a/modules/customers/src/common/dto/request/get-customer-by-id.request.dto.ts b/modules/customers/src/common/dto/request/get-customer-by-id.request.dto.ts index 07f04ac8..0f1169c3 100644 --- a/modules/customers/src/common/dto/request/get-customer-by-id.request.dto.ts +++ b/modules/customers/src/common/dto/request/get-customer-by-id.request.dto.ts @@ -1,4 +1,4 @@ -import * as z from "zod/v4"; +import { z } from "zod/v4"; /** * Este DTO es utilizado por el endpoint: diff --git a/modules/customers/src/common/dto/request/update-customer-by-id.request.dto.ts b/modules/customers/src/common/dto/request/update-customer-by-id.request.dto.ts index c942fb53..19ff1867 100644 --- a/modules/customers/src/common/dto/request/update-customer-by-id.request.dto.ts +++ b/modules/customers/src/common/dto/request/update-customer-by-id.request.dto.ts @@ -1,4 +1,4 @@ -import * as z from "zod/v4"; +import { z } from "zod/v4"; export const UpdateCustomerByIdParamsRequestSchema = z.object({ customer_id: z.string(), diff --git a/modules/customers/src/common/dto/response/create-customer.result.dto.ts b/modules/customers/src/common/dto/response/create-customer.result.dto.ts index 7c398de2..22798e7c 100644 --- a/modules/customers/src/common/dto/response/create-customer.result.dto.ts +++ b/modules/customers/src/common/dto/response/create-customer.result.dto.ts @@ -1,5 +1,5 @@ import { MetadataSchema } from "@erp/core"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; export const CreateCustomerResponseSchema = z.object({ id: z.uuid(), diff --git a/modules/customers/src/common/dto/response/get-customer-by-id.response.dto.ts b/modules/customers/src/common/dto/response/get-customer-by-id.response.dto.ts index 21464c23..6ae75cd2 100644 --- a/modules/customers/src/common/dto/response/get-customer-by-id.response.dto.ts +++ b/modules/customers/src/common/dto/response/get-customer-by-id.response.dto.ts @@ -1,5 +1,5 @@ import { MetadataSchema } from "@erp/core"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; export const GetCustomerByIdResponseSchema = z.object({ id: z.uuid(), diff --git a/modules/customers/src/common/dto/response/list-customers.response.dto.ts b/modules/customers/src/common/dto/response/list-customers.response.dto.ts index 64248177..060594c6 100644 --- a/modules/customers/src/common/dto/response/list-customers.response.dto.ts +++ b/modules/customers/src/common/dto/response/list-customers.response.dto.ts @@ -1,5 +1,5 @@ import { MetadataSchema, createListViewResponseSchema } from "@erp/core"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; export const ListCustomersResponseSchema = createListViewResponseSchema( z.object({ diff --git a/modules/customers/src/common/dto/response/update-customer-by-id.response.dto.ts b/modules/customers/src/common/dto/response/update-customer-by-id.response.dto.ts index 628616fa..81b9c3bb 100644 --- a/modules/customers/src/common/dto/response/update-customer-by-id.response.dto.ts +++ b/modules/customers/src/common/dto/response/update-customer-by-id.response.dto.ts @@ -1,5 +1,5 @@ import { MetadataSchema } from "@erp/core"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; export const UpdateCustomerByIdResponseSchema = z.object({ id: z.uuid(), diff --git a/modules/customers/src/web/hooks/index.ts b/modules/customers/src/web/hooks/index.ts index 18f3fee4..e7126993 100644 --- a/modules/customers/src/web/hooks/index.ts +++ b/modules/customers/src/web/hooks/index.ts @@ -1,5 +1,4 @@ export * from "./use-create-customer-mutation"; -export * from "./use-customer-form"; export * from "./use-customer-query"; export * from "./use-customers-context"; export * from "./use-customers-query"; diff --git a/modules/customers/src/web/hooks/use-create-customer-mutation.ts b/modules/customers/src/web/hooks/use-create-customer-mutation.ts index 5dd66658..38d5cefc 100644 --- a/modules/customers/src/web/hooks/use-create-customer-mutation.ts +++ b/modules/customers/src/web/hooks/use-create-customer-mutation.ts @@ -9,7 +9,7 @@ type CreateCustomerPayload = { data: CustomerFormData; }; -export function useCreateCustomerMutation() { +export function useCreateCustomer() { const queryClient = useQueryClient(); const dataSource = useDataSource(); const schema = CreateCustomerRequestSchema; diff --git a/modules/customers/src/web/hooks/use-customer-form.ts b/modules/customers/src/web/hooks/use-customer-form.ts deleted file mode 100644 index de77aa8e..00000000 --- a/modules/customers/src/web/hooks/use-customer-form.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { zodResolver } from "@hookform/resolvers/zod"; -import { useEffect } from "react"; -import { useForm } from "react-hook-form"; -import { CustomerFormData, CustomerFormSchema } from "../schemas"; - -type UseCustomerFormProps = { - initialValues: CustomerFormData; - disabled?: boolean; - onDirtyChange?: (isDirty: boolean) => void; -}; - -export function useCustomerForm({ initialValues, disabled, onDirtyChange }: UseCustomerFormProps) { - const form = useForm({ - resolver: zodResolver(CustomerFormSchema), - defaultValues: initialValues, - disabled, - }); - - const { - formState: { isDirty }, - } = form; - - // Avisar cuando cambia el dirty state - useEffect(() => { - if (onDirtyChange) { - onDirtyChange(isDirty); - } - }, [isDirty, onDirtyChange]); - - // Resetear el form si cambian los valores iniciales - useEffect(() => { - form.reset(initialValues); - }, [initialValues, form]); - - return form; -} diff --git a/modules/customers/src/web/hooks/use-customer-query.ts b/modules/customers/src/web/hooks/use-customer-query.ts index 316ae853..553f66ca 100644 --- a/modules/customers/src/web/hooks/use-customer-query.ts +++ b/modules/customers/src/web/hooks/use-customer-query.ts @@ -12,22 +12,19 @@ export function useCustomerQuery(customerId?: string, options?: CustomerQueryOpt const dataSource = useDataSource(); const enabled = (options?.enabled ?? true) && !!customerId; - const queryResult = useQuery({ + return useQuery({ queryKey: CUSTOMER_QUERY_KEY(customerId ?? "unknown"), queryFn: async (context) => { const { signal } = context; if (!customerId) { if (!customerId) throw new Error("customerId is required"); } - const customer = await dataSource.getOne("customers", customerId, { + return await dataSource.getOne("customers", customerId, { signal, }); - return customer; }, enabled, }); - - return queryResult; } /* diff --git a/modules/customers/src/web/hooks/use-update-customer-mutation.ts b/modules/customers/src/web/hooks/use-update-customer-mutation.ts index f302a1d4..417a76e8 100644 --- a/modules/customers/src/web/hooks/use-update-customer-mutation.ts +++ b/modules/customers/src/web/hooks/use-update-customer-mutation.ts @@ -14,7 +14,7 @@ type UpdateCustomerPayload = { data: Partial; }; -export function useUpdateCustomerMutation() { +export function useUpdateCustomer() { const queryClient = useQueryClient(); const dataSource = useDataSource(); const schema = UpdateCustomerByIdRequestSchema; diff --git a/modules/customers/src/web/pages/create/customer-create.tsx b/modules/customers/src/web/pages/create/customer-create.tsx index 06dd26dd..c337137a 100644 --- a/modules/customers/src/web/pages/create/customer-create.tsx +++ b/modules/customers/src/web/pages/create/customer-create.tsx @@ -1,13 +1,13 @@ import { AppBreadcrumb, AppContent } from "@repo/rdx-ui/components"; import { useNavigate } from "react-router-dom"; -import { FormCommitButtonGroup, UnsavedChangesProvider } from "@erp/core/hooks"; +import { FormCommitButtonGroup, UnsavedChangesProvider, useHookForm } from "@erp/core/hooks"; import { showErrorToast, showSuccessToast } from "@repo/rdx-ui/helpers"; import { FieldErrors, FormProvider } from "react-hook-form"; import { CustomerEditForm, ErrorAlert } from "../../components"; -import { useCreateCustomerMutation, useCustomerForm } from "../../hooks"; +import { useCreateCustomer } from "../../hooks"; import { useTranslation } from "../../i18n"; -import { CustomerFormData, defaultCustomerFormData } from "../../schemas"; +import { CustomerFormData, CustomerFormSchema, defaultCustomerFormData } from "../../schemas"; export const CustomerCreate = () => { const { t } = useTranslation(); @@ -19,11 +19,13 @@ export const CustomerCreate = () => { isPending: isCreating, isError: isCreateError, error: createError, - } = useCreateCustomerMutation(); + } = useCreateCustomer(); // 2) Form hook - const form = useCustomerForm({ + const form = useHookForm({ + resolverSchema: CustomerFormSchema, initialValues: defaultCustomerFormData, + disabled: isCreating, }); // 3) Submit con navegación condicionada por éxito diff --git a/modules/customers/src/web/pages/update/customer-update.tsx b/modules/customers/src/web/pages/update/customer-update.tsx index 7970241a..c6deada4 100644 --- a/modules/customers/src/web/pages/update/customer-update.tsx +++ b/modules/customers/src/web/pages/update/customer-update.tsx @@ -2,7 +2,12 @@ import { AppBreadcrumb, AppContent, BackHistoryButton } from "@repo/rdx-ui/compo import { useNavigate } from "react-router-dom"; import { formHasAnyDirty, pickFormDirtyValues } from "@erp/core/client"; -import { FormCommitButtonGroup, UnsavedChangesProvider, useUrlParamId } from "@erp/core/hooks"; +import { + FormCommitButtonGroup, + UnsavedChangesProvider, + useHookForm, + useUrlParamId, +} from "@erp/core/hooks"; import { showErrorToast, showSuccessToast, showWarningToast } from "@repo/rdx-ui/helpers"; import { FieldErrors, FormProvider } from "react-hook-form"; import { @@ -11,9 +16,9 @@ import { ErrorAlert, NotFoundCard, } from "../../components"; -import { useCustomerForm, useCustomerQuery, useUpdateCustomerMutation } from "../../hooks"; +import { useCustomerQuery, useUpdateCustomer } from "../../hooks"; import { useTranslation } from "../../i18n"; -import { CustomerFormData, defaultCustomerFormData } from "../../schemas"; +import { CustomerFormData, CustomerFormSchema, defaultCustomerFormData } from "../../schemas"; export const CustomerUpdate = () => { const customerId = useUrlParamId(); @@ -34,11 +39,13 @@ export const CustomerUpdate = () => { isPending: isUpdating, isError: isUpdateError, error: updateError, - } = useUpdateCustomerMutation(); + } = useUpdateCustomer(); // 3) Form hook - const form = useCustomerForm({ + const form = useHookForm({ + resolverSchema: CustomerFormSchema, initialValues: customerData ?? defaultCustomerFormData, + disabled: isUpdating, }); // 4) Submit con navegación condicionada por éxito diff --git a/modules/customers/src/web/schemas/customer.api.schema.ts b/modules/customers/src/web/schemas/customer.api.schema.ts index 2c363e2a..405c0600 100644 --- a/modules/customers/src/web/schemas/customer.api.schema.ts +++ b/modules/customers/src/web/schemas/customer.api.schema.ts @@ -1,4 +1,4 @@ -import * as z from "zod/v4"; +import { z } from "zod/v4"; import { CreateCustomerRequestSchema, diff --git a/modules/customers/src/web/schemas/customer.form.schema.ts b/modules/customers/src/web/schemas/customer.form.schema.ts index 5f1f4b0a..abda9345 100644 --- a/modules/customers/src/web/schemas/customer.form.schema.ts +++ b/modules/customers/src/web/schemas/customer.form.schema.ts @@ -1,4 +1,4 @@ -import * as z from "zod/v4"; +import { z } from "zod/v4"; export const CustomerFormSchema = z.object({ reference: z.string().optional(), diff --git a/modules/verifactu/package.json b/modules/verifactu/package.json index 60cd494e..011b42c3 100644 --- a/modules/verifactu/package.json +++ b/modules/verifactu/package.json @@ -3,17 +3,23 @@ "version": "0.0.1", "main": "src/index.ts", "types": "src/index.ts", - "exports": { "./api": "./src/api/index.ts" }, + "exports": { + "./api": "./src/api/index.ts", + "./common": "./src/common/index.ts" + }, "peerDependencies": { "sequelize": "^6.37.5", - "express": "^4.18.2" + "express": "^4.18.2", + "zod": "^4.1.11" }, "devDependencies": { "@types/express": "^4.17.21" }, "dependencies": { "@erp/auth": "workspace:*", "@erp/core": "workspace:*", "@repo/rdx-ddd": "workspace:*", + "@repo/rdx-criteria": "workspace:*", "@repo/rdx-utils": "workspace:*", - "@repo/rdx-logger": "workspace:*" + "@repo/rdx-logger": "workspace:*", + "@erp/customer-invoices": "workspace:*" } } diff --git a/modules/verifactu/src/api/application/presenters/domain/index.ts b/modules/verifactu/src/api/application/presenters/domain/index.ts new file mode 100644 index 00000000..59327b29 --- /dev/null +++ b/modules/verifactu/src/api/application/presenters/domain/index.ts @@ -0,0 +1,2 @@ +export * from "./verifactu-record.full.presenter"; +//export * from "./verifactu-record.full.representer"; diff --git a/modules/verifactu/src/api/application/presenters/domain/verifactu-record.full.presenter.ts b/modules/verifactu/src/api/application/presenters/domain/verifactu-record.full.presenter.ts new file mode 100644 index 00000000..911cad5d --- /dev/null +++ b/modules/verifactu/src/api/application/presenters/domain/verifactu-record.full.presenter.ts @@ -0,0 +1,24 @@ +import { Presenter } from "@erp/core/api"; +import { GetVerifactuRecordByIdResponseDTO } from "@erp/verifactu-records/common"; +import { VerifactuRecord } from "../../../domain"; + +export class VerifactuRecordFullPresenter extends Presenter< + VerifactuRecord, + GetVerifactuRecordByIdResponseDTO +> { + toOutput(record: VerifactuRecord): GetVerifactuRecordByIdResponseDTO { + return { + id: record.id.toString(), + invoice_id: record.invoiceId.toString(), + + estado: record.estado.toPrimitive(), + url: record.url.toPrimitive(), + // qr1: toEmptyString(record.qr1, (value) => value.toString()), + + metadata: { + entity: "verifactu-records", + link: "", + }, + }; + } +} diff --git a/modules/verifactu/src/api/application/use-cases/send/send-invoice.use-case.ts b/modules/verifactu/src/api/application/use-cases/send/send-invoice.use-case.ts index 6395de35..710d07f9 100644 --- a/modules/verifactu/src/api/application/use-cases/send/send-invoice.use-case.ts +++ b/modules/verifactu/src/api/application/use-cases/send/send-invoice.use-case.ts @@ -17,7 +17,7 @@ export class SendInvoiceUseCase { public async execute(params: SendInvoiceUseCaseInput) { const { invoice_id } = params; - + console.log("CASO DE USO -----ESTO ES UNA PRUEBA>>>>>>", invoice_id); const idOrError = UniqueID.create(invoice_id); if (idOrError.isFailure) { @@ -25,14 +25,41 @@ export class SendInvoiceUseCase { } const invoiceId = idOrError.data; + console.log("CASO DE USO -----VALIDADO>>>>>>", invoiceId); return this.transactionManager.complete(async (transaction: Transaction) => { try { - const invoiceOrError = await this.service.sendInvoiceToVerifactu(invoiceId, transaction); + console.log( + "CASO DE USO -----LLamar servicio de invoices para recuperar el invoice>>>>>>", + invoiceId + ); + const invoice = { + serie: "A", + numero: "1", + fecha_expedicion: "12-09-2025", + tipo_factura: "F1", + descripcion: "Venta de bienes", + nif: "A15022510", + nombre: "Empresa de prueba SL", + lineas: [ + { + base_imponible: "200", + tipo_impositivo: "21", + cuota_repercutida: "42", + }, + { + base_imponible: "100", + tipo_impositivo: "10", + cuota_repercutida: "10", + }, + ], + importe_total: "352.00", + }; + const invoiceOrError = await this.service.sendInvoiceToVerifactu(invoice, transaction); if (invoiceOrError.isFailure) { return Result.fail(invoiceOrError.error); } - const invoice = invoiceOrError.data; + const invoice2 = invoiceOrError.data; return Result.ok({}); } catch (error: unknown) { return Result.fail(error as Error); diff --git a/modules/verifactu/src/api/domain/aggregates/value-objects/verifactu-record-url.ts b/modules/verifactu/src/api/domain/aggregates/value-objects/verifactu-record-url.ts index 806636a3..0b232999 100644 --- a/modules/verifactu/src/api/domain/aggregates/value-objects/verifactu-record-url.ts +++ b/modules/verifactu/src/api/domain/aggregates/value-objects/verifactu-record-url.ts @@ -1,7 +1,7 @@ import { DomainValidationError } from "@erp/core/api"; import { ValueObject } from "@repo/rdx-ddd"; import { Maybe, Result } from "@repo/rdx-utils"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; interface VerifactuRecordUrlProps { value: string; diff --git a/modules/verifactu/src/api/domain/services/verifactu-record.service.ts b/modules/verifactu/src/api/domain/services/verifactu-record.service.ts index 01743c72..cbf74400 100644 --- a/modules/verifactu/src/api/domain/services/verifactu-record.service.ts +++ b/modules/verifactu/src/api/domain/services/verifactu-record.service.ts @@ -42,29 +42,6 @@ export class VerifactuRecordService { // return Result.fail(invoiceResult.error); // } - const invoice = { - serie: "A", - numero: "1", - fecha_expedicion: "12-09-2025", - tipo_factura: "F1", - descripcion: "Venta de bienes", - nif: "A15022510", - nombre: "Empresa de prueba SL", - lineas: [ - { - base_imponible: "200", - tipo_impositivo: "21", - cuota_repercutida: "42", - }, - { - base_imponible: "100", - tipo_impositivo: "10", - cuota_repercutida: "10", - }, - ], - importe_total: "352.00", - }; - console.log("ESTO ES UNA PRUEBA>>>>>>"); return Result.ok(invoice); diff --git a/modules/verifactu/src/api/index.ts b/modules/verifactu/src/api/index.ts index d3beb129..460e75b0 100644 --- a/modules/verifactu/src/api/index.ts +++ b/modules/verifactu/src/api/index.ts @@ -4,11 +4,9 @@ import { models, verifactuRouter } from "./infrastructure"; export const verifactuAPIModule: IModuleServer = { name: "verifactu", version: "1.0.0", - dependencies: ["customers-invoices"], + dependencies: ["customer-invoices"], async init(params: ModuleParams) { - // const contacts = getService("contacts"); - console.log("111111111111111111111111111A>>>>>>>>>>>>>>>>>>>"); const { logger } = params; verifactuRouter(params); logger.info("🚀 Verifactu module initialized", { label: this.name }); diff --git a/modules/verifactu/src/api/infrastructure/dependencies.ts b/modules/verifactu/src/api/infrastructure/dependencies.ts index 6845a811..a9c71767 100644 --- a/modules/verifactu/src/api/infrastructure/dependencies.ts +++ b/modules/verifactu/src/api/infrastructure/dependencies.ts @@ -2,116 +2,62 @@ import type { IMapperRegistry, IPresenterRegistry, ModuleParams } from "@erp/core/api"; -import { JsonTaxCatalogProvider } from "@erp/core"; import { InMemoryMapperRegistry, InMemoryPresenterRegistry, SequelizeTransactionManager, } from "@erp/core/api"; -import { SendCustomerInvoiceUseCase } from "../application"; -import { CustomerInvoiceItemsReportPersenter } from "../application/presenters/queries/customer-invoice-items.report.presenter"; -import { CustomerInvoiceService } from "../domain"; -import { CustomerInvoiceDomainMapper, CustomerInvoiceListMapper } from "./mappers"; -import { CustomerInvoiceRepository } from "./sequelize"; +import { SendInvoiceUseCase } from "../application"; +import { VerifactuRecordFullPresenter } from "../application/presenters/domain/verifactu-record.full.presenter"; +import { VerifactuRecordService } from "../domain"; +//import { VerifactuRecordItemsReportPersenter } from "../application/presenters/queries/verifactu-record-items.report.presenter"; +import { VerifactuRecordDomainMapper } from "./mappers"; +import { VerifactuRecordRepository } from "./sequelize"; -export type CustomerInvoiceDeps = { +export type VerifactuRecordDeps = { transactionManager: SequelizeTransactionManager; mapperRegistry: IMapperRegistry; presenterRegistry: IPresenterRegistry; - repo: CustomerInvoiceRepository; - service: CustomerInvoiceService; - catalogs: { - taxes: JsonTaxCatalogProvider; - }; + repo: VerifactuRecordRepository; + service: VerifactuRecordService; build: { - send: () => SendCustomerInvoiceUseCase; + send: () => SendInvoiceUseCase; }; + getService: (name: string) => any; + listServices: () => string[]; }; -export function buildVerifactuDependencies(params: ModuleParams): CustomerInvoiceDeps { - const { database } = params; +export function buildVerifactuDependencies(params: ModuleParams): VerifactuRecordDeps { + const { database, listServices, getService } = params; const transactionManager = new SequelizeTransactionManager(database); // Mapper Registry const mapperRegistry = new InMemoryMapperRegistry(); - mapperRegistry - .registerDomainMapper( - { resource: "customer-invoice" }, - new CustomerInvoiceDomainMapper({ taxCatalog: catalogs.taxes }) - ) - .registerQueryMappers([ + mapperRegistry.registerDomainMapper( + { resource: "verifactu-record" }, + new VerifactuRecordDomainMapper({}) + ); + /* .registerQueryMappers([ { - key: { resource: "customer-invoice", query: "LIST" }, - mapper: new CustomerInvoiceListMapper(), + key: { resource: "verifactu-record", query: "LIST" }, + mapper: new VerifactuRecordListMapper(), }, ]); +*/ // Repository & Services - const repo = new CustomerInvoiceRepository({ mapperRegistry, database }); - const service = new CustomerInvoiceService(repo); + const repo = new VerifactuRecordRepository({ mapperRegistry, database }); + const service = new VerifactuRecordService(repo); // Presenter Registry const presenterRegistry = new InMemoryPresenterRegistry(); presenterRegistry.registerPresenters([ { key: { - resource: "customer-invoice-items", + resource: "verifactu-record", projection: "FULL", }, - presenter: new CustomerInvoiceItemsFullPresenter(presenterRegistry), - }, - { - key: { - resource: "recipient-invoice", - projection: "FULL", - }, - presenter: new RecipientInvoiceFullPresenter(presenterRegistry), - }, - { - key: { - resource: "customer-invoice", - projection: "FULL", - }, - presenter: new CustomerInvoiceFullPresenter(presenterRegistry), - }, - { - key: { - resource: "customer-invoice", - projection: "LIST", - }, - presenter: new ListCustomerInvoicesPresenter(presenterRegistry), - }, - { - key: { - resource: "customer-invoice", - projection: "REPORT", - format: "JSON", - }, - presenter: new CustomerInvoiceReportPresenter(presenterRegistry), - }, - { - key: { - resource: "customer-invoice-items", - projection: "REPORT", - format: "JSON", - }, - presenter: new CustomerInvoiceItemsReportPersenter(presenterRegistry), - }, - { - key: { - resource: "customer-invoice", - projection: "REPORT", - format: "HTML", - }, - presenter: new CustomerInvoiceReportHTMLPresenter(presenterRegistry), - }, - { - key: { - resource: "customer-invoice", - projection: "REPORT", - format: "PDF", - }, - presenter: new CustomerInvoiceReportPDFPresenter(presenterRegistry), + presenter: new VerifactuRecordFullPresenter(presenterRegistry), }, ]); @@ -121,21 +67,20 @@ export function buildVerifactuDependencies(params: ModuleParams): CustomerInvoic mapperRegistry, presenterRegistry, service, - catalogs, build: { - list: () => new ListCustomerInvoicesUseCase(service, transactionManager, presenterRegistry), - get: () => new GetCustomerInvoiceUseCase(service, transactionManager, presenterRegistry), - create: () => - new CreateCustomerInvoiceUseCase( + send: () => new SendInvoiceUseCase(service, transactionManager, presenterRegistry), + // get: () => new GetVerifactuRecordUseCase(service, transactionManager, presenterRegistry), + /* create: () => + new CreateVerifactuRecordUseCase( service, transactionManager, presenterRegistry, - catalogs.taxes ), - // update: () => new UpdateCustomerInvoiceUseCase(service, transactionManager), - // delete: () => new DeleteCustomerInvoiceUseCase(service, transactionManager), - report: () => - new ReportCustomerInvoiceUseCase(service, transactionManager, presenterRegistry), +*/ + // update: () => new UpdateVerifactuRecordUseCase(service, transactionManager), + // delete: () => new DeleteVerifactuRecordUseCase(service, transactionManager), }, + listServices, + getService, }; } diff --git a/modules/verifactu/src/api/infrastructure/express/controllers/send-invoice-verifactu.controller.ts b/modules/verifactu/src/api/infrastructure/express/controllers/send-invoice-verifactu.controller.ts index 20cebfd1..c4cdb05a 100644 --- a/modules/verifactu/src/api/infrastructure/express/controllers/send-invoice-verifactu.controller.ts +++ b/modules/verifactu/src/api/infrastructure/express/controllers/send-invoice-verifactu.controller.ts @@ -15,8 +15,6 @@ export class SendInvoiceVerifactuController extends ExpressController { } const { invoice_id } = this.req.params; - console.log("CONTROLLER -----ESTO ES UNA PRUEBA>>>>>>"); - const result = await this.useCase.execute({ invoice_id }); return result.match( diff --git a/modules/verifactu/src/api/infrastructure/express/verifactu.routes.ts b/modules/verifactu/src/api/infrastructure/express/verifactu.routes.ts index d2bcdbb5..29457883 100644 --- a/modules/verifactu/src/api/infrastructure/express/verifactu.routes.ts +++ b/modules/verifactu/src/api/infrastructure/express/verifactu.routes.ts @@ -1,8 +1,9 @@ import { RequestWithAuth, enforceTenant, enforceUser, mockUser } from "@erp/auth/api"; -import { ILogger, ModuleParams, validateRequest } from "@erp/core/api"; +import { ModuleParams, validateRequest } from "@erp/core/api"; +import { SendInvoiceByIdRequestSchema } from "@erp/verifactu/common"; +import { ILogger } from "@repo/rdx-logger"; import { Application, NextFunction, Request, Response, Router } from "express"; import { Sequelize } from "sequelize"; -import { SendCustomerInvoiceByIdRequestSchema } from "../../../common/dto"; import { buildVerifactuDependencies } from "../dependencies"; import { SendInvoiceVerifactuController } from "./controllers"; @@ -14,7 +15,6 @@ export const verifactuRouter = (params: ModuleParams) => { logger: ILogger; }; - console.log("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA>>>>>>>>>>>>>>>>>>>"); const deps = buildVerifactuDependencies(params); const router: Router = Router({ mergeParams: true }); @@ -40,11 +40,17 @@ export const verifactuRouter = (params: ModuleParams) => { router.get( "/:invoice_id/sendVerifactu", //checkTabContext, - validateRequest(SendCustomerInvoiceByIdRequestSchema, "params"), + validateRequest(SendInvoiceByIdRequestSchema, "params"), (req: Request, res: Response, next: NextFunction) => { - const useCase = deps.build.report(); + const { listServices } = deps; + const useCase = deps.build.send(); + + logger.info(listServices()); + const controller = new SendInvoiceVerifactuController(useCase); return controller.execute(req, res, next); } ); + + app.use(`${baseRoutePath}/verifactu`, router); }; diff --git a/modules/verifactu/src/api/infrastructure/mappers/domain/index.ts b/modules/verifactu/src/api/infrastructure/mappers/domain/index.ts new file mode 100644 index 00000000..7875eab9 --- /dev/null +++ b/modules/verifactu/src/api/infrastructure/mappers/domain/index.ts @@ -0,0 +1 @@ +export * from "./verifactu-record.mapper"; diff --git a/modules/verifactu/src/api/infrastructure/mappers/domain/verifactu-record.mapper.ts b/modules/verifactu/src/api/infrastructure/mappers/domain/verifactu-record.mapper.ts index e8d553fd..647da433 100644 --- a/modules/verifactu/src/api/infrastructure/mappers/domain/verifactu-record.mapper.ts +++ b/modules/verifactu/src/api/infrastructure/mappers/domain/verifactu-record.mapper.ts @@ -1,5 +1,4 @@ import { ISequelizeDomainMapper, MapperParamsType, SequelizeDomainMapper } from "@erp/core/api"; -import { VerifactuRecordEstado } from "@erp/customer-invoices/api/domain/aggregates/value-objects"; import { UniqueID, ValidationErrorCollection, diff --git a/modules/verifactu/src/api/infrastructure/mappers/index.ts b/modules/verifactu/src/api/infrastructure/mappers/index.ts new file mode 100644 index 00000000..6b42abc4 --- /dev/null +++ b/modules/verifactu/src/api/infrastructure/mappers/index.ts @@ -0,0 +1,2 @@ +export * from "./domain"; +//export * from "./queries"; diff --git a/modules/verifactu/src/common/dto/request/get-verifactu-record-by-id.response.dto.ts b/modules/verifactu/src/common/dto/request/get-verifactu-record-by-id.response.dto.ts new file mode 100644 index 00000000..0b485eb8 --- /dev/null +++ b/modules/verifactu/src/common/dto/request/get-verifactu-record-by-id.response.dto.ts @@ -0,0 +1,74 @@ +import { MetadataSchema, MoneySchema, PercentageSchema, QuantitySchema } from "@erp/core"; +import { z } from "zod/v4"; + +export const GetVerifactuRecordByIdResponseSchema = z.object({ + id: z.uuid(), + company_id: z.uuid(), + + invoice_number: z.string(), + status: z.string(), + series: z.string(), + + invoice_date: z.string(), + operation_date: z.string(), + + notes: z.string(), + + language_code: z.string(), + currency_code: z.string(), + + customer_id: z.string(), + recipient: z.object({ + id: z.string(), + name: z.string(), + tin: z.string(), + street: z.string(), + street2: z.string(), + city: z.string(), + province: z.string(), + postal_code: z.string(), + country: z.string(), + }), + + taxes: z.string(), + + payment_method: z + .object({ + payment_id: z.string(), + payment_description: z.string(), + }) + .optional(), + + subtotal_amount: MoneySchema, + discount_percentage: PercentageSchema, + discount_amount: MoneySchema, + taxable_amount: MoneySchema, + taxes_amount: MoneySchema, + total_amount: MoneySchema, + + items: z.array( + z.object({ + id: z.uuid(), + isNonValued: z.string(), + position: z.string(), + description: z.string(), + quantity: QuantitySchema, + unit_amount: MoneySchema, + + taxes: z.string(), + + subtotal_amount: MoneySchema, + discount_percentage: PercentageSchema, + discount_amount: MoneySchema, + taxable_amount: MoneySchema, + taxes_amount: MoneySchema, + total_amount: MoneySchema, + }) + ), + + metadata: MetadataSchema.optional(), +}); + +export type GetVerifactuRecordByIdResponseDTO = z.infer< + typeof GetVerifactuRecordByIdResponseSchema +>; diff --git a/modules/verifactu/src/common/dto/request/index.ts b/modules/verifactu/src/common/dto/request/index.ts index b8c00e70..723effe3 100644 --- a/modules/verifactu/src/common/dto/request/index.ts +++ b/modules/verifactu/src/common/dto/request/index.ts @@ -1 +1,2 @@ -export * from "./send-customer-invoice-by-id.request.dto"; +export * from "./get-verifactu-record-by-id.response.dto"; +export * from "./send-invoice-by-id.request.dto"; diff --git a/modules/verifactu/src/common/dto/request/send-customer-invoice-by-id.request.dto.ts b/modules/verifactu/src/common/dto/request/send-customer-invoice-by-id.request.dto.ts deleted file mode 100644 index 5e402160..00000000 --- a/modules/verifactu/src/common/dto/request/send-customer-invoice-by-id.request.dto.ts +++ /dev/null @@ -1,9 +0,0 @@ -import * as z from "zod/v4"; - -export const SendCustomerInvoiceByIdRequestSchema = z.object({ - invoice_id: z.string(), -}); - -export type SendCustomerInvoiceByIdRequestDTO = z.infer< - typeof SendCustomerInvoiceByIdRequestSchema ->; diff --git a/modules/verifactu/src/common/dto/request/send-invoice-by-id.request.dto.ts b/modules/verifactu/src/common/dto/request/send-invoice-by-id.request.dto.ts new file mode 100644 index 00000000..0aab263d --- /dev/null +++ b/modules/verifactu/src/common/dto/request/send-invoice-by-id.request.dto.ts @@ -0,0 +1,7 @@ +import { z } from "zod/v4"; + +export const SendInvoiceByIdRequestSchema = z.object({ + invoice_id: z.string(), +}); + +export type SendInvoiceByIdRequestDTO = z.infer; diff --git a/packages/rdx-ddd/package.json b/packages/rdx-ddd/package.json index 7c3ec8ab..a49ea917 100644 --- a/packages/rdx-ddd/package.json +++ b/packages/rdx-ddd/package.json @@ -20,6 +20,6 @@ "dinero.js": "^1.9.1", "libphonenumber-js": "^1.11.20", "shallow-equal-object": "^1.1.1", - "zod": "^3.24.4" + "zod": "^4.1.11" } } diff --git a/packages/rdx-ddd/src/value-objects/city.ts b/packages/rdx-ddd/src/value-objects/city.ts index 9991eaf6..5457de4a 100644 --- a/packages/rdx-ddd/src/value-objects/city.ts +++ b/packages/rdx-ddd/src/value-objects/city.ts @@ -1,5 +1,5 @@ import { Result } from "@repo/rdx-utils"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; import { translateZodValidationError } from "../helpers"; import { ValueObject } from "./value-object"; diff --git a/packages/rdx-ddd/src/value-objects/country.ts b/packages/rdx-ddd/src/value-objects/country.ts index fcdd95f0..d6eb59c6 100644 --- a/packages/rdx-ddd/src/value-objects/country.ts +++ b/packages/rdx-ddd/src/value-objects/country.ts @@ -1,5 +1,5 @@ import { Result } from "@repo/rdx-utils"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; import { translateZodValidationError } from "../helpers"; import { ValueObject } from "./value-object"; diff --git a/packages/rdx-ddd/src/value-objects/currency-code.ts b/packages/rdx-ddd/src/value-objects/currency-code.ts index c07e4375..67b02237 100644 --- a/packages/rdx-ddd/src/value-objects/currency-code.ts +++ b/packages/rdx-ddd/src/value-objects/currency-code.ts @@ -1,5 +1,5 @@ import { Result } from "@repo/rdx-utils"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; import { translateZodValidationError } from "../helpers"; import { ValueObject } from "./value-object"; diff --git a/packages/rdx-ddd/src/value-objects/email-address.ts b/packages/rdx-ddd/src/value-objects/email-address.ts index 79806b40..d81e811a 100644 --- a/packages/rdx-ddd/src/value-objects/email-address.ts +++ b/packages/rdx-ddd/src/value-objects/email-address.ts @@ -1,5 +1,5 @@ import { Result } from "@repo/rdx-utils"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; import { translateZodValidationError } from "../helpers"; import { ValueObject } from "./value-object"; diff --git a/packages/rdx-ddd/src/value-objects/language-code.ts b/packages/rdx-ddd/src/value-objects/language-code.ts index 0a7d651c..8f34e388 100644 --- a/packages/rdx-ddd/src/value-objects/language-code.ts +++ b/packages/rdx-ddd/src/value-objects/language-code.ts @@ -1,5 +1,5 @@ import { Result } from "@repo/rdx-utils"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; import { translateZodValidationError } from "../helpers"; import { ValueObject } from "./value-object"; diff --git a/packages/rdx-ddd/src/value-objects/name.ts b/packages/rdx-ddd/src/value-objects/name.ts index 5b978b64..eaf98832 100644 --- a/packages/rdx-ddd/src/value-objects/name.ts +++ b/packages/rdx-ddd/src/value-objects/name.ts @@ -1,5 +1,5 @@ import { Result } from "@repo/rdx-utils"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; import { translateZodValidationError } from "../helpers"; import { ValueObject } from "./value-object"; diff --git a/packages/rdx-ddd/src/value-objects/percentage.ts b/packages/rdx-ddd/src/value-objects/percentage.ts index 62169b4c..dd7e7d84 100644 --- a/packages/rdx-ddd/src/value-objects/percentage.ts +++ b/packages/rdx-ddd/src/value-objects/percentage.ts @@ -1,5 +1,5 @@ import { Result } from "@repo/rdx-utils"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; import { translateZodValidationError } from "../helpers"; import { ValueObject } from "./value-object"; diff --git a/packages/rdx-ddd/src/value-objects/phone-number.ts b/packages/rdx-ddd/src/value-objects/phone-number.ts index a0f67d6b..80a16f63 100644 --- a/packages/rdx-ddd/src/value-objects/phone-number.ts +++ b/packages/rdx-ddd/src/value-objects/phone-number.ts @@ -1,6 +1,6 @@ import { Result } from "@repo/rdx-utils"; import { isPossiblePhoneNumber, parsePhoneNumberWithError } from "libphonenumber-js"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; import { translateZodValidationError } from "../helpers"; import { ValueObject } from "./value-object"; diff --git a/packages/rdx-ddd/src/value-objects/postal-code.ts b/packages/rdx-ddd/src/value-objects/postal-code.ts index 1fef267c..854b945f 100644 --- a/packages/rdx-ddd/src/value-objects/postal-code.ts +++ b/packages/rdx-ddd/src/value-objects/postal-code.ts @@ -1,5 +1,5 @@ import { Result } from "@repo/rdx-utils"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; import { translateZodValidationError } from "../helpers"; import { ValueObject } from "./value-object"; diff --git a/packages/rdx-ddd/src/value-objects/province.ts b/packages/rdx-ddd/src/value-objects/province.ts index 6f5b53ff..4f51046b 100644 --- a/packages/rdx-ddd/src/value-objects/province.ts +++ b/packages/rdx-ddd/src/value-objects/province.ts @@ -1,5 +1,5 @@ import { Result } from "@repo/rdx-utils"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; import { translateZodValidationError } from "../helpers"; import { ValueObject } from "./value-object"; diff --git a/packages/rdx-ddd/src/value-objects/quantity.ts b/packages/rdx-ddd/src/value-objects/quantity.ts index e38bce17..33b04b9c 100644 --- a/packages/rdx-ddd/src/value-objects/quantity.ts +++ b/packages/rdx-ddd/src/value-objects/quantity.ts @@ -1,5 +1,5 @@ import { Result } from "@repo/rdx-utils"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; import { translateZodValidationError } from "../helpers"; import { ValueObject } from "./value-object"; diff --git a/packages/rdx-ddd/src/value-objects/slug.ts b/packages/rdx-ddd/src/value-objects/slug.ts index 28241e53..d15f5e09 100644 --- a/packages/rdx-ddd/src/value-objects/slug.ts +++ b/packages/rdx-ddd/src/value-objects/slug.ts @@ -1,5 +1,5 @@ import { Result } from "@repo/rdx-utils"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; import { translateZodValidationError } from "../helpers"; import { ValueObject } from "./value-object"; diff --git a/packages/rdx-ddd/src/value-objects/street.ts b/packages/rdx-ddd/src/value-objects/street.ts index 27d23605..eee8c391 100644 --- a/packages/rdx-ddd/src/value-objects/street.ts +++ b/packages/rdx-ddd/src/value-objects/street.ts @@ -1,5 +1,5 @@ import { Result } from "@repo/rdx-utils"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; import { translateZodValidationError } from "../helpers"; import { ValueObject } from "./value-object"; diff --git a/packages/rdx-ddd/src/value-objects/tax-code.ts b/packages/rdx-ddd/src/value-objects/tax-code.ts index 0229a3c0..abb0ea19 100644 --- a/packages/rdx-ddd/src/value-objects/tax-code.ts +++ b/packages/rdx-ddd/src/value-objects/tax-code.ts @@ -1,5 +1,5 @@ import { Result } from "@repo/rdx-utils"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; import { translateZodValidationError } from "../helpers"; import { ValueObject } from "./value-object"; diff --git a/packages/rdx-ddd/src/value-objects/text-value.ts b/packages/rdx-ddd/src/value-objects/text-value.ts index c34a2360..5964697d 100644 --- a/packages/rdx-ddd/src/value-objects/text-value.ts +++ b/packages/rdx-ddd/src/value-objects/text-value.ts @@ -1,5 +1,5 @@ import { Result } from "@repo/rdx-utils"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; import { translateZodValidationError } from "../helpers"; import { ValueObject } from "./value-object"; diff --git a/packages/rdx-ddd/src/value-objects/tin-number.ts b/packages/rdx-ddd/src/value-objects/tin-number.ts index a255698e..16d065f1 100644 --- a/packages/rdx-ddd/src/value-objects/tin-number.ts +++ b/packages/rdx-ddd/src/value-objects/tin-number.ts @@ -1,5 +1,5 @@ import { Result } from "@repo/rdx-utils"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; import { translateZodValidationError } from "../helpers"; import { ValueObject } from "./value-object"; diff --git a/packages/rdx-ddd/src/value-objects/unique-id.ts b/packages/rdx-ddd/src/value-objects/unique-id.ts index 81fd889b..f7cb2f96 100644 --- a/packages/rdx-ddd/src/value-objects/unique-id.ts +++ b/packages/rdx-ddd/src/value-objects/unique-id.ts @@ -1,5 +1,5 @@ import { Result, generateUUIDv4 } from "@repo/rdx-utils"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; import { translateZodValidationError } from "../helpers"; import { ValueObject } from "./value-object"; diff --git a/packages/rdx-ddd/src/value-objects/url-address.ts b/packages/rdx-ddd/src/value-objects/url-address.ts index b474d41f..03893513 100644 --- a/packages/rdx-ddd/src/value-objects/url-address.ts +++ b/packages/rdx-ddd/src/value-objects/url-address.ts @@ -1,5 +1,5 @@ import { Result } from "@repo/rdx-utils"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; import { translateZodValidationError } from "../helpers"; import { ValueObject } from "./value-object"; diff --git a/packages/rdx-ddd/src/value-objects/utc-date.ts b/packages/rdx-ddd/src/value-objects/utc-date.ts index 1656919f..ff0f1319 100644 --- a/packages/rdx-ddd/src/value-objects/utc-date.ts +++ b/packages/rdx-ddd/src/value-objects/utc-date.ts @@ -1,5 +1,5 @@ import { Result } from "@repo/rdx-utils"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; import { translateZodValidationError } from "../helpers"; import { ValueObject } from "./value-object"; diff --git a/packages/rdx-ui/package.json b/packages/rdx-ui/package.json index f3de3530..46aa7069 100644 --- a/packages/rdx-ui/package.json +++ b/packages/rdx-ui/package.json @@ -20,7 +20,7 @@ "i18next": "^25.1.1", "react-hook-form": "^7.58.1", "typescript": "^5.8.3", - "zod": "^3.25.67" + "zod": "^4.1.11" }, "devDependencies": { "@biomejs/biome": "1.9.4", @@ -59,6 +59,6 @@ "react-router-dom": "^6.26.0", "recharts": "^2.15.3", "sonner": "^2.0.3", - "zod": "^3.24.4" + "zod": "^4.1.11" } } diff --git a/packages/rdx-ui/src/components/layout/data-table.tsx b/packages/rdx-ui/src/components/layout/data-table.tsx index 40d9e0c7..55a1a1fd 100644 --- a/packages/rdx-ui/src/components/layout/data-table.tsx +++ b/packages/rdx-ui/src/components/layout/data-table.tsx @@ -51,7 +51,7 @@ import { import * as React from "react"; import { Area, AreaChart, CartesianGrid, XAxis } from "recharts"; import { toast } from "sonner"; -import * as z from "zod/v4"; +import { z } from "zod/v4"; import { Badge } from "@repo/shadcn-ui/components/badge"; import { Button } from "@repo/shadcn-ui/components/button"; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 80151aa3..bf46d81c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -132,8 +132,8 @@ importers: specifier: ^5.0.0 version: 5.0.0(winston@3.17.0) zod: - specifier: ^3.25.67 - version: 3.25.67 + specifier: ^4.1.11 + version: 4.1.11 devDependencies: '@biomejs/biome': specifier: 1.9.4 @@ -344,8 +344,8 @@ importers: specifier: ^6.37.5 version: 6.37.7(mysql2@3.14.1) zod: - specifier: ^3.25.67 - version: 3.25.67 + specifier: ^4.1.11 + version: 4.1.11 devDependencies: '@biomejs/biome': specifier: 1.9.4 @@ -368,6 +368,9 @@ importers: modules/core: dependencies: + '@hookform/resolvers': + specifier: ^5.0.1 + version: 5.1.1(react-hook-form@7.58.1(react@19.1.0)) '@repo/rdx-criteria': specifier: workspace:* version: link:../../packages/rdx-criteria @@ -420,8 +423,8 @@ importers: specifier: ^6.37.5 version: 6.37.7(mysql2@3.14.1) zod: - specifier: ^3.25.67 - version: 3.25.67 + specifier: ^4.1.11 + version: 4.1.11 devDependencies: '@types/axios': specifier: ^0.14.4 @@ -541,8 +544,8 @@ importers: specifier: ^6.37.5 version: 6.37.7(mysql2@3.14.1) zod: - specifier: ^3.25.67 - version: 3.25.67 + specifier: ^4.1.11 + version: 4.1.11 devDependencies: '@hookform/devtools': specifier: ^4.4.0 @@ -641,8 +644,8 @@ importers: specifier: ^10.0.5 version: 10.0.5(react@19.1.0) zod: - specifier: ^3.25.67 - version: 3.25.67 + specifier: ^4.1.11 + version: 4.1.11 devDependencies: '@types/express': specifier: ^4.17.21 @@ -668,6 +671,12 @@ importers: '@erp/core': specifier: workspace:* version: link:../core + '@erp/customer-invoices': + specifier: workspace:* + version: link:../customer-invoices + '@repo/rdx-criteria': + specifier: workspace:* + version: link:../../packages/rdx-criteria '@repo/rdx-ddd': specifier: workspace:* version: link:../../packages/rdx-ddd @@ -683,6 +692,9 @@ importers: sequelize: specifier: ^6.37.5 version: 6.37.7(mysql2@3.14.1) + zod: + specifier: ^4.1.11 + version: 4.1.11 devDependencies: '@types/express': specifier: ^4.17.21 @@ -716,8 +728,8 @@ importers: specifier: ^1.1.1 version: 1.1.1 zod: - specifier: ^3.24.4 - version: 3.25.67 + specifier: ^4.1.11 + version: 4.1.11 devDependencies: '@repo/typescript-config': specifier: workspace:* @@ -814,8 +826,8 @@ importers: specifier: ^2.0.3 version: 2.0.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0) zod: - specifier: ^3.24.4 - version: 3.25.67 + specifier: ^4.1.11 + version: 4.1.11 devDependencies: '@biomejs/biome': specifier: 1.9.4 @@ -6777,6 +6789,9 @@ packages: zod@3.25.67: resolution: {integrity: sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==} + zod@4.1.11: + resolution: {integrity: sha512-WPsqwxITS2tzx1bzhIKsEs19ABD5vmCVa4xBo2tq/SrV4RNZtfws1EnCWQXM6yh8bD08a1idvkB5MZSBiZsjwg==} + snapshots: '@adobe/css-tools@4.3.3': {} @@ -12902,3 +12917,5 @@ snapshots: yoctocolors-cjs@2.1.2: {} zod@3.25.67: {} + + zod@4.1.11: {}