@asteby/metacore-runtime-react 37.0.5 → 37.1.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 +6 -0
- package/dist/action-modal-dispatcher.d.ts.map +1 -1
- package/dist/action-modal-dispatcher.js +21 -2
- package/dist/branch-create-gate.d.ts +25 -0
- package/dist/branch-create-gate.d.ts.map +1 -0
- package/dist/branch-create-gate.js +24 -0
- package/dist/dialogs/dynamic-record.d.ts.map +1 -1
- package/dist/dialogs/dynamic-record.js +12 -1
- package/dist/dynamic-form-schema.d.ts +9 -0
- package/dist/dynamic-form-schema.d.ts.map +1 -1
- package/dist/dynamic-form-schema.js +45 -0
- package/dist/dynamic-line-items.d.ts.map +1 -1
- package/dist/dynamic-line-items.js +12 -4
- package/dist/dynamic-table.d.ts.map +1 -1
- package/dist/dynamic-table.js +35 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/package.json +3 -3
- package/src/__tests__/line-item-formulas.test.ts +43 -0
- package/src/action-modal-dispatcher.tsx +22 -2
- package/src/branch-create-gate.tsx +40 -0
- package/src/dialogs/dynamic-record.tsx +13 -1
- package/src/dynamic-form-schema.ts +51 -0
- package/src/dynamic-line-items.tsx +16 -3
- package/src/dynamic-table.tsx +34 -0
- package/src/index.ts +8 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @asteby/metacore-runtime-react
|
|
2
2
|
|
|
3
|
+
## 37.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 3edee3a: Branch create gate (confirm+pick when no active branch), live line-item importe formula (qty×price−discount), and drop sticky f_branch_id when leaving a locked branch defaultFilter.
|
|
8
|
+
|
|
3
9
|
## 37.0.5
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action-modal-dispatcher.d.ts","sourceRoot":"","sources":["../src/action-modal-dispatcher.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"action-modal-dispatcher.d.ts","sourceRoot":"","sources":["../src/action-modal-dispatcher.tsx"],"names":[],"mappings":"AAoEA,OAAO,KAAK,EAAE,cAAc,EAAmC,MAAM,SAAS,CAAA;AAE9E,OAAO,EACH,KAAK,cAAc,EACnB,KAAK,gBAAgB,EAExB,MAAM,sBAAsB,CAAA;AAE7B,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,CAAA;AAiBhD,MAAM,WAAW,WAAW;IACxB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC5B,SAAS,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC1D;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;CAClB;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,WAAW,CAM1D;AAsBD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,cAAc,GAAG,cAAc,CAStE;AAGD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAkB3F;AASD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAY1D;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CASjE;AAUD,oEAAoE;AACpE,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAgBnF;AAED,wBAAgB,qBAAqB,CAAC,EAClC,IAAI,EACJ,YAAY,EACZ,MAAM,EACN,KAAK,EACL,MAAM,EACN,QAAQ,EACR,SAAS,GACZ,EAAE,gBAAgB,sCAoElB"}
|
|
@@ -15,6 +15,7 @@ import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, Di
|
|
|
15
15
|
import { Loader2 } from 'lucide-react';
|
|
16
16
|
import { toast } from 'sonner';
|
|
17
17
|
import { toastServerError, toastServerSuccess, extractFieldErrors, localizeFieldErrorMap } from './server-error';
|
|
18
|
+
import { useBranchCreateGate } from './branch-create-gate';
|
|
18
19
|
import { validateValues, bagHasErrors } from './validator';
|
|
19
20
|
import { clearFieldErrorTree, formatFieldErrorsDescription, labelsForValidationFields, labelForValidationPath, lineItemErrorsFor, } from './field-validation-ui';
|
|
20
21
|
import { validationCatalog } from './validation-catalog';
|
|
@@ -393,6 +394,7 @@ function GenericActionModal({ open, onOpenChange, action, model, record, endpoin
|
|
|
393
394
|
// defaultValue keeps an already-localized string unchanged.
|
|
394
395
|
const tl = (s) => t(s, { defaultValue: s });
|
|
395
396
|
const api = useApi();
|
|
397
|
+
const branchGate = useBranchCreateGate();
|
|
396
398
|
const [formData, setFormData] = useState({});
|
|
397
399
|
const [executing, setExecuting] = useState(false);
|
|
398
400
|
// Per-field validation errors (localized), shown inline under each input.
|
|
@@ -476,8 +478,25 @@ function GenericActionModal({ open, onOpenChange, action, model, record, endpoin
|
|
|
476
478
|
setFieldErrors({});
|
|
477
479
|
setExecuting(true);
|
|
478
480
|
try {
|
|
479
|
-
|
|
480
|
-
|
|
481
|
+
let payload = { ...formData };
|
|
482
|
+
// Create-placement actions (and any create with no record) may need a
|
|
483
|
+
// host branch stamp when the sidebar is on "Todas". Skip when the
|
|
484
|
+
// form already collected branch_id, or the host has no gate.
|
|
485
|
+
const isCreatePlacement = action.placement === 'create' ||
|
|
486
|
+
record?.id == null ||
|
|
487
|
+
record?.id === '' ||
|
|
488
|
+
record?.id === 'undefined';
|
|
489
|
+
if (branchGate &&
|
|
490
|
+
isCreatePlacement &&
|
|
491
|
+
(payload.branch_id == null || payload.branch_id === '')) {
|
|
492
|
+
const branchId = await branchGate.ensureBranchForCreate(model);
|
|
493
|
+
if (branchId === null)
|
|
494
|
+
return;
|
|
495
|
+
if (branchId)
|
|
496
|
+
payload = { ...payload, branch_id: branchId };
|
|
497
|
+
}
|
|
498
|
+
const url = buildActionUrl(endpoint, model, record?.id, action.key);
|
|
499
|
+
const res = await api.post(url, payload);
|
|
481
500
|
if (res.data.success) {
|
|
482
501
|
toastServerSuccess(res.data, { t });
|
|
483
502
|
onOpenChange(false);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional host gate for stamping `branch_id` on creates when the sidebar is
|
|
3
|
+
* on "all branches" (no active scope).
|
|
4
|
+
*
|
|
5
|
+
* Ops (and other hosts) provide a provider that opens a confirm + branch
|
|
6
|
+
* picker. The SDK's DynamicRecordDialog / ActionModalDispatcher call
|
|
7
|
+
* `ensureBranchForCreate` right before POST — custom federated modals can use
|
|
8
|
+
* the same hook so POS-style flows stay consistent.
|
|
9
|
+
*
|
|
10
|
+
* Return contract for `ensureBranchForCreate`:
|
|
11
|
+
* - `undefined` — model has no branch_id / gate not needed / already scoped
|
|
12
|
+
* - `string` — branch id to stamp onto the payload
|
|
13
|
+
* - `null` — user cancelled the picker (abort submit)
|
|
14
|
+
*/
|
|
15
|
+
import { type ReactNode } from 'react';
|
|
16
|
+
export type BranchCreateGateApi = {
|
|
17
|
+
ensureBranchForCreate: (model: string) => Promise<string | null | undefined>;
|
|
18
|
+
};
|
|
19
|
+
export declare function BranchCreateGateProvider({ value, children, }: {
|
|
20
|
+
value: BranchCreateGateApi;
|
|
21
|
+
children: ReactNode;
|
|
22
|
+
}): import("react").JSX.Element;
|
|
23
|
+
/** Hook for custom / federated create modals. Returns null when no host gate. */
|
|
24
|
+
export declare function useBranchCreateGate(): BranchCreateGateApi | null;
|
|
25
|
+
//# sourceMappingURL=branch-create-gate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"branch-create-gate.d.ts","sourceRoot":"","sources":["../src/branch-create-gate.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAEjE,MAAM,MAAM,mBAAmB,GAAG;IAChC,qBAAqB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAA;CAC7E,CAAA;AAID,wBAAgB,wBAAwB,CAAC,EACvC,KAAK,EACL,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,mBAAmB,CAAA;IAC1B,QAAQ,EAAE,SAAS,CAAA;CACpB,+BAMA;AAED,iFAAiF;AACjF,wBAAgB,mBAAmB,IAAI,mBAAmB,GAAG,IAAI,CAEhE"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Optional host gate for stamping `branch_id` on creates when the sidebar is
|
|
4
|
+
* on "all branches" (no active scope).
|
|
5
|
+
*
|
|
6
|
+
* Ops (and other hosts) provide a provider that opens a confirm + branch
|
|
7
|
+
* picker. The SDK's DynamicRecordDialog / ActionModalDispatcher call
|
|
8
|
+
* `ensureBranchForCreate` right before POST — custom federated modals can use
|
|
9
|
+
* the same hook so POS-style flows stay consistent.
|
|
10
|
+
*
|
|
11
|
+
* Return contract for `ensureBranchForCreate`:
|
|
12
|
+
* - `undefined` — model has no branch_id / gate not needed / already scoped
|
|
13
|
+
* - `string` — branch id to stamp onto the payload
|
|
14
|
+
* - `null` — user cancelled the picker (abort submit)
|
|
15
|
+
*/
|
|
16
|
+
import { createContext, useContext } from 'react';
|
|
17
|
+
const BranchCreateGateContext = createContext(null);
|
|
18
|
+
export function BranchCreateGateProvider({ value, children, }) {
|
|
19
|
+
return (_jsx(BranchCreateGateContext.Provider, { value: value, children: children }));
|
|
20
|
+
}
|
|
21
|
+
/** Hook for custom / federated create modals. Returns null when no host gate. */
|
|
22
|
+
export function useBranchCreateGate() {
|
|
23
|
+
return useContext(BranchCreateGateContext);
|
|
24
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-record.d.ts","sourceRoot":"","sources":["../../src/dialogs/dynamic-record.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"dynamic-record.d.ts","sourceRoot":"","sources":["../../src/dialogs/dynamic-record.tsx"],"names":[],"mappings":"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"}
|
|
@@ -23,6 +23,7 @@ import { es } from 'date-fns/locale';
|
|
|
23
23
|
import { ExternalLink, Loader2, CalendarIcon, ChevronDown, Check, Upload, X as XIcon, ScanLine } from 'lucide-react';
|
|
24
24
|
import { BarcodeScanner } from '../barcode-scanner';
|
|
25
25
|
import { useApi } from '../api-context';
|
|
26
|
+
import { useBranchCreateGate } from '../branch-create-gate';
|
|
26
27
|
import { toastServerError, extractFieldErrors, localizeFieldIssue, localizeFieldErrorMap } from '../server-error';
|
|
27
28
|
import { DynamicSelectField, OptionLead, OptionThumb } from '../dynamic-select-field';
|
|
28
29
|
import { DynamicRelations } from '../dynamic-relations';
|
|
@@ -319,6 +320,7 @@ function applyEnsureFields(meta, ensureFields) {
|
|
|
319
320
|
}
|
|
320
321
|
export function DynamicRecordDialog({ open, onOpenChange, nestedInlineCreateSelf, ensureFields, mode, model, recordId, endpoint, onSaved, onCreate, onUpdate, defaults, lockedFields, schema, onDelete, onEdit, onOpenFullPage, initialRecord, getImageUrl = identityImageUrl, timeZone, currency, onChange, }) {
|
|
321
322
|
const api = useApi();
|
|
323
|
+
const branchGate = useBranchCreateGate();
|
|
322
324
|
const { t } = useTranslation();
|
|
323
325
|
const [modalMeta, setModalMeta] = useState(schema ? schema : null);
|
|
324
326
|
const [relations, setRelations] = useState([]);
|
|
@@ -578,7 +580,16 @@ export function DynamicRecordDialog({ open, onOpenChange, nestedInlineCreateSelf
|
|
|
578
580
|
const submittedValues = stripHiddenFieldValues(formValues, modalMeta.fields, mode);
|
|
579
581
|
// Empty reference pickers → null (not "" / nil-UUID) so nullable FK
|
|
580
582
|
// columns accept them instead of raising a 23503 FK violation.
|
|
581
|
-
|
|
583
|
+
let payload = normalizeRefFieldsForSubmit(submittedValues, modalMeta.fields);
|
|
584
|
+
if (isCreate &&
|
|
585
|
+
branchGate &&
|
|
586
|
+
(payload.branch_id == null || payload.branch_id === '')) {
|
|
587
|
+
const branchId = await branchGate.ensureBranchForCreate(model);
|
|
588
|
+
if (branchId === null)
|
|
589
|
+
return;
|
|
590
|
+
if (branchId)
|
|
591
|
+
payload = { ...payload, branch_id: branchId };
|
|
592
|
+
}
|
|
582
593
|
setSaving(true);
|
|
583
594
|
try {
|
|
584
595
|
if (isCreate && onCreate) {
|
|
@@ -38,6 +38,15 @@ export declare function toNumber(v: unknown): number;
|
|
|
38
38
|
* drift (0.1 + 0.2 noise) that would make a genuinely balanced entry look off.
|
|
39
39
|
*/
|
|
40
40
|
export declare function computeLineItemTotals(field: ActionFieldDef, rows: any[] | undefined): Record<string, number>;
|
|
41
|
+
/**
|
|
42
|
+
* Live line-amount formula for action / form line-items grids:
|
|
43
|
+
* `(qty|quantity) * (unit_price|…) - (discount|…)` → `subtotal|line_total|importe`.
|
|
44
|
+
*
|
|
45
|
+
* Pure + convention-based so create_sales_order (and similar modals) show
|
|
46
|
+
* Importe as the user types without each manifest declaring a client formula.
|
|
47
|
+
* No-op when the row has no amount column or no qty/price pair.
|
|
48
|
+
*/
|
|
49
|
+
export declare function applyLineItemRowFormulas(itemFields: ActionFieldDef[], row: Record<string, any>): Record<string, any>;
|
|
41
50
|
export interface BalanceState {
|
|
42
51
|
debit: number;
|
|
43
52
|
credit: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-form-schema.d.ts","sourceRoot":"","sources":["../src/dynamic-form-schema.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"dynamic-form-schema.d.ts","sourceRoot":"","sources":["../src/dynamic-form-schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -111,6 +111,51 @@ export function computeLineItemTotals(field, rows) {
|
|
|
111
111
|
totals[k] = Math.round(totals[k] * 100) / 100;
|
|
112
112
|
return totals;
|
|
113
113
|
}
|
|
114
|
+
/** Keys that mean "line net amount" across manifests / locales. */
|
|
115
|
+
const LINE_AMOUNT_KEYS = new Set(['subtotal', 'line_total', 'importe', 'amount', 'total']);
|
|
116
|
+
/** Keys that mean quantity on a line row. */
|
|
117
|
+
const LINE_QTY_KEYS = new Set(['qty', 'quantity', 'cantidad']);
|
|
118
|
+
/** Keys that mean unit price. */
|
|
119
|
+
const LINE_PRICE_KEYS = new Set(['unit_price', 'price', 'precio', 'precio_unitario']);
|
|
120
|
+
/** Keys that mean line discount (absolute). */
|
|
121
|
+
const LINE_DISCOUNT_KEYS = new Set(['discount', 'descuento', 'discount_amount']);
|
|
122
|
+
function firstKey(rowOrFields, candidates) {
|
|
123
|
+
if (Array.isArray(rowOrFields)) {
|
|
124
|
+
for (const f of rowOrFields) {
|
|
125
|
+
if (f.key && candidates.has(f.key))
|
|
126
|
+
return f.key;
|
|
127
|
+
}
|
|
128
|
+
return undefined;
|
|
129
|
+
}
|
|
130
|
+
for (const k of Object.keys(rowOrFields)) {
|
|
131
|
+
if (candidates.has(k))
|
|
132
|
+
return k;
|
|
133
|
+
}
|
|
134
|
+
return undefined;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Live line-amount formula for action / form line-items grids:
|
|
138
|
+
* `(qty|quantity) * (unit_price|…) - (discount|…)` → `subtotal|line_total|importe`.
|
|
139
|
+
*
|
|
140
|
+
* Pure + convention-based so create_sales_order (and similar modals) show
|
|
141
|
+
* Importe as the user types without each manifest declaring a client formula.
|
|
142
|
+
* No-op when the row has no amount column or no qty/price pair.
|
|
143
|
+
*/
|
|
144
|
+
export function applyLineItemRowFormulas(itemFields, row) {
|
|
145
|
+
const amountKey = firstKey(itemFields, LINE_AMOUNT_KEYS) ?? firstKey(row, LINE_AMOUNT_KEYS);
|
|
146
|
+
const qtyKey = firstKey(itemFields, LINE_QTY_KEYS) ?? firstKey(row, LINE_QTY_KEYS);
|
|
147
|
+
const priceKey = firstKey(itemFields, LINE_PRICE_KEYS) ?? firstKey(row, LINE_PRICE_KEYS);
|
|
148
|
+
if (!amountKey || !qtyKey || !priceKey)
|
|
149
|
+
return row;
|
|
150
|
+
const discountKey = firstKey(itemFields, LINE_DISCOUNT_KEYS) ?? firstKey(row, LINE_DISCOUNT_KEYS);
|
|
151
|
+
const qty = toNumber(row[qtyKey]);
|
|
152
|
+
const price = toNumber(row[priceKey]);
|
|
153
|
+
const discount = discountKey ? toNumber(row[discountKey]) : 0;
|
|
154
|
+
const next = Math.round((qty * price - discount) * 100) / 100;
|
|
155
|
+
if (toNumber(row[amountKey]) === next)
|
|
156
|
+
return row;
|
|
157
|
+
return { ...row, [amountKey]: next };
|
|
158
|
+
}
|
|
114
159
|
/**
|
|
115
160
|
* Evaluates a line-items field's balance rule against its rows. Returns
|
|
116
161
|
* `undefined` when the field declares no balance rule. `balanced` is true when
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-line-items.d.ts","sourceRoot":"","sources":["../src/dynamic-line-items.tsx"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"dynamic-line-items.d.ts","sourceRoot":"","sources":["../src/dynamic-line-items.tsx"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAiB7C,MAAM,WAAW,qBAAqB;IAClC,KAAK,EAAE,cAAc,CAAA;IACrB,KAAK,EAAE,GAAG,EAAE,GAAG,SAAS,CAAA;IACxB,QAAQ,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAA;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAChC;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAClC;AAkBD,wBAAgB,gBAAgB,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAgB,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,qBAAqB,+BAwQvH"}
|
|
@@ -11,7 +11,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
11
11
|
import { Input, Textarea, Switch, Button, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@asteby/metacore-ui/primitives';
|
|
12
12
|
import { useEffect, useRef } from 'react';
|
|
13
13
|
import { Plus, Trash2, Check } from 'lucide-react';
|
|
14
|
-
import { resolveWidget, getItemFields, computeLineItemTotals, evaluateBalance, toNumber, getDependsOn, resolveDependsValue, getOptionsConfig, resolveOptionsSource, applyOptionWhen, } from './dynamic-form-schema';
|
|
14
|
+
import { resolveWidget, getItemFields, computeLineItemTotals, applyLineItemRowFormulas, evaluateBalance, toNumber, getDependsOn, resolveDependsValue, getOptionsConfig, resolveOptionsSource, applyOptionWhen, } from './dynamic-form-schema';
|
|
15
15
|
import { DynamicSelectField, DEFAULT_DEPENDS_HINT } from './dynamic-select-field';
|
|
16
16
|
import { useOptionsResolver } from './use-options-resolver';
|
|
17
17
|
const fmtNumber = (n) => n.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 });
|
|
@@ -40,9 +40,11 @@ export function DynamicLineItems({ field, value, onChange, disabled = false, for
|
|
|
40
40
|
const totalKeys = itemFields.filter((c) => c.total).map((c) => c.key);
|
|
41
41
|
const hasTotals = totalKeys.length > 0;
|
|
42
42
|
const balance = evaluateBalance(field, rows);
|
|
43
|
-
const addRow = () => onChange([...rows, emptyRow(itemFields)]);
|
|
43
|
+
const addRow = () => onChange([...rows, applyLineItemRowFormulas(itemFields, emptyRow(itemFields))]);
|
|
44
44
|
const removeRow = (idx) => onChange(rows.filter((_, i) => i !== idx));
|
|
45
|
-
const updateCell = (idx, key, cellValue) => onChange(rows.map((r, i) =>
|
|
45
|
+
const updateCell = (idx, key, cellValue) => onChange(rows.map((r, i) => i === idx
|
|
46
|
+
? applyLineItemRowFormulas(itemFields, { ...r, [key]: cellValue })
|
|
47
|
+
: r));
|
|
46
48
|
// When a balance rule reconciles two columns (e.g. debit ↔ credit), typing
|
|
47
49
|
// into one clears the sibling on the same row — mirrors the federated modal
|
|
48
50
|
// UX so a line is never both a debit and a credit.
|
|
@@ -59,7 +61,13 @@ export function DynamicLineItems({ field, value, onChange, disabled = false, for
|
|
|
59
61
|
if (balancePair && (key === balancePair[0] || key === balancePair[1])) {
|
|
60
62
|
const sibling = key === balancePair[0] ? balancePair[1] : balancePair[0];
|
|
61
63
|
const hasValue = toNumber(cellValue) > 0;
|
|
62
|
-
onChange(rows.map((r, i) => i === idx
|
|
64
|
+
onChange(rows.map((r, i) => i === idx
|
|
65
|
+
? applyLineItemRowFormulas(itemFields, {
|
|
66
|
+
...r,
|
|
67
|
+
[key]: cellValue,
|
|
68
|
+
...(hasValue ? { [sibling]: '' } : {}),
|
|
69
|
+
})
|
|
70
|
+
: r));
|
|
63
71
|
return;
|
|
64
72
|
}
|
|
65
73
|
updateCell(idx, key, cellValue);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-table.d.ts","sourceRoot":"","sources":["../src/dynamic-table.tsx"],"names":[],"mappings":"AAgBA,OAAO,EAKH,KAAK,SAAS,EAajB,MAAM,uBAAuB,CAAA;AAgC9B,OAAO,KAAK,EAAsB,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAkGnF,MAAM,WAAW,iBAAiB;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,6DAA6D;IAC7D,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB;;;;;;;;;OASG;IACH,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC5B,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,CAAA;IAC7C;;;;;OAKG;IACH,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAA;IAC/B,cAAc,CAAC,EAAE,GAAG,CAAA;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACpC,YAAY,CAAC,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,CAAA;IAC/B;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,iBAAiB,CAAA;IACrC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;;;;;;;;;OAaG;IACH,UAAU,CAAC,EAAE,OAAO,GAAG,UAAU,CAAA;IACjC;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;CAC3B;AAED,wBAAgB,YAAY,CAAC,EACzB,KAAK,EACL,QAAQ,EACR,gBAAgB,EAChB,aAAoB,EACpB,UAAU,EACV,UAAU,EACV,aAAkB,EAClB,iBAAiB,EACjB,QAAQ,EACR,UAAU,EACV,cAAc,EACd,cAAc,EACd,YAAiB,EACjB,iBAA4C,EAC5C,QAAQ,EACR,QAAQ,EACR,UAAU,EAAE,cAAc,EAC1B,cAAc,EAAE,kBAA0B,GAC7C,EAAE,iBAAiB,+
|
|
1
|
+
{"version":3,"file":"dynamic-table.d.ts","sourceRoot":"","sources":["../src/dynamic-table.tsx"],"names":[],"mappings":"AAgBA,OAAO,EAKH,KAAK,SAAS,EAajB,MAAM,uBAAuB,CAAA;AAgC9B,OAAO,KAAK,EAAsB,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAkGnF,MAAM,WAAW,iBAAiB;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,6DAA6D;IAC7D,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB;;;;;;;;;OASG;IACH,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC5B,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,CAAA;IAC7C;;;;;OAKG;IACH,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAA;IAC/B,cAAc,CAAC,EAAE,GAAG,CAAA;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACpC,YAAY,CAAC,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,CAAA;IAC/B;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,iBAAiB,CAAA;IACrC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;;;;;;;;;OAaG;IACH,UAAU,CAAC,EAAE,OAAO,GAAG,UAAU,CAAA;IACjC;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;CAC3B;AAED,wBAAgB,YAAY,CAAC,EACzB,KAAK,EACL,QAAQ,EACR,gBAAgB,EAChB,aAAoB,EACpB,UAAU,EACV,UAAU,EACV,aAAkB,EAClB,iBAAiB,EACjB,QAAQ,EACR,UAAU,EACV,cAAc,EACd,cAAc,EACd,YAAiB,EACjB,iBAA4C,EAC5C,QAAQ,EACR,QAAQ,EACR,UAAU,EAAE,cAAc,EAC1B,cAAc,EAAE,kBAA0B,GAC7C,EAAE,iBAAiB,+BA02CnB"}
|
package/dist/dynamic-table.js
CHANGED
|
@@ -193,6 +193,36 @@ export function DynamicTable({ model, endpoint, mutationEndpoint, enableUrlSync
|
|
|
193
193
|
// been adopted, where `dynamicFilters`/`pagination` already mirror the URL,
|
|
194
194
|
// so the write is a no-op and the filter never gets stripped.
|
|
195
195
|
const [urlSynced, setUrlSynced] = useState(false);
|
|
196
|
+
// Keys that left `defaultFilters` (e.g. branch_id when switching to
|
|
197
|
+
// "Todas las sucursales"). The URL write effect used to carry-through every
|
|
198
|
+
// leftover `f_*` from location — that resurrected the locked branch filter
|
|
199
|
+
// forever after the host dropped it from defaultFilters.
|
|
200
|
+
const prevDefaultFilterKeys = useRef(new Set());
|
|
201
|
+
const releasedDefaultFilterKeys = useRef(new Set());
|
|
202
|
+
useEffect(() => {
|
|
203
|
+
const next = new Set(Object.keys(defaultFilters ?? {}));
|
|
204
|
+
const prev = prevDefaultFilterKeys.current;
|
|
205
|
+
const released = new Set();
|
|
206
|
+
prev.forEach((k) => {
|
|
207
|
+
if (!next.has(k))
|
|
208
|
+
released.add(k);
|
|
209
|
+
});
|
|
210
|
+
releasedDefaultFilterKeys.current = released;
|
|
211
|
+
if (released.size > 0) {
|
|
212
|
+
setDynamicFilters((df) => {
|
|
213
|
+
let changed = false;
|
|
214
|
+
const copy = { ...df };
|
|
215
|
+
released.forEach((k) => {
|
|
216
|
+
if (k in copy) {
|
|
217
|
+
delete copy[k];
|
|
218
|
+
changed = true;
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
return changed ? copy : df;
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
prevDefaultFilterKeys.current = next;
|
|
225
|
+
}, [defaultFilters]);
|
|
196
226
|
useEffect(() => {
|
|
197
227
|
if (prevBranchId.current !== currentBranch?.id) {
|
|
198
228
|
prevBranchId.current = currentBranch?.id;
|
|
@@ -349,11 +379,16 @@ export function DynamicTable({ model, endpoint, mutationEndpoint, enableUrlSync
|
|
|
349
379
|
// Sidebar deep-links (CxC→CxP) push f_party_type=eq:supplier before React
|
|
350
380
|
// re-renders with matching defaultFilters; without this carry-through the
|
|
351
381
|
// write effect races and strips the filter down to bare ?view=list.
|
|
382
|
+
// Do NOT resurrect keys the host just released from defaultFilters
|
|
383
|
+
// (branch_id when switching to "all" — otherwise San Felipe sticks).
|
|
352
384
|
current.forEach((value, key) => {
|
|
353
385
|
if (!key.startsWith('f_'))
|
|
354
386
|
return;
|
|
355
387
|
if (params.has(key))
|
|
356
388
|
return;
|
|
389
|
+
const filterKey = key.substring(2);
|
|
390
|
+
if (releasedDefaultFilterKeys.current.has(filterKey))
|
|
391
|
+
return;
|
|
357
392
|
params.set(key, value);
|
|
358
393
|
});
|
|
359
394
|
const search = params.toString();
|
package/dist/index.d.ts
CHANGED
|
@@ -71,7 +71,8 @@ export { registerModelExtension, getModelExtension, clearModelExtensions, type M
|
|
|
71
71
|
export { isColumnVisibleInTable, isColumnVisibleInModal, isColumnVisibleInLineSubtable, AUDIT_SUBTABLE_COLUMN_KEYS, getSearchableColumnKeys, } from './column-visibility';
|
|
72
72
|
export { useOptionsResolver, projectOption, type ResolvedOption, type OptionsMeta, type UseOptionsResolverArgs, type UseOptionsResolverResult, } from './use-options-resolver';
|
|
73
73
|
export { setOrgConfigBridge, getOrgConfigBridge, resolveValidatorToken, type OrgConfigBridge, } from './use-org-config-bridge';
|
|
74
|
-
export { registerValidator, getDependsOn, resolveDependsValue, getOptionsConfig, resolveOptionsSource, getVisibleWhen, evaluateVisibleWhen, scopeValueFromFilterToken, buildListScopeValues, evaluateVisibleWhenForListScope, } from './dynamic-form-schema';
|
|
74
|
+
export { registerValidator, getDependsOn, resolveDependsValue, getOptionsConfig, resolveOptionsSource, getVisibleWhen, evaluateVisibleWhen, scopeValueFromFilterToken, buildListScopeValues, evaluateVisibleWhenForListScope, applyLineItemRowFormulas, computeLineItemTotals, toNumber, } from './dynamic-form-schema';
|
|
75
|
+
export { BranchCreateGateProvider, useBranchCreateGate, type BranchCreateGateApi, } from './branch-create-gate';
|
|
75
76
|
export { ActivityValueRenderer, type ActivityValueRendererProps, } from './activity-value-renderer';
|
|
76
77
|
export { ActivityDiff, type ActivityEvent, type ActivityDiffProps, } from './activity-diff';
|
|
77
78
|
export { RecordHistory, type RecordHistoryProps, } from './record-history';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -71,7 +71,8 @@ export { registerModelExtension, getModelExtension, clearModelExtensions, } from
|
|
|
71
71
|
export { isColumnVisibleInTable, isColumnVisibleInModal, isColumnVisibleInLineSubtable, AUDIT_SUBTABLE_COLUMN_KEYS, getSearchableColumnKeys, } from './column-visibility';
|
|
72
72
|
export { useOptionsResolver, projectOption, } from './use-options-resolver';
|
|
73
73
|
export { setOrgConfigBridge, getOrgConfigBridge, resolveValidatorToken, } from './use-org-config-bridge';
|
|
74
|
-
export { registerValidator, getDependsOn, resolveDependsValue, getOptionsConfig, resolveOptionsSource, getVisibleWhen, evaluateVisibleWhen, scopeValueFromFilterToken, buildListScopeValues, evaluateVisibleWhenForListScope, } from './dynamic-form-schema';
|
|
74
|
+
export { registerValidator, getDependsOn, resolveDependsValue, getOptionsConfig, resolveOptionsSource, getVisibleWhen, evaluateVisibleWhen, scopeValueFromFilterToken, buildListScopeValues, evaluateVisibleWhenForListScope, applyLineItemRowFormulas, computeLineItemTotals, toNumber, } from './dynamic-form-schema';
|
|
75
|
+
export { BranchCreateGateProvider, useBranchCreateGate, } from './branch-create-gate';
|
|
75
76
|
export { ActivityValueRenderer, } from './activity-value-renderer';
|
|
76
77
|
export { ActivityDiff, } from './activity-diff';
|
|
77
78
|
export { RecordHistory, } from './record-history';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@asteby/metacore-runtime-react",
|
|
3
|
-
"version": "37.0
|
|
3
|
+
"version": "37.1.0",
|
|
4
4
|
"description": "React runtime for metacore hosts — renders addon contributions dynamically",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -67,8 +67,8 @@
|
|
|
67
67
|
"typescript": "^6.0.0",
|
|
68
68
|
"vitest": "^4.0.0",
|
|
69
69
|
"zustand": "^5.0.0",
|
|
70
|
-
"@asteby/metacore-
|
|
71
|
-
"@asteby/metacore-
|
|
70
|
+
"@asteby/metacore-ui": "2.17.3",
|
|
71
|
+
"@asteby/metacore-sdk": "3.7.0"
|
|
72
72
|
},
|
|
73
73
|
"scripts": {
|
|
74
74
|
"build": "tsc -p tsconfig.json",
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { applyLineItemRowFormulas } from '../dynamic-form-schema'
|
|
3
|
+
import type { ActionFieldDef } from '../types'
|
|
4
|
+
|
|
5
|
+
const fields: ActionFieldDef[] = [
|
|
6
|
+
{ key: 'product_id', label: 'Producto', type: 'dynamic_select' },
|
|
7
|
+
{ key: 'qty', label: 'Cantidad', type: 'number' },
|
|
8
|
+
{ key: 'unit_price', label: 'Precio', type: 'number' },
|
|
9
|
+
{ key: 'discount', label: 'Descuento', type: 'number' },
|
|
10
|
+
{ key: 'subtotal', label: 'Importe', type: 'number' },
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
describe('applyLineItemRowFormulas', () => {
|
|
14
|
+
it('computes qty * unit_price - discount into subtotal', () => {
|
|
15
|
+
const row = applyLineItemRowFormulas(fields, {
|
|
16
|
+
product_id: 'p1',
|
|
17
|
+
qty: 3,
|
|
18
|
+
unit_price: 10,
|
|
19
|
+
discount: 5,
|
|
20
|
+
subtotal: 0,
|
|
21
|
+
})
|
|
22
|
+
expect(row.subtotal).toBe(25)
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
it('treats blank discount as 0', () => {
|
|
26
|
+
const row = applyLineItemRowFormulas(fields, {
|
|
27
|
+
qty: '2',
|
|
28
|
+
unit_price: '12.5',
|
|
29
|
+
discount: '',
|
|
30
|
+
subtotal: '',
|
|
31
|
+
})
|
|
32
|
+
expect(row.subtotal).toBe(25)
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
it('is a no-op without an amount column', () => {
|
|
36
|
+
const lean: ActionFieldDef[] = [
|
|
37
|
+
{ key: 'qty', label: 'Cantidad', type: 'number' },
|
|
38
|
+
{ key: 'unit_price', label: 'Precio', type: 'number' },
|
|
39
|
+
]
|
|
40
|
+
const input = { qty: 2, unit_price: 5 }
|
|
41
|
+
expect(applyLineItemRowFormulas(lean, input)).toBe(input)
|
|
42
|
+
})
|
|
43
|
+
})
|
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
import { Loader2 } from 'lucide-react'
|
|
39
39
|
import { toast } from 'sonner'
|
|
40
40
|
import { toastServerError, toastServerSuccess, extractFieldErrors, localizeFieldErrorMap } from './server-error'
|
|
41
|
+
import { useBranchCreateGate } from './branch-create-gate'
|
|
41
42
|
import type { Translate } from './server-error'
|
|
42
43
|
import { validateValues, bagHasErrors } from './validator'
|
|
43
44
|
import {
|
|
@@ -588,6 +589,7 @@ function GenericActionModal({ open, onOpenChange, action, model, record, endpoin
|
|
|
588
589
|
// defaultValue keeps an already-localized string unchanged.
|
|
589
590
|
const tl = (s: string) => t(s, { defaultValue: s })
|
|
590
591
|
const api = useApi()
|
|
592
|
+
const branchGate = useBranchCreateGate()
|
|
591
593
|
const [formData, setFormData] = useState<Record<string, any>>({})
|
|
592
594
|
const [executing, setExecuting] = useState(false)
|
|
593
595
|
// Per-field validation errors (localized), shown inline under each input.
|
|
@@ -671,8 +673,26 @@ function GenericActionModal({ open, onOpenChange, action, model, record, endpoin
|
|
|
671
673
|
setFieldErrors({})
|
|
672
674
|
setExecuting(true)
|
|
673
675
|
try {
|
|
674
|
-
|
|
675
|
-
|
|
676
|
+
let payload: Record<string, any> = { ...formData }
|
|
677
|
+
// Create-placement actions (and any create with no record) may need a
|
|
678
|
+
// host branch stamp when the sidebar is on "Todas". Skip when the
|
|
679
|
+
// form already collected branch_id, or the host has no gate.
|
|
680
|
+
const isCreatePlacement =
|
|
681
|
+
action.placement === 'create' ||
|
|
682
|
+
record?.id == null ||
|
|
683
|
+
record?.id === '' ||
|
|
684
|
+
record?.id === 'undefined'
|
|
685
|
+
if (
|
|
686
|
+
branchGate &&
|
|
687
|
+
isCreatePlacement &&
|
|
688
|
+
(payload.branch_id == null || payload.branch_id === '')
|
|
689
|
+
) {
|
|
690
|
+
const branchId = await branchGate.ensureBranchForCreate(model)
|
|
691
|
+
if (branchId === null) return
|
|
692
|
+
if (branchId) payload = { ...payload, branch_id: branchId }
|
|
693
|
+
}
|
|
694
|
+
const url = buildActionUrl(endpoint, model, record?.id, action.key)
|
|
695
|
+
const res = await api.post(url, payload)
|
|
676
696
|
if (res.data.success) {
|
|
677
697
|
toastServerSuccess(res.data, { t })
|
|
678
698
|
onOpenChange(false)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional host gate for stamping `branch_id` on creates when the sidebar is
|
|
3
|
+
* on "all branches" (no active scope).
|
|
4
|
+
*
|
|
5
|
+
* Ops (and other hosts) provide a provider that opens a confirm + branch
|
|
6
|
+
* picker. The SDK's DynamicRecordDialog / ActionModalDispatcher call
|
|
7
|
+
* `ensureBranchForCreate` right before POST — custom federated modals can use
|
|
8
|
+
* the same hook so POS-style flows stay consistent.
|
|
9
|
+
*
|
|
10
|
+
* Return contract for `ensureBranchForCreate`:
|
|
11
|
+
* - `undefined` — model has no branch_id / gate not needed / already scoped
|
|
12
|
+
* - `string` — branch id to stamp onto the payload
|
|
13
|
+
* - `null` — user cancelled the picker (abort submit)
|
|
14
|
+
*/
|
|
15
|
+
import { createContext, useContext, type ReactNode } from 'react'
|
|
16
|
+
|
|
17
|
+
export type BranchCreateGateApi = {
|
|
18
|
+
ensureBranchForCreate: (model: string) => Promise<string | null | undefined>
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const BranchCreateGateContext = createContext<BranchCreateGateApi | null>(null)
|
|
22
|
+
|
|
23
|
+
export function BranchCreateGateProvider({
|
|
24
|
+
value,
|
|
25
|
+
children,
|
|
26
|
+
}: {
|
|
27
|
+
value: BranchCreateGateApi
|
|
28
|
+
children: ReactNode
|
|
29
|
+
}) {
|
|
30
|
+
return (
|
|
31
|
+
<BranchCreateGateContext.Provider value={value}>
|
|
32
|
+
{children}
|
|
33
|
+
</BranchCreateGateContext.Provider>
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Hook for custom / federated create modals. Returns null when no host gate. */
|
|
38
|
+
export function useBranchCreateGate(): BranchCreateGateApi | null {
|
|
39
|
+
return useContext(BranchCreateGateContext)
|
|
40
|
+
}
|
|
@@ -53,6 +53,7 @@ import { es } from 'date-fns/locale'
|
|
|
53
53
|
import { ExternalLink, Loader2, CalendarIcon, ChevronDown, Check, Upload, X as XIcon, ScanLine } from 'lucide-react'
|
|
54
54
|
import { BarcodeScanner } from '../barcode-scanner'
|
|
55
55
|
import { useApi } from '../api-context'
|
|
56
|
+
import { useBranchCreateGate } from '../branch-create-gate'
|
|
56
57
|
import { toastServerError, extractFieldErrors, localizeFieldIssue, localizeFieldErrorMap } from '../server-error'
|
|
57
58
|
import { DynamicSelectField, OptionLead, OptionThumb } from '../dynamic-select-field'
|
|
58
59
|
import { DynamicRelations } from '../dynamic-relations'
|
|
@@ -614,6 +615,7 @@ export function DynamicRecordDialog({
|
|
|
614
615
|
onChange,
|
|
615
616
|
}: DynamicRecordDialogProps) {
|
|
616
617
|
const api = useApi()
|
|
618
|
+
const branchGate = useBranchCreateGate()
|
|
617
619
|
const { t } = useTranslation()
|
|
618
620
|
const [modalMeta, setModalMeta] = useState<ModalMetadata | null>(
|
|
619
621
|
schema ? (schema as ModalMetadata) : null,
|
|
@@ -892,7 +894,17 @@ export function DynamicRecordDialog({
|
|
|
892
894
|
|
|
893
895
|
// Empty reference pickers → null (not "" / nil-UUID) so nullable FK
|
|
894
896
|
// columns accept them instead of raising a 23503 FK violation.
|
|
895
|
-
|
|
897
|
+
let payload = normalizeRefFieldsForSubmit(submittedValues, modalMeta.fields)
|
|
898
|
+
|
|
899
|
+
if (
|
|
900
|
+
isCreate &&
|
|
901
|
+
branchGate &&
|
|
902
|
+
(payload.branch_id == null || payload.branch_id === '')
|
|
903
|
+
) {
|
|
904
|
+
const branchId = await branchGate.ensureBranchForCreate(model)
|
|
905
|
+
if (branchId === null) return
|
|
906
|
+
if (branchId) payload = { ...payload, branch_id: branchId }
|
|
907
|
+
}
|
|
896
908
|
|
|
897
909
|
setSaving(true)
|
|
898
910
|
try {
|
|
@@ -119,6 +119,57 @@ export function computeLineItemTotals(
|
|
|
119
119
|
return totals
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
+
/** Keys that mean "line net amount" across manifests / locales. */
|
|
123
|
+
const LINE_AMOUNT_KEYS = new Set(['subtotal', 'line_total', 'importe', 'amount', 'total'])
|
|
124
|
+
/** Keys that mean quantity on a line row. */
|
|
125
|
+
const LINE_QTY_KEYS = new Set(['qty', 'quantity', 'cantidad'])
|
|
126
|
+
/** Keys that mean unit price. */
|
|
127
|
+
const LINE_PRICE_KEYS = new Set(['unit_price', 'price', 'precio', 'precio_unitario'])
|
|
128
|
+
/** Keys that mean line discount (absolute). */
|
|
129
|
+
const LINE_DISCOUNT_KEYS = new Set(['discount', 'descuento', 'discount_amount'])
|
|
130
|
+
|
|
131
|
+
function firstKey(rowOrFields: { key?: string }[] | Record<string, unknown>, candidates: Set<string>): string | undefined {
|
|
132
|
+
if (Array.isArray(rowOrFields)) {
|
|
133
|
+
for (const f of rowOrFields) {
|
|
134
|
+
if (f.key && candidates.has(f.key)) return f.key
|
|
135
|
+
}
|
|
136
|
+
return undefined
|
|
137
|
+
}
|
|
138
|
+
for (const k of Object.keys(rowOrFields)) {
|
|
139
|
+
if (candidates.has(k)) return k
|
|
140
|
+
}
|
|
141
|
+
return undefined
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Live line-amount formula for action / form line-items grids:
|
|
146
|
+
* `(qty|quantity) * (unit_price|…) - (discount|…)` → `subtotal|line_total|importe`.
|
|
147
|
+
*
|
|
148
|
+
* Pure + convention-based so create_sales_order (and similar modals) show
|
|
149
|
+
* Importe as the user types without each manifest declaring a client formula.
|
|
150
|
+
* No-op when the row has no amount column or no qty/price pair.
|
|
151
|
+
*/
|
|
152
|
+
export function applyLineItemRowFormulas(
|
|
153
|
+
itemFields: ActionFieldDef[],
|
|
154
|
+
row: Record<string, any>,
|
|
155
|
+
): Record<string, any> {
|
|
156
|
+
const amountKey =
|
|
157
|
+
firstKey(itemFields, LINE_AMOUNT_KEYS) ?? firstKey(row, LINE_AMOUNT_KEYS)
|
|
158
|
+
const qtyKey = firstKey(itemFields, LINE_QTY_KEYS) ?? firstKey(row, LINE_QTY_KEYS)
|
|
159
|
+
const priceKey =
|
|
160
|
+
firstKey(itemFields, LINE_PRICE_KEYS) ?? firstKey(row, LINE_PRICE_KEYS)
|
|
161
|
+
if (!amountKey || !qtyKey || !priceKey) return row
|
|
162
|
+
|
|
163
|
+
const discountKey =
|
|
164
|
+
firstKey(itemFields, LINE_DISCOUNT_KEYS) ?? firstKey(row, LINE_DISCOUNT_KEYS)
|
|
165
|
+
const qty = toNumber(row[qtyKey])
|
|
166
|
+
const price = toNumber(row[priceKey])
|
|
167
|
+
const discount = discountKey ? toNumber(row[discountKey]) : 0
|
|
168
|
+
const next = Math.round((qty * price - discount) * 100) / 100
|
|
169
|
+
if (toNumber(row[amountKey]) === next) return row
|
|
170
|
+
return { ...row, [amountKey]: next }
|
|
171
|
+
}
|
|
172
|
+
|
|
122
173
|
export interface BalanceState {
|
|
123
174
|
debit: number
|
|
124
175
|
credit: number
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
resolveWidget,
|
|
26
26
|
getItemFields,
|
|
27
27
|
computeLineItemTotals,
|
|
28
|
+
applyLineItemRowFormulas,
|
|
28
29
|
evaluateBalance,
|
|
29
30
|
toNumber,
|
|
30
31
|
getDependsOn,
|
|
@@ -87,10 +88,16 @@ export function DynamicLineItems({ field, value, onChange, disabled = false, for
|
|
|
87
88
|
const hasTotals = totalKeys.length > 0
|
|
88
89
|
const balance = evaluateBalance(field, rows)
|
|
89
90
|
|
|
90
|
-
const addRow = () => onChange([...rows, emptyRow(itemFields)])
|
|
91
|
+
const addRow = () => onChange([...rows, applyLineItemRowFormulas(itemFields, emptyRow(itemFields))])
|
|
91
92
|
const removeRow = (idx: number) => onChange(rows.filter((_, i) => i !== idx))
|
|
92
93
|
const updateCell = (idx: number, key: string, cellValue: any) =>
|
|
93
|
-
onChange(
|
|
94
|
+
onChange(
|
|
95
|
+
rows.map((r, i) =>
|
|
96
|
+
i === idx
|
|
97
|
+
? applyLineItemRowFormulas(itemFields, { ...r, [key]: cellValue })
|
|
98
|
+
: r,
|
|
99
|
+
),
|
|
100
|
+
)
|
|
94
101
|
|
|
95
102
|
// When a balance rule reconciles two columns (e.g. debit ↔ credit), typing
|
|
96
103
|
// into one clears the sibling on the same row — mirrors the federated modal
|
|
@@ -111,7 +118,13 @@ export function DynamicLineItems({ field, value, onChange, disabled = false, for
|
|
|
111
118
|
const hasValue = toNumber(cellValue) > 0
|
|
112
119
|
onChange(
|
|
113
120
|
rows.map((r, i) =>
|
|
114
|
-
i === idx
|
|
121
|
+
i === idx
|
|
122
|
+
? applyLineItemRowFormulas(itemFields, {
|
|
123
|
+
...r,
|
|
124
|
+
[key]: cellValue,
|
|
125
|
+
...(hasValue ? { [sibling]: '' } : {}),
|
|
126
|
+
})
|
|
127
|
+
: r,
|
|
115
128
|
),
|
|
116
129
|
)
|
|
117
130
|
return
|
package/src/dynamic-table.tsx
CHANGED
|
@@ -367,6 +367,36 @@ export function DynamicTable({
|
|
|
367
367
|
// been adopted, where `dynamicFilters`/`pagination` already mirror the URL,
|
|
368
368
|
// so the write is a no-op and the filter never gets stripped.
|
|
369
369
|
const [urlSynced, setUrlSynced] = useState(false)
|
|
370
|
+
// Keys that left `defaultFilters` (e.g. branch_id when switching to
|
|
371
|
+
// "Todas las sucursales"). The URL write effect used to carry-through every
|
|
372
|
+
// leftover `f_*` from location — that resurrected the locked branch filter
|
|
373
|
+
// forever after the host dropped it from defaultFilters.
|
|
374
|
+
const prevDefaultFilterKeys = useRef<Set<string>>(new Set())
|
|
375
|
+
const releasedDefaultFilterKeys = useRef<Set<string>>(new Set())
|
|
376
|
+
|
|
377
|
+
useEffect(() => {
|
|
378
|
+
const next = new Set(Object.keys(defaultFilters ?? {}))
|
|
379
|
+
const prev = prevDefaultFilterKeys.current
|
|
380
|
+
const released = new Set<string>()
|
|
381
|
+
prev.forEach((k) => {
|
|
382
|
+
if (!next.has(k)) released.add(k)
|
|
383
|
+
})
|
|
384
|
+
releasedDefaultFilterKeys.current = released
|
|
385
|
+
if (released.size > 0) {
|
|
386
|
+
setDynamicFilters((df) => {
|
|
387
|
+
let changed = false
|
|
388
|
+
const copy = { ...df }
|
|
389
|
+
released.forEach((k) => {
|
|
390
|
+
if (k in copy) {
|
|
391
|
+
delete copy[k]
|
|
392
|
+
changed = true
|
|
393
|
+
}
|
|
394
|
+
})
|
|
395
|
+
return changed ? copy : df
|
|
396
|
+
})
|
|
397
|
+
}
|
|
398
|
+
prevDefaultFilterKeys.current = next
|
|
399
|
+
}, [defaultFilters])
|
|
370
400
|
|
|
371
401
|
useEffect(() => {
|
|
372
402
|
if (prevBranchId.current !== currentBranch?.id) {
|
|
@@ -513,9 +543,13 @@ export function DynamicTable({
|
|
|
513
543
|
// Sidebar deep-links (CxC→CxP) push f_party_type=eq:supplier before React
|
|
514
544
|
// re-renders with matching defaultFilters; without this carry-through the
|
|
515
545
|
// write effect races and strips the filter down to bare ?view=list.
|
|
546
|
+
// Do NOT resurrect keys the host just released from defaultFilters
|
|
547
|
+
// (branch_id when switching to "all" — otherwise San Felipe sticks).
|
|
516
548
|
current.forEach((value, key) => {
|
|
517
549
|
if (!key.startsWith('f_')) return
|
|
518
550
|
if (params.has(key)) return
|
|
551
|
+
const filterKey = key.substring(2)
|
|
552
|
+
if (releasedDefaultFilterKeys.current.has(filterKey)) return
|
|
519
553
|
params.set(key, value)
|
|
520
554
|
})
|
|
521
555
|
const search = params.toString()
|
package/src/index.ts
CHANGED
|
@@ -385,7 +385,15 @@ export {
|
|
|
385
385
|
scopeValueFromFilterToken,
|
|
386
386
|
buildListScopeValues,
|
|
387
387
|
evaluateVisibleWhenForListScope,
|
|
388
|
+
applyLineItemRowFormulas,
|
|
389
|
+
computeLineItemTotals,
|
|
390
|
+
toNumber,
|
|
388
391
|
} from './dynamic-form-schema'
|
|
392
|
+
export {
|
|
393
|
+
BranchCreateGateProvider,
|
|
394
|
+
useBranchCreateGate,
|
|
395
|
+
type BranchCreateGateApi,
|
|
396
|
+
} from './branch-create-gate'
|
|
389
397
|
export {
|
|
390
398
|
ActivityValueRenderer,
|
|
391
399
|
type ActivityValueRendererProps,
|