.
This commit is contained in:
parent
00b892b91b
commit
71b4dc1d06
@ -39,6 +39,7 @@
|
|||||||
"@erp/core": "workspace:*",
|
"@erp/core": "workspace:*",
|
||||||
"@erp/customers": "workspace:*",
|
"@erp/customers": "workspace:*",
|
||||||
"@hookform/resolvers": "^5.2.2",
|
"@hookform/resolvers": "^5.2.2",
|
||||||
|
"@lglab/react-qr-code": "^1.4.10",
|
||||||
"@repo/i18next": "workspace:*",
|
"@repo/i18next": "workspace:*",
|
||||||
"@repo/rdx-criteria": "workspace:*",
|
"@repo/rdx-criteria": "workspace:*",
|
||||||
"@repo/rdx-ddd": "workspace:*",
|
"@repo/rdx-ddd": "workspace:*",
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { UtcDate } from "@repo/rdx-ddd";
|
||||||
import { Maybe, Result } from "@repo/rdx-utils";
|
import { Maybe, Result } from "@repo/rdx-utils";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -102,7 +103,7 @@ export class ProformaToIssuedInvoiceConverter implements IProformaToIssuedInvoic
|
|||||||
|
|
||||||
invoiceNumber: proforma.invoiceNumber,
|
invoiceNumber: proforma.invoiceNumber,
|
||||||
|
|
||||||
invoiceDate: proforma.invoiceDate,
|
invoiceDate: UtcDate.today(), // La fecha de la factura es la fecha de emisión, no la de la proforma
|
||||||
operationDate: proforma.operationDate,
|
operationDate: proforma.operationDate,
|
||||||
|
|
||||||
description: proforma.description,
|
description: proforma.description,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import type { Tax } from "@erp/core/api";
|
import type { Tax } from "@erp/core/api";
|
||||||
import { ValueObject } from "@repo/rdx-ddd";
|
import { ValueObject } from "@repo/rdx-ddd";
|
||||||
import { type Maybe, Result } from "@repo/rdx-utils";
|
import { Maybe, Result } from "@repo/rdx-utils";
|
||||||
|
|
||||||
import { ItemAmount } from "../../common/value-objects";
|
import { ItemAmount } from "../../common/value-objects";
|
||||||
|
|
||||||
@ -32,6 +32,19 @@ export class ProformaItemTaxes
|
|||||||
return Result.ok(new ProformaItemTaxes(props));
|
return Result.ok(new ProformaItemTaxes(props));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crea una instancia "vacía" (sin impuestos)
|
||||||
|
* - Evita duplicación de lógica de construcción
|
||||||
|
* - Centraliza el concepto de "sin impuestos"
|
||||||
|
*/
|
||||||
|
static empty(): ProformaItemTaxes {
|
||||||
|
return new ProformaItemTaxes({
|
||||||
|
iva: Maybe.none(),
|
||||||
|
rec: Maybe.none(),
|
||||||
|
retention: Maybe.none(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
toKey(): string {
|
toKey(): string {
|
||||||
const ivaCode = this.props.iva.match(
|
const ivaCode = this.props.iva.match(
|
||||||
(iva) => iva.code,
|
(iva) => iva.code,
|
||||||
|
|||||||
@ -283,12 +283,6 @@ export class IssuedInvoiceRepository
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
// Reemplazar findAndCountAll por findAll + count (más control y mejor rendimiento)
|
|
||||||
/*const { rows, count } = await CustomerInvoiceModel.findAndCountAll({
|
|
||||||
...query,
|
|
||||||
transaction,
|
|
||||||
});*/
|
|
||||||
|
|
||||||
const [rows, count] = await Promise.all([
|
const [rows, count] = await Promise.all([
|
||||||
CustomerInvoiceModel.findAll({
|
CustomerInvoiceModel.findAll({
|
||||||
...query,
|
...query,
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
CreateProformaRequestSchema,
|
CreateProformaRequestSchema,
|
||||||
GetProformaByIdRequestSchema,
|
GetProformaByIdRequestSchema,
|
||||||
IssueProformaByIdResponseSchema,
|
IssueProformaByIdParamsRequestSchema,
|
||||||
ListProformasRequestSchema,
|
ListProformasRequestSchema,
|
||||||
ReportProformaByIdParamsRequestSchema,
|
ReportProformaByIdParamsRequestSchema,
|
||||||
ReportProformaByIdQueryRequestSchema,
|
ReportProformaByIdQueryRequestSchema,
|
||||||
@ -150,7 +150,7 @@ export const proformasRouter = (params: StartParams) => {
|
|||||||
"/:proforma_id/issue",
|
"/:proforma_id/issue",
|
||||||
//checkTabContext,
|
//checkTabContext,
|
||||||
|
|
||||||
validateRequest(IssueProformaByIdResponseSchema, "params"),
|
validateRequest(IssueProformaByIdParamsRequestSchema, "params"),
|
||||||
|
|
||||||
(req: Request, res: Response, next: NextFunction) => {
|
(req: Request, res: Response, next: NextFunction) => {
|
||||||
const useCase = deps.useCases.issueProforma(publicServices);
|
const useCase = deps.useCases.issueProforma(publicServices);
|
||||||
|
|||||||
@ -3,12 +3,12 @@ import { useMemo, useState } from "react";
|
|||||||
|
|
||||||
import type {
|
import type {
|
||||||
IssuedInvoiceList,
|
IssuedInvoiceList,
|
||||||
IssuedInvoiceStatus,
|
|
||||||
ListIssuedInvoicesByCriteriaParams,
|
ListIssuedInvoicesByCriteriaParams,
|
||||||
|
VerifactuRecordStatus,
|
||||||
} from "../../shared";
|
} from "../../shared";
|
||||||
import { useIssuedInvoiceListQuery } from "../../shared/";
|
import { useIssuedInvoiceListQuery } from "../../shared/";
|
||||||
|
|
||||||
type IssuedInvoiceListStatusFilter = "all" | IssuedInvoiceStatus;
|
type VerifactuRecordListStatusFilter = "all" | VerifactuRecordStatus;
|
||||||
|
|
||||||
const EMPTY_ISSUED_INVOICES_LIST: IssuedInvoiceList = {
|
const EMPTY_ISSUED_INVOICES_LIST: IssuedInvoiceList = {
|
||||||
items: [],
|
items: [],
|
||||||
@ -22,7 +22,8 @@ export const useIssuedInvoiceListController = () => {
|
|||||||
const [pageIndex, setPageIndex] = useState(0);
|
const [pageIndex, setPageIndex] = useState(0);
|
||||||
const [pageSize, setPageSize] = useState(5);
|
const [pageSize, setPageSize] = useState(5);
|
||||||
const [search, setSearch] = useState("");
|
const [search, setSearch] = useState("");
|
||||||
const [statusFilter, setStatusFilter] = useState<IssuedInvoiceListStatusFilter>("all");
|
const [verifactuStatusFilter, setVerifactuStatusFilter] =
|
||||||
|
useState<VerifactuRecordListStatusFilter>("all");
|
||||||
|
|
||||||
const debouncedSearch = useDebounce(search, 300);
|
const debouncedSearch = useDebounce(search, 300);
|
||||||
|
|
||||||
@ -33,17 +34,20 @@ export const useIssuedInvoiceListController = () => {
|
|||||||
pageSize,
|
pageSize,
|
||||||
order: "desc",
|
order: "desc",
|
||||||
orderBy: "invoice_date",
|
orderBy: "invoice_date",
|
||||||
filters: status === "all" ? [] : [{ field: "status", operator: "eq", value: status }],
|
filters:
|
||||||
|
verifactuStatusFilter === "all"
|
||||||
|
? []
|
||||||
|
: [{ field: "verifactu.status", operator: "eq", value: verifactuStatusFilter }],
|
||||||
}),
|
}),
|
||||||
[debouncedSearch, pageIndex, pageSize, status]
|
[debouncedSearch, pageIndex, pageSize, verifactuStatusFilter]
|
||||||
);
|
);
|
||||||
|
|
||||||
const query = useIssuedInvoiceListQuery({ criteria });
|
const query = useIssuedInvoiceListQuery({ criteria });
|
||||||
|
|
||||||
const setStatusFilterValue = (value: string) => {
|
const setStatusFilterValue = (value: string) => {
|
||||||
const nextValue = (value || "all") as IssuedInvoiceListStatusFilter;
|
const nextValue = (value || "all") as VerifactuRecordListStatusFilter;
|
||||||
|
|
||||||
setStatusFilter((prev) => {
|
setVerifactuStatusFilter((prev) => {
|
||||||
if (prev === nextValue) return prev;
|
if (prev === nextValue) return prev;
|
||||||
|
|
||||||
// Sólo si la búsqueda realmente cambia,
|
// Sólo si la búsqueda realmente cambia,
|
||||||
@ -95,7 +99,7 @@ export const useIssuedInvoiceListController = () => {
|
|||||||
search,
|
search,
|
||||||
setSearchValue,
|
setSearchValue,
|
||||||
|
|
||||||
statusFilter,
|
statusFilter: verifactuStatusFilter,
|
||||||
setStatusFilter: setStatusFilterValue,
|
setStatusFilter: setStatusFilterValue,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { formatDate } from "@erp/core/client";
|
import { formatDate } from "@erp/core/client";
|
||||||
|
import { ReactQRCode } from "@lglab/react-qr-code";
|
||||||
import { DataTableColumnHeader } from "@repo/rdx-ui/components";
|
import { DataTableColumnHeader } from "@repo/rdx-ui/components";
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
@ -16,7 +17,6 @@ import {
|
|||||||
import type { ColumnDef } from "@tanstack/react-table";
|
import type { ColumnDef } from "@tanstack/react-table";
|
||||||
import { DownloadIcon, FileDownIcon, MailIcon, MoreVerticalIcon, QrCodeIcon } from "lucide-react";
|
import { DownloadIcon, FileDownIcon, MailIcon, MoreVerticalIcon, QrCodeIcon } from "lucide-react";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import QrCode from "react-qr-code";
|
|
||||||
|
|
||||||
import { useTranslation } from "../../../../../i18n";
|
import { useTranslation } from "../../../../../i18n";
|
||||||
import type { IssuedInvoiceListRow } from "../../../../shared";
|
import type { IssuedInvoiceListRow } from "../../../../shared";
|
||||||
@ -115,7 +115,17 @@ export function useIssuedInvoicesGridColumns(
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<TooltipContent className="m-0 p-3">
|
<TooltipContent className="m-0 p-3">
|
||||||
<QrCode className="bg-white p-8" value={verifactu.url} />
|
<div className="border-2 border-black">
|
||||||
|
<ReactQRCode
|
||||||
|
background="#fff"
|
||||||
|
dataModulesSettings={{ color: "#000" }}
|
||||||
|
finderPatternInnerSettings={{ color: "#000" }}
|
||||||
|
finderPatternOuterSettings={{ color: "#000" }}
|
||||||
|
marginSize={8}
|
||||||
|
size={256}
|
||||||
|
value={verifactu.url}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -489,6 +489,9 @@ importers:
|
|||||||
'@hookform/resolvers':
|
'@hookform/resolvers':
|
||||||
specifier: ^5.2.2
|
specifier: ^5.2.2
|
||||||
version: 5.2.2(react-hook-form@7.72.1(react@19.2.5))
|
version: 5.2.2(react-hook-form@7.72.1(react@19.2.5))
|
||||||
|
'@lglab/react-qr-code':
|
||||||
|
specifier: ^1.4.10
|
||||||
|
version: 1.4.10(react@19.2.5)
|
||||||
'@repo/i18next':
|
'@repo/i18next':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../packages/i18n
|
version: link:../../packages/i18n
|
||||||
@ -2226,6 +2229,11 @@ packages:
|
|||||||
'@jridgewell/trace-mapping@0.3.9':
|
'@jridgewell/trace-mapping@0.3.9':
|
||||||
resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
|
resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
|
||||||
|
|
||||||
|
'@lglab/react-qr-code@1.4.10':
|
||||||
|
resolution: {integrity: sha512-B+VOFfvnx+NqVaJqDbh1glHEU/rJR/3XtINcvM3qC9DW292GbaLNoa2OvRlXHYUQdsWcdzNzOcPzT39P1O8uJg==}
|
||||||
|
peerDependencies:
|
||||||
|
react: ^18 || ^19
|
||||||
|
|
||||||
'@modelcontextprotocol/sdk@1.29.0':
|
'@modelcontextprotocol/sdk@1.29.0':
|
||||||
resolution: {integrity: sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ==}
|
resolution: {integrity: sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@ -8015,6 +8023,10 @@ snapshots:
|
|||||||
'@jridgewell/resolve-uri': 3.1.2
|
'@jridgewell/resolve-uri': 3.1.2
|
||||||
'@jridgewell/sourcemap-codec': 1.5.5
|
'@jridgewell/sourcemap-codec': 1.5.5
|
||||||
|
|
||||||
|
'@lglab/react-qr-code@1.4.10(react@19.2.5)':
|
||||||
|
dependencies:
|
||||||
|
react: 19.2.5
|
||||||
|
|
||||||
'@modelcontextprotocol/sdk@1.29.0(zod@3.25.76)':
|
'@modelcontextprotocol/sdk@1.29.0(zod@3.25.76)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@hono/node-server': 1.19.13(hono@4.12.12)
|
'@hono/node-server': 1.19.13(hono@4.12.12)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user