@asteby/metacore-runtime-react 47.1.0 → 48.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/dist/action-modal-dispatcher.d.ts.map +1 -1
- package/dist/action-modal-dispatcher.js +24 -4
- package/dist/business/catalog-product-search.d.ts +25 -0
- package/dist/business/catalog-product-search.d.ts.map +1 -0
- package/dist/business/catalog-product-search.js +57 -0
- package/dist/business/catalog.d.ts.map +1 -1
- package/dist/business/catalog.js +2 -0
- package/dist/business/document-editor-model.d.ts +107 -0
- package/dist/business/document-editor-model.d.ts.map +1 -0
- package/dist/business/document-editor-model.js +279 -0
- package/dist/business/document-editor-panels.d.ts +64 -0
- package/dist/business/document-editor-panels.d.ts.map +1 -0
- package/dist/business/document-editor-panels.js +58 -0
- package/dist/business/document-editor.d.ts +27 -0
- package/dist/business/document-editor.d.ts.map +1 -0
- package/dist/business/document-editor.js +445 -0
- package/dist/business/document-lines.d.ts.map +1 -1
- package/dist/business/document-lines.js +5 -1
- package/dist/business/index.d.ts +5 -0
- package/dist/business/index.d.ts.map +1 -1
- package/dist/business/index.js +5 -0
- package/dist/business/line-items.d.ts +7 -0
- package/dist/business/line-items.d.ts.map +1 -1
- package/dist/business/line-items.js +6 -1
- package/dist/business/payment-allocator.d.ts +19 -0
- package/dist/business/payment-allocator.d.ts.map +1 -0
- package/dist/business/payment-allocator.js +31 -0
- package/dist/business/product-search.d.ts +4 -0
- package/dist/business/product-search.d.ts.map +1 -1
- package/dist/dialogs/dynamic-record.d.ts.map +1 -1
- package/dist/dialogs/dynamic-record.js +14 -7
- package/dist/document-form-dialog.d.ts +31 -2
- package/dist/document-form-dialog.d.ts.map +1 -1
- package/dist/document-form-dialog.js +43 -11
- package/dist/dynamic-columns-helpers.d.ts +9 -0
- package/dist/dynamic-columns-helpers.d.ts.map +1 -1
- package/dist/dynamic-columns-helpers.js +19 -0
- package/dist/dynamic-columns.d.ts +8 -2
- package/dist/dynamic-columns.d.ts.map +1 -1
- package/dist/dynamic-columns.js +21 -5
- package/dist/dynamic-crud-page.d.ts +6 -0
- package/dist/dynamic-crud-page.d.ts.map +1 -1
- package/dist/dynamic-crud-page.js +14 -5
- package/dist/dynamic-form-schema.d.ts.map +1 -1
- package/dist/dynamic-form-schema.js +15 -3
- package/dist/dynamic-form.d.ts +16 -1
- package/dist/dynamic-form.d.ts.map +1 -1
- package/dist/dynamic-form.js +78 -20
- package/dist/dynamic-kanban.d.ts +9 -3
- package/dist/dynamic-kanban.d.ts.map +1 -1
- package/dist/dynamic-kanban.js +31 -12
- package/dist/dynamic-relation-helpers.d.ts.map +1 -1
- package/dist/dynamic-relation-helpers.js +8 -0
- package/dist/dynamic-relation.js +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -2
- package/dist/installed-addons-context.d.ts +15 -0
- package/dist/installed-addons-context.d.ts.map +1 -0
- package/dist/installed-addons-context.js +39 -0
- package/dist/org-runtime-context.d.ts +8 -0
- package/dist/org-runtime-context.d.ts.map +1 -1
- package/dist/org-runtime-context.js +8 -0
- package/dist/org-runtime-provider.d.ts +3 -1
- package/dist/org-runtime-provider.d.ts.map +1 -1
- package/dist/org-runtime-provider.js +3 -3
- package/dist/primitives/aging.d.ts +34 -0
- package/dist/primitives/aging.d.ts.map +1 -0
- package/dist/primitives/aging.js +48 -0
- package/dist/primitives/allocation.d.ts +42 -0
- package/dist/primitives/allocation.d.ts.map +1 -0
- package/dist/primitives/allocation.js +59 -0
- package/dist/primitives/approvals.d.ts +71 -0
- package/dist/primitives/approvals.d.ts.map +1 -0
- package/dist/primitives/approvals.js +48 -0
- package/dist/primitives/contributions.d.ts +82 -0
- package/dist/primitives/contributions.d.ts.map +1 -0
- package/dist/primitives/contributions.js +126 -0
- package/dist/primitives/document-kinds.d.ts +25 -0
- package/dist/primitives/document-kinds.d.ts.map +1 -0
- package/dist/primitives/document-kinds.js +26 -0
- package/dist/primitives/index.d.ts +8 -0
- package/dist/primitives/index.d.ts.map +1 -0
- package/dist/primitives/index.js +23 -0
- package/dist/primitives/panels.d.ts +68 -0
- package/dist/primitives/panels.d.ts.map +1 -0
- package/dist/primitives/panels.js +3 -0
- package/dist/primitives/use-contributions.d.ts +15 -0
- package/dist/primitives/use-contributions.d.ts.map +1 -0
- package/dist/primitives/use-contributions.js +30 -0
- package/dist/record-prefill-bar.d.ts +11 -0
- package/dist/record-prefill-bar.d.ts.map +1 -0
- package/dist/record-prefill-bar.js +33 -0
- package/dist/types.d.ts +102 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/catalog-product-search.test.ts +61 -0
- package/src/__tests__/document-editor-model.test.ts +167 -0
- package/src/__tests__/document-editor.test.tsx +261 -0
- package/src/__tests__/document-form-dialog.test.tsx +118 -3
- package/src/__tests__/dynamic-form-select-edit.test.tsx +155 -0
- package/src/__tests__/dynamic-kanban.test.tsx +24 -3
- package/src/__tests__/dynamic-record-extension-label.test.tsx +88 -0
- package/src/__tests__/installed-addons-context.test.tsx +50 -0
- package/src/__tests__/line-item-totals.test.ts +28 -0
- package/src/__tests__/primitives-federated.test.tsx +156 -0
- package/src/__tests__/primitives.test.ts +224 -0
- package/src/__tests__/record-prefill-bar.test.tsx +50 -0
- package/src/action-modal-dispatcher.tsx +47 -4
- package/src/business/catalog-product-search.ts +87 -0
- package/src/business/catalog.ts +2 -0
- package/src/business/document-editor-model.ts +325 -0
- package/src/business/document-editor-panels.tsx +164 -0
- package/src/business/document-editor.tsx +727 -0
- package/src/business/document-lines.ts +5 -1
- package/src/business/index.ts +5 -0
- package/src/business/line-items.ts +15 -1
- package/src/business/payment-allocator.tsx +110 -0
- package/src/business/product-search.ts +4 -0
- package/src/dialogs/dynamic-record.tsx +29 -6
- package/src/document-form-dialog.tsx +92 -12
- package/src/dynamic-columns-helpers.ts +22 -0
- package/src/dynamic-columns.tsx +23 -6
- package/src/dynamic-crud-page.tsx +22 -3
- package/src/dynamic-form-schema.ts +15 -2
- package/src/dynamic-form.tsx +117 -39
- package/src/dynamic-kanban.tsx +34 -7
- package/src/dynamic-relation-helpers.ts +9 -0
- package/src/dynamic-relation.tsx +7 -2
- package/src/index.ts +21 -1
- package/src/installed-addons-context.tsx +58 -0
- package/src/org-runtime-context.ts +10 -0
- package/src/org-runtime-provider.tsx +7 -2
- package/src/primitives/aging.ts +76 -0
- package/src/primitives/allocation.ts +104 -0
- package/src/primitives/approvals.ts +103 -0
- package/src/primitives/contributions.ts +208 -0
- package/src/primitives/document-kinds.ts +62 -0
- package/src/primitives/index.ts +23 -0
- package/src/primitives/panels.ts +59 -0
- package/src/primitives/use-contributions.ts +42 -0
- package/src/record-prefill-bar.tsx +62 -0
- package/src/row-action-stage-gate.test.ts +33 -0
- package/src/types.ts +101 -0
|
@@ -18,17 +18,21 @@ export function applyProductToLine(line, product, variant, opts = {}) {
|
|
|
18
18
|
const list = variant?.price ?? product.price;
|
|
19
19
|
const cost = variant?.cost ?? product.cost;
|
|
20
20
|
const catalog = source === 'cost' ? (cost ?? list) : list;
|
|
21
|
+
// Nunca cantidad 0: un renglón vacío (o con la celda borrada) entra con 1.
|
|
22
|
+
const qty = opts.quantity ?? toAmount(line.quantity);
|
|
21
23
|
return {
|
|
22
24
|
...line,
|
|
23
25
|
kind: 'item',
|
|
24
26
|
product_id: variant?.id ?? product.id,
|
|
25
27
|
sku: variant?.sku ?? product.sku,
|
|
26
28
|
description: variant ? `${product.name} · ${variant.label}` : product.name,
|
|
27
|
-
quantity:
|
|
29
|
+
quantity: qty !== 0 ? qty : 1,
|
|
28
30
|
unit_price: priceFromProduct(product, variant, source),
|
|
29
31
|
catalog_price: catalog,
|
|
30
32
|
cost,
|
|
31
33
|
tax_rate: product.tax_rate ?? line.tax_rate ?? 0,
|
|
34
|
+
unit: product.unit ?? line.unit,
|
|
35
|
+
extensions: product.extensions ? { ...(line.extensions ?? {}), ...product.extensions } : line.extensions,
|
|
32
36
|
available: availableStock(src, opts.warehouseId) ?? availableStock(product, opts.warehouseId),
|
|
33
37
|
};
|
|
34
38
|
}
|
package/dist/business/index.d.ts
CHANGED
|
@@ -19,4 +19,9 @@ export * from './inspection-checklist';
|
|
|
19
19
|
export * from './vehicle-picker';
|
|
20
20
|
export * from './relate-documents';
|
|
21
21
|
export * from './print-send-dialog';
|
|
22
|
+
export * from './catalog-product-search';
|
|
23
|
+
export * from './document-editor-model';
|
|
24
|
+
export * from './document-editor-panels';
|
|
25
|
+
export * from './payment-allocator';
|
|
26
|
+
export * from './document-editor';
|
|
22
27
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/business/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAA;AACxB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,YAAY,CAAA;AAC1B,cAAc,cAAc,CAAA;AAC5B,cAAc,kBAAkB,CAAA;AAChC,cAAc,qBAAqB,CAAA;AACnC,cAAc,WAAW,CAAA;AACzB,cAAc,mBAAmB,CAAA;AACjC,cAAc,UAAU,CAAA;AACxB,cAAc,sBAAsB,CAAA;AACpC,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,mBAAmB,CAAA;AACjC,cAAc,WAAW,CAAA;AACzB,cAAc,UAAU,CAAA;AACxB,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA;AAC5B,cAAc,wBAAwB,CAAA;AACtC,cAAc,kBAAkB,CAAA;AAChC,cAAc,oBAAoB,CAAA;AAClC,cAAc,qBAAqB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/business/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAA;AACxB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,YAAY,CAAA;AAC1B,cAAc,cAAc,CAAA;AAC5B,cAAc,kBAAkB,CAAA;AAChC,cAAc,qBAAqB,CAAA;AACnC,cAAc,WAAW,CAAA;AACzB,cAAc,mBAAmB,CAAA;AACjC,cAAc,UAAU,CAAA;AACxB,cAAc,sBAAsB,CAAA;AACpC,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,mBAAmB,CAAA;AACjC,cAAc,WAAW,CAAA;AACzB,cAAc,UAAU,CAAA;AACxB,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA;AAC5B,cAAc,wBAAwB,CAAA;AACtC,cAAc,kBAAkB,CAAA;AAChC,cAAc,oBAAoB,CAAA;AAClC,cAAc,qBAAqB,CAAA;AACnC,cAAc,0BAA0B,CAAA;AACxC,cAAc,yBAAyB,CAAA;AACvC,cAAc,0BAA0B,CAAA;AACxC,cAAc,qBAAqB,CAAA;AACnC,cAAc,mBAAmB,CAAA"}
|
package/dist/business/index.js
CHANGED
|
@@ -19,3 +19,8 @@ export * from './inspection-checklist';
|
|
|
19
19
|
export * from './vehicle-picker';
|
|
20
20
|
export * from './relate-documents';
|
|
21
21
|
export * from './print-send-dialog';
|
|
22
|
+
export * from './catalog-product-search';
|
|
23
|
+
export * from './document-editor-model';
|
|
24
|
+
export * from './document-editor-panels';
|
|
25
|
+
export * from './payment-allocator';
|
|
26
|
+
export * from './document-editor';
|
|
@@ -30,6 +30,13 @@ export interface LineItem {
|
|
|
30
30
|
dot?: string;
|
|
31
31
|
/** Existencia disponible conocida (para la política de sobreventa). */
|
|
32
32
|
available?: number;
|
|
33
|
+
/**
|
|
34
|
+
* Campos de extensión del renglón que aportan OTROS addons (p. ej.
|
|
35
|
+
* fiscal_mexico: `mx_clave_prod_serv`, `mx_clave_unidad`), copiados del
|
|
36
|
+
* producto al elegirlo. Viajan en `fiscal_data` (la bolsa de ModelExtension
|
|
37
|
+
* del host) — el SDK no conoce sus claves.
|
|
38
|
+
*/
|
|
39
|
+
extensions?: Record<string, string>;
|
|
33
40
|
}
|
|
34
41
|
/** Qué hacer si `quantity > available`. */
|
|
35
42
|
export type StockPolicy = 'allow' | 'warn' | 'block';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"line-items.d.ts","sourceRoot":"","sources":["../../src/business/line-items.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAAA;AAEtD,MAAM,WAAW,QAAQ;IACrB,oDAAoD;IACpD,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,YAAY,CAAA;IAClB,2DAA2D;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAA;IAChB,8DAA8D;IAC9D,aAAa,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAA;IACpC,kFAAkF;IAClF,QAAQ,EAAE,MAAM,CAAA;IAChB,4EAA4E;IAC5E,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,0EAA0E;IAC1E,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,qFAAqF;IACrF,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,qFAAqF;IACrF,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"line-items.d.ts","sourceRoot":"","sources":["../../src/business/line-items.ts"],"names":[],"mappings":"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"}
|
|
@@ -144,6 +144,8 @@ export function serializeLineItems(lines) {
|
|
|
144
144
|
if (typeof v === 'string' && v.trim())
|
|
145
145
|
out[k] = v.trim();
|
|
146
146
|
}
|
|
147
|
+
if (l.extensions && Object.keys(l.extensions).length > 0)
|
|
148
|
+
out.fiscal_data = { ...l.extensions };
|
|
147
149
|
}
|
|
148
150
|
return out;
|
|
149
151
|
});
|
|
@@ -161,7 +163,7 @@ export function parseLineItems(rows) {
|
|
|
161
163
|
product_id: str(o.product_id),
|
|
162
164
|
sku: str(o.sku),
|
|
163
165
|
description: typeof o.description === 'string' ? o.description : '',
|
|
164
|
-
quantity: o.quantity == null ? 1 : toAmount(o.quantity),
|
|
166
|
+
quantity: o.quantity == null || o.quantity === '' ? 1 : toAmount(o.quantity),
|
|
165
167
|
unit_price: toAmount(o.unit_price),
|
|
166
168
|
discount: toAmount(o.discount),
|
|
167
169
|
discount_kind: o.discount_kind === 'amount' ? 'amount' : undefined,
|
|
@@ -173,6 +175,9 @@ export function parseLineItems(rows) {
|
|
|
173
175
|
technician_id: str(o.technician_id),
|
|
174
176
|
lot: str(o.lot),
|
|
175
177
|
dot: str(o.dot),
|
|
178
|
+
extensions: o.fiscal_data && typeof o.fiscal_data === 'object'
|
|
179
|
+
? Object.fromEntries(Object.entries(o.fiscal_data).filter(([, v]) => typeof v === 'string'))
|
|
180
|
+
: undefined,
|
|
176
181
|
});
|
|
177
182
|
});
|
|
178
183
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { AllocationResult, AllocationStrategy, OpenDocument } from '../primitives/allocation';
|
|
2
|
+
export interface PaymentAllocatorValue {
|
|
3
|
+
strategy: AllocationStrategy;
|
|
4
|
+
manual: Record<string, number>;
|
|
5
|
+
}
|
|
6
|
+
export interface PaymentAllocatorProps {
|
|
7
|
+
documents: OpenDocument[];
|
|
8
|
+
/** Resultado de `allocatePayment(amount, documents, value.strategy, value.manual)`. */
|
|
9
|
+
result: AllocationResult;
|
|
10
|
+
value: PaymentAllocatorValue;
|
|
11
|
+
onChange: (next: PaymentAllocatorValue) => void;
|
|
12
|
+
currency?: string;
|
|
13
|
+
loading?: boolean;
|
|
14
|
+
readOnly?: boolean;
|
|
15
|
+
/** Hoy (para los días de atraso; inyectable en tests). */
|
|
16
|
+
today?: Date;
|
|
17
|
+
}
|
|
18
|
+
export declare function PaymentAllocator({ documents, result, value, onChange, currency, loading, readOnly, today }: PaymentAllocatorProps): import("react").JSX.Element;
|
|
19
|
+
//# sourceMappingURL=payment-allocator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payment-allocator.d.ts","sourceRoot":"","sources":["../../src/business/payment-allocator.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAIlG,MAAM,WAAW,qBAAqB;IAClC,QAAQ,EAAE,kBAAkB,CAAA;IAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACjC;AAED,MAAM,WAAW,qBAAqB;IAClC,SAAS,EAAE,YAAY,EAAE,CAAA;IACzB,uFAAuF;IACvF,MAAM,EAAE,gBAAgB,CAAA;IACxB,KAAK,EAAE,qBAAqB,CAAA;IAC5B,QAAQ,EAAE,CAAC,IAAI,EAAE,qBAAqB,KAAK,IAAI,CAAA;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,0DAA0D;IAC1D,KAAK,CAAC,EAAE,IAAI,CAAA;CACf;AAID,wBAAgB,gBAAgB,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,qBAAqB,+BA6EjI"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
// PaymentAllocator — UI del reparto de un pago entre los documentos abiertos de
|
|
3
|
+
// la contraparte (cobro multi-factura / REP, CxP «Aplicar pago»). Las reglas
|
|
4
|
+
// son las de primitives/allocation (allocatePayment / validateAllocation); aquí
|
|
5
|
+
// solo se pintan y se editan. Por defecto reparte solo, del más vencido al más
|
|
6
|
+
// reciente; al teclear un monto pasa a manual sin perder lo ya repartido.
|
|
7
|
+
import { useTranslation } from 'react-i18next';
|
|
8
|
+
import { Badge, Button } from '@asteby/metacore-ui/primitives';
|
|
9
|
+
import { Input } from '@asteby/metacore-ui';
|
|
10
|
+
import { manualFromAllocations, overdueDays } from './document-editor-model';
|
|
11
|
+
import { useFormatter } from './format';
|
|
12
|
+
const num = (s) => (s.trim() === '' ? 0 : Number(s.replace(',', '.')) || 0);
|
|
13
|
+
export function PaymentAllocator({ documents, result, value, onChange, currency, loading, readOnly, today }) {
|
|
14
|
+
const { t } = useTranslation();
|
|
15
|
+
const fmt = useFormatter({ currency });
|
|
16
|
+
const byDoc = new Map(result.allocations.map((a) => [a.document_id, a]));
|
|
17
|
+
if (loading) {
|
|
18
|
+
return _jsx("p", { className: "text-sm text-muted-foreground", children: t('paymentAllocator.loading', { defaultValue: 'Buscando documentos con saldo…' }) });
|
|
19
|
+
}
|
|
20
|
+
if (documents.length === 0) {
|
|
21
|
+
return (_jsx("p", { className: "text-sm text-muted-foreground", "data-slot": "payment-allocator-empty", children: t('paymentAllocator.empty', { defaultValue: 'No hay documentos con saldo pendiente.' }) }));
|
|
22
|
+
}
|
|
23
|
+
const setAmount = (id, amount) => onChange({ strategy: 'manual', manual: { ...manualFromAllocations(result.allocations), [id]: amount } });
|
|
24
|
+
return (_jsxs("div", { className: "space-y-2", "data-slot": "payment-allocator", children: [_jsxs("div", { className: "flex items-center justify-between gap-3 text-xs text-muted-foreground", children: [_jsx("span", { children: value.strategy === 'manual'
|
|
25
|
+
? t('paymentAllocator.manual', { defaultValue: 'Reparto manual' })
|
|
26
|
+
: t('paymentAllocator.auto', { defaultValue: 'Se aplica primero a lo más vencido' }) }), !readOnly && value.strategy === 'manual' && (_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => onChange({ strategy: 'oldest_due_first', manual: {} }), children: t('paymentAllocator.autoapply', { defaultValue: 'Autoaplicar' }) }))] }), _jsx("ul", { className: "divide-y rounded-md border", children: documents.map((d) => {
|
|
27
|
+
const a = byDoc.get(d.id);
|
|
28
|
+
const late = overdueDays(d, today);
|
|
29
|
+
return (_jsxs("li", { className: "flex flex-wrap items-center gap-3 px-3 py-2 text-sm", "data-document": d.id, children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "font-medium", children: d.number }), late > 0 && (_jsx(Badge, { variant: "secondary", children: t('paymentAllocator.overdue', { defaultValue: 'Vencida · {{days}} d', days: late }) })), d.payment_method && _jsx("span", { className: "text-xs text-muted-foreground", children: d.payment_method })] }), _jsxs("div", { className: "text-xs text-muted-foreground", children: [t('paymentAllocator.balance', { defaultValue: 'Saldo' }), " ", fmt.money(d.balance, d.currency), a && a.balance_after > 0 && (_jsxs(_Fragment, { children: [' · ', t('paymentAllocator.installment', { defaultValue: 'Parcialidad {{n}}', n: a.installment }), ' · ', t('paymentAllocator.remaining', { defaultValue: 'Queda' }), " ", fmt.money(a.balance_after, d.currency)] }))] })] }), _jsx(Input, { type: "number", inputMode: "decimal", min: 0, step: "0.01", "aria-label": t('paymentAllocator.apply_to', { defaultValue: 'Aplicar a {{number}}', number: d.number }), className: "h-9 w-32 text-right tabular-nums", value: a ? String(a.amount) : '', placeholder: "0.00", disabled: readOnly, onChange: (e) => setAmount(d.id, num(e.target.value)) })] }, d.id));
|
|
30
|
+
}) })] }));
|
|
31
|
+
}
|
|
@@ -61,6 +61,10 @@ export interface ProductResult {
|
|
|
61
61
|
name: string;
|
|
62
62
|
quantity: number;
|
|
63
63
|
}>;
|
|
64
|
+
/** Unidad de venta del catálogo (pza, juego, kg…). */
|
|
65
|
+
unit?: string;
|
|
66
|
+
/** Campos de extensión del producto (fiscal_data.*) que se copian al renglón. */
|
|
67
|
+
extensions?: Record<string, string>;
|
|
64
68
|
}
|
|
65
69
|
/** Existencia disponible: de la variante o del producto, en un almacén o en total. */
|
|
66
70
|
export declare function availableStock(source: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"product-search.d.ts","sourceRoot":"","sources":["../../src/business/product-search.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAG5C,MAAM,WAAW,QAAQ;IACrB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,CAAA;IACX,kCAAkC;IAClC,UAAU,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,MAAM,YAAY,GAClB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACjD;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,GAClD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAMjD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAW5D;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAO3D;AAED,MAAM,WAAW,gBAAgB;IAC7B,YAAY,EAAE,MAAM,CAAA;IACpB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,SAAS,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,cAAc;IAC3B,EAAE,EAAE,MAAM,CAAA;IACV,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,kFAAkF;IAClF,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,gBAAgB,EAAE,CAAA;CAC7B;AAED,MAAM,WAAW,aAAa;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,4DAA4D;IAC5D,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,IAAI,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAA;IAChD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,mCAAmC;IACnC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,IAAI,CAAC,EAAE,QAAQ,CAAA;IACf,QAAQ,CAAC,EAAE,cAAc,EAAE,CAAA;IAC3B,KAAK,CAAC,EAAE,gBAAgB,EAAE,CAAA;IAC1B,2EAA2E;IAC3E,YAAY,CAAC,EAAE,KAAK,CAAC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"product-search.d.ts","sourceRoot":"","sources":["../../src/business/product-search.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-record.d.ts","sourceRoot":"","sources":["../../src/dialogs/dynamic-record.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAkD1C,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAGjF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"dynamic-record.d.ts","sourceRoot":"","sources":["../../src/dialogs/dynamic-record.tsx"],"names":[],"mappings":"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"}
|
|
@@ -11,7 +11,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
11
11
|
// the image-url resolver and the org IANA timezone — are passed as props so the
|
|
12
12
|
// SDK stays transport- and host-agnostic.
|
|
13
13
|
import { emitRecordMutation } from '../record-mutation-events';
|
|
14
|
-
import { createContext, useCallback, useContext, useEffect, useId, useRef, useState } from 'react';
|
|
14
|
+
import { createContext, useCallback, useContext, useEffect, useId, useMemo, useRef, useState } from 'react';
|
|
15
15
|
import { useTranslation } from 'react-i18next';
|
|
16
16
|
/** Model key of the open create/edit dialog — used to hide "+" on self-FK pickers
|
|
17
17
|
* (e.g. Customer.parent_id) so they don't nest another "Crear Cliente" modal. */
|
|
@@ -37,13 +37,14 @@ import { useAttributeClasses } from '../attribute-classes';
|
|
|
37
37
|
import { groupFieldsBySection } from '../form-layout';
|
|
38
38
|
import { FieldSection, WizardProgress } from '../form-layout-ui';
|
|
39
39
|
import { AssistInterview } from '../assist-interview';
|
|
40
|
+
import { RecordPrefillBar } from '../record-prefill-bar';
|
|
40
41
|
import { FieldCell } from '../field-grid';
|
|
41
42
|
import { isNilUuid, normalizeNilUuid } from '../nil-uuid';
|
|
42
43
|
import { normalizeRefFieldsForSubmit } from './normalize-submit';
|
|
43
44
|
import { validateValues, bagHasErrors, exemptUnchangedRuleIssues } from '../validator';
|
|
44
45
|
import { DynamicIcon, isLucideIconName } from '../dynamic-icon';
|
|
45
46
|
import { IconPickerField } from '../icon-picker-field';
|
|
46
|
-
import { humanizeToken } from '../dynamic-columns-helpers';
|
|
47
|
+
import { humanizeToken, localizeFieldLabel } from '../dynamic-columns-helpers';
|
|
47
48
|
import { formatDateCell } from '../dynamic-columns';
|
|
48
49
|
import { ImageStack, OptionBadge, statusColorFor, useIsDarkTheme, } from '../display-value';
|
|
49
50
|
import { MediaValue, RichText } from '../rich-url';
|
|
@@ -359,6 +360,11 @@ export function DynamicRecordDialog({ open, onOpenChange, nestedInlineCreateSelf
|
|
|
359
360
|
const isCreate = mode === 'create';
|
|
360
361
|
const isView = mode === 'view';
|
|
361
362
|
const isEditable = mode === 'create' || mode === 'edit';
|
|
363
|
+
// Claves que un ayudante de captura (RecordPrefillBar) puede escribir: sólo
|
|
364
|
+
// los campos que este formulario declara (incluye fiscal_data.* de las
|
|
365
|
+
// ModelExtension). Readonly fuera: un prefill no salta un candado.
|
|
366
|
+
const prefillAllowedKeys = useMemo(() => new Set((modalMeta?.fields ?? []).filter((f) => !f.readonly).map((f) => f.key)), [modalMeta]);
|
|
367
|
+
const applyPrefill = useCallback((patch) => setFormValues(prev => ({ ...prev, ...patch })), []);
|
|
362
368
|
const config = MODE_CONFIG[mode];
|
|
363
369
|
// ── Fetch metadata + record when dialog opens ──────────────────────────
|
|
364
370
|
useEffect(() => {
|
|
@@ -539,7 +545,7 @@ export function DynamicRecordDialog({ open, onOpenChange, nestedInlineCreateSelf
|
|
|
539
545
|
const labelForKey = (key) => {
|
|
540
546
|
const f = (modalMeta?.fields ?? []).find(x => x.key === key);
|
|
541
547
|
if (f?.label)
|
|
542
|
-
return f.label;
|
|
548
|
+
return localizeFieldLabel(f.label, t);
|
|
543
549
|
return key.replace(/[._-]+/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
|
|
544
550
|
};
|
|
545
551
|
// Turn a failed submit (422 `errors` map, or a bare `{errors}` body) into
|
|
@@ -586,7 +592,7 @@ export function DynamicRecordDialog({ open, onOpenChange, nestedInlineCreateSelf
|
|
|
586
592
|
if (bagHasErrors(bag)) {
|
|
587
593
|
const labels = {};
|
|
588
594
|
for (const f of visible)
|
|
589
|
-
labels[f.key] = f.label;
|
|
595
|
+
labels[f.key] = localizeFieldLabel(f.label, t);
|
|
590
596
|
const next = localizeFieldErrorMap(bag, t, { labels });
|
|
591
597
|
setFieldErrors(next);
|
|
592
598
|
const description = Object.entries(next)
|
|
@@ -736,7 +742,7 @@ export function DynamicRecordDialog({ open, onOpenChange, nestedInlineCreateSelf
|
|
|
736
742
|
if (bagHasErrors(bag)) {
|
|
737
743
|
const labels = {};
|
|
738
744
|
for (const f of stepFields)
|
|
739
|
-
labels[f.key] = f.label;
|
|
745
|
+
labels[f.key] = localizeFieldLabel(f.label, t);
|
|
740
746
|
setFieldErrors(localizeFieldErrorMap(bag, t, { labels }));
|
|
741
747
|
toast.error(t('dynamic.validation_failed', { defaultValue: 'Revisa los campos marcados' }));
|
|
742
748
|
return;
|
|
@@ -745,7 +751,7 @@ export function DynamicRecordDialog({ open, onOpenChange, nestedInlineCreateSelf
|
|
|
745
751
|
setStepIndex(Math.min(clampedStep + 1, groups.length - 1));
|
|
746
752
|
};
|
|
747
753
|
const goBackStep = () => setStepIndex(Math.max(clampedStep - 1, 0));
|
|
748
|
-
return (_jsx(RecordDialogModelContext.Provider, { value: model, children: _jsx(Dialog, { open: open, onOpenChange: onOpenChange, nestedInlineCreateSelf: nestedInlineCreateSelf, children: _jsxs(DialogContent, { className: "sm:max-w-2xl max-h-[90dvh] flex flex-col p-0 gap-0 overflow-hidden", style: { maxHeight: '90dvh' }, children: [_jsxs(DialogHeader, { className: "p-6 pb-4 border-b shrink-0", children: [_jsx(DialogTitle, { children: title }), _jsx(DialogDescription, { children: config.description })] }), _jsx("div", { className: "flex-1 overflow-y-auto p-6", children: loading ? (_jsx(LoadingSkeleton, {})) : modalMeta ? (_jsx(ModelContext.Provider, { value: model, children: _jsx(ImageUrlContext.Provider, { value: getImageUrl, children: _jsx(TimeZoneContext.Provider, { value: timeZone, children: _jsxs(CurrencyContext.Provider, { value: currency, children: [_jsxs("form", { id: formId, "data-aby-record-form": "", "data-aby-model": model, "data-aby-mode": mode, onSubmit: handleSubmit, className: "grid gap-y-4", children: [isSteps && (_jsx(WizardProgress, { groups: groups, stepIndex: clampedStep, onStepClick: i => setStepIndex(i) })), (isSteps ? [groups[clampedStep]] : groups).map(group =>
|
|
754
|
+
return (_jsx(RecordDialogModelContext.Provider, { value: model, children: _jsx(Dialog, { open: open, onOpenChange: onOpenChange, nestedInlineCreateSelf: nestedInlineCreateSelf, children: _jsxs(DialogContent, { className: "sm:max-w-2xl max-h-[90dvh] flex flex-col p-0 gap-0 overflow-hidden", style: { maxHeight: '90dvh' }, children: [_jsxs(DialogHeader, { className: "p-6 pb-4 border-b shrink-0", children: [_jsx(DialogTitle, { children: title }), _jsx(DialogDescription, { children: config.description })] }), _jsx("div", { className: "flex-1 overflow-y-auto p-6", children: loading ? (_jsx(LoadingSkeleton, {})) : modalMeta ? (_jsx(ModelContext.Provider, { value: model, children: _jsx(ImageUrlContext.Provider, { value: getImageUrl, children: _jsx(TimeZoneContext.Provider, { value: timeZone, children: _jsxs(CurrencyContext.Provider, { value: currency, children: [isEditable && (_jsx(RecordPrefillBar, { model: model, mode: isCreate ? 'create' : 'edit', recordId: recordId, values: formValues, allowedKeys: prefillAllowedKeys, onApply: applyPrefill })), _jsxs("form", { id: formId, "data-aby-record-form": "", "data-aby-model": model, "data-aby-mode": mode, onSubmit: handleSubmit, className: "grid gap-y-4", children: [isSteps && (_jsx(WizardProgress, { groups: groups, stepIndex: clampedStep, onStepClick: i => setStepIndex(i) })), (isSteps ? [groups[clampedStep]] : groups).map(group =>
|
|
749
755
|
// An assisted step IS the interview: no form inputs, the
|
|
750
756
|
// provider asks what it needs and fills the fields.
|
|
751
757
|
isSteps && isEditable && group.assist ? (_jsx(AssistInterview, { assist: group.assist, values: formValues, eyebrow: group.title, autoStart: group.assist.trigger !== 'button', onApply: fields => setFormValues(prev => ({ ...prev, ...fields })) }, group.key)) : (_jsxs(FieldSection, { group: group, children: [_jsx("div", { className: "grid grid-cols-1 gap-x-6 gap-y-4 sm:grid-cols-2", children: renderFields(group.fields) }), isEditable && group.assist && (_jsx(AssistInterview, { assist: group.assist, values: formValues, eyebrow: group.title, autoStart: group.assist.trigger === 'auto', onApply: fields => setFormValues(prev => ({ ...prev, ...fields })) }))] }, group.key))), record?.external_url && (_jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2", children: _jsx("div", { className: "sm:col-span-2 min-w-0", children: _jsxs("a", { href: record.external_url, target: "_blank", rel: "noreferrer", className: "inline-flex items-center gap-1.5 text-sm text-primary hover:underline mt-1", children: [_jsx(ExternalLink, { className: "h-3.5 w-3.5" }), "Ver en ", record.external_provider ?? 'proveedor externo'] }) }) }))] }), !isCreate && record && relations.length > 0 && (_jsx("div", { className: "mt-6", children: _jsx(DynamicRelations, { record: record, relations: relations, lineSubtable: true, embedOnly: true, canCreate: mode === 'edit', canEdit: mode === 'edit', canDelete: mode === 'edit', onChange: handleChildChange }) })), !isCreate && record && audit && (_jsx(AuditInfo, { record: record, audit: audit, timeZone: timeZone, className: "mt-6 border-t pt-3" }))] }) }) }) })) : null }), _jsxs(DialogFooter, { className: "p-4 border-t shrink-0 sm:justify-between", children: [isView && onOpenFullPage ? (_jsxs(Button, { variant: "ghost", size: "sm", className: "text-muted-foreground", onClick: () => { onOpenChange(false); onOpenFullPage(); }, children: [_jsx(ExternalLink, { className: "mr-1.5 h-3.5 w-3.5" }), "Ver p\u00E1gina completa"] })) : _jsx("span", {}), _jsxs("div", { className: "flex items-center gap-2", children: [isSteps && clampedStep > 0 ? (_jsx(Button, { variant: "outline", onClick: goBackStep, disabled: saving || deleting, children: "Anterior" })) : (_jsx(Button, { variant: "outline", onClick: () => onOpenChange(false), disabled: saving || deleting, children: config.cancelLabel })), isView && onDelete && (_jsxs(Button, { variant: "destructive", onClick: handleDelete, disabled: deleting || loading, children: [deleting && _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), deleting ? 'Eliminando...' : 'Eliminar'] })), isView && onEdit && (_jsx(Button, { onClick: onEdit, disabled: deleting || loading, children: "Editar" })), isEditable && isSteps && !isLastStep && (_jsx(Button, { type: "button", onClick: goNextStep, disabled: saving || loading, children: "Siguiente" })), isEditable && (!isSteps || isLastStep) && (_jsxs(Button, { type: "submit", form: formId, disabled: saving || loading, children: [saving && _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), saving ? config.submittingLabel : config.submitLabel] }))] })] })] }) }) }));
|
|
@@ -762,7 +768,8 @@ function FieldRow({ field, record, value, mode, onChange, error, locked }) {
|
|
|
762
768
|
// the rich read-only renderer. `locked` forces the same disabled rendering on
|
|
763
769
|
// CREATE for a caller-specified field (see `lockedFields`).
|
|
764
770
|
const isEditReadonly = (mode === 'edit' && !!field.readonly) || !!locked;
|
|
765
|
-
|
|
771
|
+
const { t } = useTranslation();
|
|
772
|
+
return (_jsxs("div", { className: "flex flex-col gap-1.5", "data-aby-field": field.key, children: [_jsxs(Label, { className: "text-xs font-medium text-muted-foreground uppercase tracking-wide", children: [localizeFieldLabel(field.label, t), field.required && mode !== 'view' && !isEditReadonly && (_jsx("span", { className: "text-destructive ml-0.5", children: "*" }))] }), mode === 'view' ? (_jsx(ViewValue, { field: field, value: value, record: record })) : isEditReadonly ? (_jsx(ReadonlyEditField, { field: field, value: value })) : (_jsx(EditField, { field: field, value: value, onChange: onChange, record: record, invalid: !!error })), error && mode !== 'view' && (_jsx("p", { className: "text-destructive text-xs mt-1", children: error }))] }));
|
|
766
773
|
}
|
|
767
774
|
// ReadonlyEditField — the edit-mode rendering of a `readonly` (system-generated)
|
|
768
775
|
// field: a disabled, muted input that shows the current value without allowing
|
|
@@ -12,12 +12,41 @@ export interface DocumentFormDialogProps {
|
|
|
12
12
|
initialType?: string;
|
|
13
13
|
/** Se llama con el registro creado. */
|
|
14
14
|
onSaved?: (record?: unknown) => void;
|
|
15
|
-
/**
|
|
15
|
+
/**
|
|
16
|
+
* Buscador de productos para el editor de renglones (mismo contrato que
|
|
17
|
+
* ProductPicker). Sin él se busca en el catálogo (`productModel`) vía /data.
|
|
18
|
+
*/
|
|
16
19
|
searchProducts?: DocumentLinesGridProps['search'];
|
|
20
|
+
/** Modelo de catálogo del buscador por defecto. Default `products.Product`. */
|
|
21
|
+
productModel?: string;
|
|
22
|
+
/** Tasa de impuesto (0.16) si el producto no trae la suya. Default: la de la org (OrgRuntimeProvider). */
|
|
23
|
+
defaultTaxRate?: number;
|
|
17
24
|
/** Moneda ISO para el editor de renglones (default: la de la org). */
|
|
18
25
|
currency?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Registro desde el que se abre (acción de fila «Crear NC», «Registrar
|
|
28
|
+
* cobro»…): siembra los campos con `default_from_record`.
|
|
29
|
+
*/
|
|
30
|
+
record?: Record<string, any>;
|
|
31
|
+
/** Documento origen a precargar en el DocumentEditor (`sources[].key` + id). */
|
|
32
|
+
initialSource?: {
|
|
33
|
+
key: string;
|
|
34
|
+
id: string;
|
|
35
|
+
};
|
|
19
36
|
}
|
|
20
37
|
/** Manifest efectivo: la prop gana sobre el metadata; sin tipos devuelve undefined. */
|
|
21
38
|
export declare function resolveDocumentForms(metadata?: Pick<TableMetadata, 'document_forms'> | null, override?: DocumentFormsManifest | null): DocumentFormsManifest | undefined;
|
|
22
|
-
|
|
39
|
+
/**
|
|
40
|
+
* Acota el alta guiada a la vista filtrada. Un nav que filtra por la columna
|
|
41
|
+
* discriminadora (`type_field`) lista UN tipo de documento: «Crear» debe abrir
|
|
42
|
+
* ese tipo directo y, si el manifest no trae formulario para él, no ofrecerse
|
|
43
|
+
* (retest r3: «Documentos fiscales → Facturas → Crear» abría el REP, el único
|
|
44
|
+
* tipo declarado). Sin manifest, sin `type_field` o sin filtro sobre él, todo
|
|
45
|
+
* queda igual.
|
|
46
|
+
*/
|
|
47
|
+
export declare function scopeDocumentFormsToFilter(forms: DocumentFormsManifest | undefined, filter?: Record<string, unknown> | null): {
|
|
48
|
+
forms: DocumentFormsManifest | undefined;
|
|
49
|
+
hideCreate: boolean;
|
|
50
|
+
};
|
|
51
|
+
export declare function DocumentFormDialog({ open, onOpenChange, model, endpoint, forms, initialType, onSaved, searchProducts, productModel, defaultTaxRate, currency, record, initialSource, }: DocumentFormDialogProps): import("react").JSX.Element;
|
|
23
52
|
//# sourceMappingURL=document-form-dialog.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"document-form-dialog.d.ts","sourceRoot":"","sources":["../src/document-form-dialog.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"document-form-dialog.d.ts","sourceRoot":"","sources":["../src/document-form-dialog.tsx"],"names":[],"mappings":"AA6BA,OAAO,EAEH,KAAK,sBAAsB,EAE9B,MAAM,8BAA8B,CAAA;AAerC,OAAO,KAAK,EAER,qBAAqB,EACrB,aAAa,EAChB,MAAM,SAAS,CAAA;AAEhB,MAAM,WAAW,uBAAuB;IACpC,IAAI,EAAE,OAAO,CAAA;IACb,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAA;IACb,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,qBAAqB,CAAA;IAC5B,mDAAmD;IACnD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,uCAAuC;IACvC,OAAO,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;IACpC;;;OAGG;IACH,cAAc,CAAC,EAAE,sBAAsB,CAAC,QAAQ,CAAC,CAAA;IACjD,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,0GAA0G;IAC1G,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,sEAAsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC5B,gFAAgF;IAChF,aAAa,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAA;CAC9C;AAED,uFAAuF;AACvF,wBAAgB,oBAAoB,CAChC,QAAQ,CAAC,EAAE,IAAI,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,IAAI,EACvD,QAAQ,CAAC,EAAE,qBAAqB,GAAG,IAAI,GACxC,qBAAqB,GAAG,SAAS,CAGnC;AAED;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CACtC,KAAK,EAAE,qBAAqB,GAAG,SAAS,EACxC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GACxC;IAAE,KAAK,EAAE,qBAAqB,GAAG,SAAS,CAAC;IAAC,UAAU,EAAE,OAAO,CAAA;CAAE,CAQnE;AAID,wBAAgB,kBAAkB,CAAC,EAC/B,IAAI,EACJ,YAAY,EACZ,KAAK,EACL,QAAQ,EACR,KAAK,EACL,WAAW,EACX,OAAO,EACP,cAAc,EACd,YAAY,EACZ,cAAc,EACd,QAAQ,EACR,MAAM,EACN,aAAa,GAChB,EAAE,uBAAuB,+BAgTzB"}
|
|
@@ -16,6 +16,7 @@ import { Button, Dialog, DialogContent, DialogDescription, DialogFooter, DialogH
|
|
|
16
16
|
import { Loader2 } from 'lucide-react';
|
|
17
17
|
import { toast } from 'sonner';
|
|
18
18
|
import { useApi } from './api-context';
|
|
19
|
+
import { useOrgTaxRate } from './org-runtime-context';
|
|
19
20
|
import { DynamicIcon } from './dynamic-icon';
|
|
20
21
|
import { FieldCell, FieldGrid, FieldLabel } from './field-grid';
|
|
21
22
|
import { FormErrorBanner } from './business/feedback';
|
|
@@ -26,21 +27,39 @@ import { extractFieldErrors, localizeFieldErrorMap } from './server-error';
|
|
|
26
27
|
import { validateValues, bagHasErrors } from './validator';
|
|
27
28
|
import { clearFieldErrorTree } from './field-validation-ui';
|
|
28
29
|
import { emitRecordMutation } from './record-mutation-events';
|
|
29
|
-
import { isLineItemsField, resolveWidget } from './dynamic-form-schema';
|
|
30
|
+
import { isLineItemsField, resolveWidget, scopeValueFromFilterToken } from './dynamic-form-schema';
|
|
31
|
+
import { createCatalogProductSearch } from './business/catalog-product-search';
|
|
32
|
+
import { DocumentEditor } from './business/document-editor';
|
|
33
|
+
import { editorLinesConfig, isEditorLayout } from './business/document-editor-model';
|
|
30
34
|
/** Manifest efectivo: la prop gana sobre el metadata; sin tipos devuelve undefined. */
|
|
31
35
|
export function resolveDocumentForms(metadata, override) {
|
|
32
36
|
const m = override ?? metadata?.document_forms;
|
|
33
37
|
return m && Array.isArray(m.types) && m.types.length > 0 ? m : undefined;
|
|
34
38
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
/**
|
|
40
|
+
* Acota el alta guiada a la vista filtrada. Un nav que filtra por la columna
|
|
41
|
+
* discriminadora (`type_field`) lista UN tipo de documento: «Crear» debe abrir
|
|
42
|
+
* ese tipo directo y, si el manifest no trae formulario para él, no ofrecerse
|
|
43
|
+
* (retest r3: «Documentos fiscales → Facturas → Crear» abría el REP, el único
|
|
44
|
+
* tipo declarado). Sin manifest, sin `type_field` o sin filtro sobre él, todo
|
|
45
|
+
* queda igual.
|
|
46
|
+
*/
|
|
47
|
+
export function scopeDocumentFormsToFilter(forms, filter) {
|
|
48
|
+
const field = forms?.type_field;
|
|
49
|
+
if (!forms || !field || !filter || !(field in filter))
|
|
50
|
+
return { forms, hideCreate: false };
|
|
51
|
+
const want = scopeValueFromFilterToken(filter[field]).trim().toLowerCase();
|
|
52
|
+
if (want === '')
|
|
53
|
+
return { forms, hideCreate: false };
|
|
54
|
+
const types = forms.types.filter((x) => String(x.value ?? x.key).trim().toLowerCase() === want);
|
|
55
|
+
if (types.length === 0)
|
|
56
|
+
return { forms: undefined, hideCreate: true };
|
|
57
|
+
return { forms: types.length === forms.types.length ? forms : { ...forms, types }, hideCreate: false };
|
|
40
58
|
}
|
|
41
|
-
export function DocumentFormDialog({ open, onOpenChange, model, endpoint, forms, initialType, onSaved, searchProducts, currency, }) {
|
|
59
|
+
export function DocumentFormDialog({ open, onOpenChange, model, endpoint, forms, initialType, onSaved, searchProducts, productModel, defaultTaxRate, currency, record, initialSource, }) {
|
|
42
60
|
const { t, i18n } = useTranslation();
|
|
43
61
|
const api = useApi();
|
|
62
|
+
const orgTaxRate = useOrgTaxRate();
|
|
44
63
|
const types = forms.types;
|
|
45
64
|
const single = types.length === 1 ? types[0] : undefined;
|
|
46
65
|
const [typeKey, setTypeKey] = useState(initialType ?? single?.key ?? null);
|
|
@@ -52,7 +71,12 @@ export function DocumentFormDialog({ open, onOpenChange, model, endpoint, forms,
|
|
|
52
71
|
const [formError, setFormError] = useState();
|
|
53
72
|
const [saving, setSaving] = useState(false);
|
|
54
73
|
const type = useMemo(() => types.find((x) => x.key === typeKey) ?? null, [types, typeKey]);
|
|
55
|
-
|
|
74
|
+
// Sin buscador inyectado, el paso de renglones solo ofrecía «Renglón libre»
|
|
75
|
+
// y la línea entraba sin precio (DynamicCRUDPage no pasa searchProducts).
|
|
76
|
+
// Default: el catálogo de productos de la org.
|
|
77
|
+
const taxRate = defaultTaxRate ?? orgTaxRate;
|
|
78
|
+
const lineSearch = useMemo(() => searchProducts ?? createCatalogProductSearch(api, { model: productModel, defaultTaxRate: taxRate }), [searchProducts, api, productModel, taxRate]);
|
|
79
|
+
const lineCfg = type ? editorLinesConfig(type, forms) : undefined;
|
|
56
80
|
// Reset every time the dialog (re)opens.
|
|
57
81
|
useEffect(() => {
|
|
58
82
|
if (!open)
|
|
@@ -69,10 +93,10 @@ export function DocumentFormDialog({ open, onOpenChange, model, endpoint, forms,
|
|
|
69
93
|
useEffect(() => {
|
|
70
94
|
if (!type)
|
|
71
95
|
return;
|
|
72
|
-
setFormData({ ...buildFieldDefaults(type.fields,
|
|
96
|
+
setFormData({ ...buildFieldDefaults(type.fields, record), ...(type.defaults ?? {}) });
|
|
73
97
|
setFieldErrors({});
|
|
74
98
|
setFormError(undefined);
|
|
75
|
-
}, [type]);
|
|
99
|
+
}, [type, record]);
|
|
76
100
|
const updateField = (key, value) => {
|
|
77
101
|
setFormData((prev) => ({ ...prev, [key]: value }));
|
|
78
102
|
setFieldErrors((prev) => clearFieldErrorTree(prev, key));
|
|
@@ -175,6 +199,14 @@ export function DocumentFormDialog({ open, onOpenChange, model, endpoint, forms,
|
|
|
175
199
|
: s === 'fields'
|
|
176
200
|
? t('documentForm.step_data', { defaultValue: 'Datos' })
|
|
177
201
|
: tl(lineCfg?.title ?? 'Renglones');
|
|
202
|
+
// layout "editor": una sola pantalla por secciones (DocumentEditor). Sin él
|
|
203
|
+
// sigue el wizard de siempre (retrocompatible).
|
|
204
|
+
if (open && type && step !== 'type' && isEditorLayout(type)) {
|
|
205
|
+
return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { className: "flex max-h-[92dvh] flex-col overflow-hidden", style: { maxHeight: '92dvh', maxWidth: '960px', width: '95vw' }, "data-slot": "document-editor-dialog", children: [_jsxs(DialogHeader, { className: "shrink-0", children: [_jsx(DialogTitle, { children: tl(type.label) }), type.description && _jsx(DialogDescription, { children: tl(type.description) })] }), _jsx(DocumentEditor, { model: model, endpoint: endpoint, forms: forms, type: type, record: record, initialSource: initialSource, searchProducts: lineSearch, currency: currency, onCancel: () => (canGoBackToTypes ? setStep('type') : onOpenChange(false)), onSaved: (rec) => {
|
|
206
|
+
onSaved?.(rec);
|
|
207
|
+
onOpenChange(false);
|
|
208
|
+
} }, type.key)] }) }));
|
|
209
|
+
}
|
|
178
210
|
return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { className: "flex max-h-[90dvh] flex-col overflow-hidden sm:max-w-2xl", style: { maxHeight: '90dvh', ...(step === 'lines' ? { maxWidth: '980px', width: '95vw' } : {}) }, "data-slot": "document-form-dialog", children: [_jsxs(DialogHeader, { className: "shrink-0", children: [_jsx(DialogTitle, { children: type ? tl(type.label) : t('documentForm.title', { defaultValue: 'Nuevo documento' }) }), _jsx(DialogDescription, { children: stepLabel(step) })] }), _jsxs("div", { className: "-mx-1 min-h-0 flex-1 space-y-3 overflow-y-auto px-1 py-3", children: [_jsx(FormErrorBanner, { message: formError }), step === 'type' && (_jsx("div", { role: "radiogroup", className: "grid gap-3 sm:grid-cols-2", children: types.map((x) => (_jsxs("button", { type: "button", role: "radio", "aria-checked": x.key === typeKey, "data-type-card": x.key, onClick: () => chooseType(x.key), className: "flex items-start gap-3 rounded-lg border p-4 text-left transition-colors hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", children: [x.icon && _jsx(DynamicIcon, { name: x.icon, className: "mt-0.5 size-5 shrink-0 text-primary" }), _jsxs("span", { children: [_jsx("span", { className: "block text-sm font-medium", children: tl(x.label) }), x.description && (_jsx("span", { className: "block text-xs text-muted-foreground", children: tl(x.description) }))] })] }, x.key))) })), step === 'fields' && type && (_jsx(FieldGrid, { children: type.fields.map((field) => {
|
|
179
211
|
const fullWidth = isLineItemsField(field) ||
|
|
180
212
|
resolveWidget(field) === 'textarea' ||
|
|
@@ -183,7 +215,7 @@ export function DocumentFormDialog({ open, onOpenChange, model, endpoint, forms,
|
|
|
183
215
|
}) })), step === 'lines' && type && lineCfg && (_jsx(DocumentLinesGrid, { value: lines, onChange: (next) => {
|
|
184
216
|
setLines(next);
|
|
185
217
|
setServerLineErrors({});
|
|
186
|
-
}, columns: lineCfg.columns ?? ['discount', 'tax'], priceSource: lineCfg.price_source ?? 'sale', serverErrors: serverLineErrors, search:
|
|
218
|
+
}, columns: lineCfg.columns ?? ['discount', 'tax'], priceSource: lineCfg.price_source ?? 'sale', discountMode: lineCfg.discount_mode, serverErrors: serverLineErrors, search: lineSearch, currency: currency }))] }), _jsxs(DialogFooter, { className: "shrink-0", children: [step === 'type' ? (_jsx(Button, { type: "button", variant: "outline", onClick: () => onOpenChange(false), children: t('common.cancel', { defaultValue: 'Cancelar' }) })) : (_jsx(Button, { type: "button", variant: "outline", disabled: saving, onClick: () => {
|
|
187
219
|
if (step === 'lines')
|
|
188
220
|
setStep('fields');
|
|
189
221
|
else if (canGoBackToTypes)
|
|
@@ -27,4 +27,13 @@ export type MetadataTranslator = (key: string, options?: {
|
|
|
27
27
|
* machine path such as `models.orders.table.columns.payment_status`.
|
|
28
28
|
*/
|
|
29
29
|
export declare function translateMetadataLabel(value: string | undefined, translate?: MetadataTranslator): string;
|
|
30
|
+
/**
|
|
31
|
+
* Form-field label as the user should read it. The host usually serves labels
|
|
32
|
+
* already localized; when it could not (an extension field whose addon catalog
|
|
33
|
+
* the server did not resolve), the label arrives as the raw catalog key and the
|
|
34
|
+
* form printed `FISCAL_MEXICO.EXT.CUSTOMER.RFC_RECEPTOR`. Such a key is resolved
|
|
35
|
+
* with the client catalog and, failing that, humanized. Any other label is
|
|
36
|
+
* returned untouched.
|
|
37
|
+
*/
|
|
38
|
+
export declare function localizeFieldLabel(label: string | undefined, translate?: MetadataTranslator): string;
|
|
30
39
|
//# sourceMappingURL=dynamic-columns-helpers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-columns-helpers.d.ts","sourceRoot":"","sources":["../src/dynamic-columns-helpers.ts"],"names":[],"mappings":"AAqBA;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAiBpD;AAED,MAAM,MAAM,kBAAkB,GAAG,CAC7B,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE;IAAE,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,KAClC,MAAM,CAAA;AAEX;;;;GAIG;AACH,wBAAgB,sBAAsB,CAClC,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,SAAS,CAAC,EAAE,kBAAkB,GAC/B,MAAM,CAOR"}
|
|
1
|
+
{"version":3,"file":"dynamic-columns-helpers.d.ts","sourceRoot":"","sources":["../src/dynamic-columns-helpers.ts"],"names":[],"mappings":"AAqBA;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAiBpD;AAED,MAAM,MAAM,kBAAkB,GAAG,CAC7B,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE;IAAE,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,KAClC,MAAM,CAAA;AAEX;;;;GAIG;AACH,wBAAgB,sBAAsB,CAClC,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,SAAS,CAAC,EAAE,kBAAkB,GAC/B,MAAM,CAOR;AAOD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAC9B,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,SAAS,CAAC,EAAE,kBAAkB,GAC/B,MAAM,CAIR"}
|
|
@@ -72,3 +72,22 @@ export function translateMetadataLabel(value, translate) {
|
|
|
72
72
|
const translated = translate(value, { defaultValue: fallback });
|
|
73
73
|
return translated && translated !== value ? translated : fallback;
|
|
74
74
|
}
|
|
75
|
+
// A catalog key as addons write them: lowercase dotted segments
|
|
76
|
+
// ("fiscal_mexico.ext.customer.rfc_receptor"). Human labels have spaces,
|
|
77
|
+
// capitals or accents and never match.
|
|
78
|
+
const CATALOG_KEY_RE = /^[a-z0-9_]+(\.[a-z0-9_]+)+$/;
|
|
79
|
+
/**
|
|
80
|
+
* Form-field label as the user should read it. The host usually serves labels
|
|
81
|
+
* already localized; when it could not (an extension field whose addon catalog
|
|
82
|
+
* the server did not resolve), the label arrives as the raw catalog key and the
|
|
83
|
+
* form printed `FISCAL_MEXICO.EXT.CUSTOMER.RFC_RECEPTOR`. Such a key is resolved
|
|
84
|
+
* with the client catalog and, failing that, humanized. Any other label is
|
|
85
|
+
* returned untouched.
|
|
86
|
+
*/
|
|
87
|
+
export function localizeFieldLabel(label, translate) {
|
|
88
|
+
if (!label)
|
|
89
|
+
return '';
|
|
90
|
+
if (!CATALOG_KEY_RE.test(label))
|
|
91
|
+
return label;
|
|
92
|
+
return translateMetadataLabel(label, translate);
|
|
93
|
+
}
|
|
@@ -62,7 +62,7 @@ export declare function RowActionMenuItem({ action, label, onSelect, }: {
|
|
|
62
62
|
* - action without requiresState (or empty array) → always shown.
|
|
63
63
|
* - row with neither `status` nor `state` → all actions shown.
|
|
64
64
|
*/
|
|
65
|
-
export declare const isActionAllowedForRowState: (action: any, row: any) => boolean;
|
|
65
|
+
export declare const isActionAllowedForRowState: (action: any, row: any, stageField?: string) => boolean;
|
|
66
66
|
/**
|
|
67
67
|
* Declarative `condition` gate for a per-row action: shows the action only when
|
|
68
68
|
* the row's `field` satisfies the operator. Supports both the SDK dialect
|
|
@@ -89,7 +89,13 @@ export declare const isActionConditionMet: (action: any, row: any) => boolean;
|
|
|
89
89
|
* (`requiresState`) AND the declarative `condition` must pass. Shared by the
|
|
90
90
|
* table's action column and the kanban card menu so they hide/show identically.
|
|
91
91
|
*/
|
|
92
|
-
export declare const isRowActionVisible: (action: any, row: any) => boolean;
|
|
92
|
+
export declare const isRowActionVisible: (action: any, row: any, stageField?: string) => boolean;
|
|
93
|
+
/**
|
|
94
|
+
* The column a model's `requiresState` gates read: the served `stage_field`
|
|
95
|
+
* (or, for hosts that predate it, the `group_by` of a model with stages).
|
|
96
|
+
* Undefined → the historical `status` / `state` lookup.
|
|
97
|
+
*/
|
|
98
|
+
export declare const lifecycleStageField: (metadata: any) => string | undefined;
|
|
93
99
|
/**
|
|
94
100
|
* Resolves the relation sibling object a backend serves alongside an FK column.
|
|
95
101
|
* For a column keyed `category_id` the data row also carries
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-columns.d.ts","sourceRoot":"","sources":["../src/dynamic-columns.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAU,KAAK,MAAM,EAAE,MAAM,UAAU,CAAA;AA4C9C,OAAO,KAAK,EAAiB,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAE9D,OAAO,KAAK,EAER,iBAAiB,EACpB,MAAM,wBAAwB,CAAA;AAE/B,qEAAqE;AACrE,MAAM,WAAW,qBAAqB;IAClC;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;IACtC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACtB;AA0BD;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAAI,KAAK,gBAAgB,EAAE,cAAc,MAAM,KAAG,MACzB,CAAA;AAQrD;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GAAI,KAAK,gBAAgB,KAAG,MAAM,GAAG,SAG5D,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,GAC7B,KAAK,gBAAgB,EACrB,OAAO,OAAO,EACd,WAAW,MAAM,EACjB,SAAS,MAAM,KAChB,MAyBF,CAAA;AAyCD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,EAC9B,MAAM,EACN,KAAK,EACL,QAAQ,GACX,EAAE;IACC,MAAM,EAAE,GAAG,CAAA;IACX,KAAK,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,QAAQ,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAA;CAC1C,qBAcA;
|
|
1
|
+
{"version":3,"file":"dynamic-columns.d.ts","sourceRoot":"","sources":["../src/dynamic-columns.tsx"],"names":[],"mappings":"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"}
|