@asteby/metacore-runtime-react 49.7.0 → 49.9.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 +25 -0
- package/dist/business/document-editor-model.d.ts +27 -2
- package/dist/business/document-editor-model.d.ts.map +1 -1
- package/dist/business/document-editor-model.js +53 -3
- package/dist/business/document-editor.d.ts +7 -2
- package/dist/business/document-editor.d.ts.map +1 -1
- package/dist/business/document-editor.js +121 -22
- package/dist/business/document-lines.d.ts +21 -1
- package/dist/business/document-lines.d.ts.map +1 -1
- package/dist/business/document-lines.js +69 -7
- package/dist/business/index.d.ts +1 -0
- package/dist/business/index.d.ts.map +1 -1
- package/dist/business/index.js +1 -0
- package/dist/business/line-items-editor.d.ts +21 -1
- package/dist/business/line-items-editor.d.ts.map +1 -1
- package/dist/business/line-items-editor.js +74 -15
- package/dist/business/line-items.d.ts +28 -0
- package/dist/business/line-items.d.ts.map +1 -1
- package/dist/business/line-items.js +1 -0
- package/dist/business/line-product-cell.d.ts +6 -0
- package/dist/business/line-product-cell.d.ts.map +1 -1
- package/dist/business/line-product-cell.js +9 -3
- package/dist/business/product-display.d.ts +18 -0
- package/dist/business/product-display.d.ts.map +1 -0
- package/dist/business/product-display.js +40 -0
- package/dist/business/product-options.d.ts +6 -1
- package/dist/business/product-options.d.ts.map +1 -1
- package/dist/business/product-options.js +11 -2
- package/dist/business/product-search.d.ts +8 -0
- package/dist/business/product-search.d.ts.map +1 -1
- package/dist/dialogs/dynamic-record.js +1 -1
- package/dist/dynamic-select-field.d.ts +7 -1
- package/dist/dynamic-select-field.d.ts.map +1 -1
- package/dist/dynamic-select-field.js +18 -4
- package/dist/field-grid.d.ts +4 -3
- package/dist/field-grid.d.ts.map +1 -1
- package/dist/field-grid.js +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/option-display.d.ts +68 -0
- package/dist/option-display.d.ts.map +1 -0
- package/dist/option-display.js +135 -0
- package/dist/query-batch.d.ts +1 -1
- package/dist/query-batch.d.ts.map +1 -1
- package/dist/query-batch.js +3 -1
- package/dist/record-picker.d.ts +2 -0
- package/dist/record-picker.d.ts.map +1 -1
- package/dist/record-picker.js +11 -4
- package/dist/use-options-resolver.d.ts +16 -1
- package/dist/use-options-resolver.d.ts.map +1 -1
- package/dist/use-options-resolver.js +38 -6
- package/package.json +1 -1
- package/src/__tests__/document-editor-inline-selects.test.tsx +11 -4
- package/src/__tests__/line-row-create-edit.test.tsx +312 -0
- package/src/__tests__/option-display.test.tsx +241 -0
- package/src/business/document-editor-model.ts +60 -2
- package/src/business/document-editor.tsx +143 -19
- package/src/business/document-lines.ts +79 -7
- package/src/business/index.ts +1 -0
- package/src/business/line-items-editor.tsx +158 -30
- package/src/business/line-items.ts +31 -0
- package/src/business/line-product-cell.tsx +32 -5
- package/src/business/product-display.ts +62 -0
- package/src/business/product-options.tsx +11 -2
- package/src/business/product-search.ts +8 -0
- package/src/dialogs/dynamic-record.tsx +1 -1
- package/src/dynamic-select-field.tsx +45 -1
- package/src/field-grid.tsx +5 -4
- package/src/index.ts +10 -0
- package/src/option-display.tsx +255 -0
- package/src/query-batch.ts +2 -0
- package/src/record-picker.tsx +16 -3
- package/src/use-options-resolver.ts +49 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# @asteby/metacore-runtime-react
|
|
2
2
|
|
|
3
|
+
## 49.9.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- be68177: Selectores con presentación declarativa (`option_display` del kernel): el
|
|
8
|
+
`DynamicSelectField` pinta la fila que resolvió el servidor — avatar 32px,
|
|
9
|
+
título a 2 líneas, subtítulo atenuado, badges y métricas a la derecha con
|
|
10
|
+
`tabular-nums` (precio con la moneda de la org, existencia como chip con tono:
|
|
11
|
+
«Agotado» en danger atenuando la fila pero seleccionable, poco stock en
|
|
12
|
+
warning) — y el disparador muestra un resumen compacto; una opción `blocked`
|
|
13
|
+
no se puede elegir. Sin display, la fila de siempre. Nuevos
|
|
14
|
+
`OptionDisplayRow`, `OptionDisplayValue`, `getOptionDisplay`,
|
|
15
|
+
`formatTrailingValue`; `ResolvedOption.display`; contexto del selector
|
|
16
|
+
(`useOptionsResolver({ context })` / `DynamicSelectField optionsContext` →
|
|
17
|
+
`?ctx.<key>=`, también en el token del batch). El buscador de renglones del
|
|
18
|
+
`DocumentEditor` completa sus resultados con una sola consulta `?ids=` al
|
|
19
|
+
catálogo (`withOptionDisplays`, con el almacén del encabezado como contexto),
|
|
20
|
+
así la celda de producto muestra precio + existencia con su tono.
|
|
21
|
+
|
|
22
|
+
## 49.8.0
|
|
23
|
+
|
|
24
|
+
### Minor Changes
|
|
25
|
+
|
|
26
|
+
- 13e4aaf: DocumentEditor: crear y editar el producto desde la celda del renglón. «Crear producto «texto»» y «+» abren el alta del modelo de catálogo (metacore:create-record) prellenada con lo buscado y el producto nuevo llena ESE renglón con el mismo mapeo que al elegirlo; el lápiz (hover/foco, accesible por teclado) abre la edición (metacore:edit-record) y al guardar el renglón se actualiza salvo los campos que el usuario sobrescribió (dirty por campo contra la foto del catálogo), con aviso «Precio de catálogo cambió a $X — aplicar». Los renglones de un documento origen no cambian cantidad, tope ni precios. Tarjeta de la contraparte con etiquetas de la metadata (clave corta si la larga no resuelve) y valores de catálogo «G03 · Gastos en general», sin vacíos. Placeholder corto «Buscar producto…» con la ayuda como tooltip y en el estado vacío; el buscador del renglón vacío usa el ancho de las columnas que aún no llena; la unidad bajo el SKU sale con su etiqueta (nunca la clave cruda). RecordPicker: la lista se acota al alto disponible (no se sale del viewport al abrirse hacia arriba), `maxListWidth` y nombres a 2 líneas. FieldLabel y el modal genérico usan sentence case por defecto.
|
|
27
|
+
|
|
3
28
|
## 49.7.0
|
|
4
29
|
|
|
5
30
|
### Minor Changes
|
|
@@ -61,8 +61,33 @@ export declare function gatedOptionFixes(fields: readonly ActionFieldDef[], valu
|
|
|
61
61
|
* Solo llena lo que está vacío: nunca pisa lo que el usuario ya capturó.
|
|
62
62
|
*/
|
|
63
63
|
export declare function partyDefaults(party: Record<string, any> | null, documentFieldKeys: readonly string[], current: Record<string, unknown>): Record<string, unknown>;
|
|
64
|
-
/**
|
|
65
|
-
export
|
|
64
|
+
/** Etiqueta y opciones de catálogo de un campo (de la metadata del modelo o del propio tipo). */
|
|
65
|
+
export interface FieldDisplayMeta {
|
|
66
|
+
label?: string;
|
|
67
|
+
options?: ReadonlyArray<{
|
|
68
|
+
value: unknown;
|
|
69
|
+
label?: unknown;
|
|
70
|
+
}>;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Metadata de pantalla por clave a partir de listas de campos/columnas
|
|
74
|
+
* (`/metadata/modal` → fields, `/metadata/table` → columns, campos del tipo).
|
|
75
|
+
* La primera lista que trae etiqueta u opciones para una clave gana.
|
|
76
|
+
*/
|
|
77
|
+
export declare function fieldDisplayMeta(lists: ReadonlyArray<ReadonlyArray<unknown> | null | undefined>, translate?: (s: string) => string): Record<string, FieldDisplayMeta>;
|
|
78
|
+
/** `tax_id` → «Tax id»: último recurso cuando ningún metadata etiqueta la columna. */
|
|
79
|
+
export declare function humanizeKey(key: string): string;
|
|
80
|
+
/**
|
|
81
|
+
* Valor de catálogo legible: `G03` con la opción «Gastos en general» →
|
|
82
|
+
* «G03 · Gastos en general» (si la etiqueta ya trae el código, tal cual).
|
|
83
|
+
*/
|
|
84
|
+
export declare function formatOptionValue(value: unknown, options?: FieldDisplayMeta['options']): string;
|
|
85
|
+
/**
|
|
86
|
+
* Filas de la tarjeta de contraparte: resumen declarado + extensiones (máximo
|
|
87
|
+
* `limit`). Etiqueta del campo (metadata / labels declarados, ya traducidos),
|
|
88
|
+
* valores de catálogo con su texto y nunca claves crudas ni vacíos.
|
|
89
|
+
*/
|
|
90
|
+
export declare function partySummaryRows(party: Record<string, any> | null, summary?: readonly string[], labels?: Record<string, string>, limit?: number, meta?: Record<string, FieldDisplayMeta>): Array<{
|
|
66
91
|
key: string;
|
|
67
92
|
label: string;
|
|
68
93
|
value: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"document-editor-model.d.ts","sourceRoot":"","sources":["../../src/business/document-editor-model.ts"],"names":[],"mappings":"AAMA,OAAO,EAA2B,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAA;AAIrE,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACzF,OAAO,KAAK,EACR,cAAc,EACd,iBAAiB,EACjB,kBAAkB,EAClB,yBAAyB,EACzB,qBAAqB,EACrB,gBAAgB,EACnB,MAAM,UAAU,CAAA;AAEjB,eAAO,MAAM,gBAAgB,iBAAiB,CAAA;AAK9C,MAAM,MAAM,iBAAiB,GAAG,iBAAiB,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAErE,yEAAyE;AACzE,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,gBAAgB,EAAE,QAAQ,GAAG,SAAS,CAAC,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAI7G;AAED,qEAAqE;AACrE,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE,IAAI,CAAC,qBAAqB,EAAE,aAAa,CAAC,GAAG,iBAAiB,GAAG,SAAS,CAK1I;AAeD;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,cAAc,EAAE,aAAa,GAAE,WAAW,CAAC,MAAM,CAAa,GAAG,OAAO,CAM1G;AAED,MAAM,WAAW,iBAAiB;IAC9B,iFAAiF;IACjF,KAAK,CAAC,EAAE,cAAc,CAAA;IACtB,8CAA8C;IAC9C,SAAS,EAAE,cAAc,EAAE,CAAA;IAC3B,uCAAuC;IACvC,QAAQ,EAAE,cAAc,EAAE,CAAA;IAC1B,yCAAyC;IACzC,KAAK,EAAE,cAAc,EAAE,CAAA;CAC1B;AAED,gFAAgF;AAChF,wBAAgB,iBAAiB,CAC7B,MAAM,EAAE,SAAS,cAAc,EAAE,EACjC,IAAI,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,eAAe,CAAC,EAAE,SAAS,cAAc,EAAE,CAAA;CAAO,GACnH,iBAAiB,CAgBnB;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGzD;AAED,mEAAmE;AACnE,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,cAAc,GAAG,cAAc,CAGrE;AAOD,mFAAmF;AACnF,wBAAgB,YAAY,CAAC,CAAC,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,cAAc,CAG/F;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAc5H;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CACzB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,EACjC,iBAAiB,EAAE,SAAS,MAAM,EAAE,EACpC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAYzB;AAED,
|
|
1
|
+
{"version":3,"file":"document-editor-model.d.ts","sourceRoot":"","sources":["../../src/business/document-editor-model.ts"],"names":[],"mappings":"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"}
|
|
@@ -152,8 +152,55 @@ export function partyDefaults(party, documentFieldKeys, current) {
|
|
|
152
152
|
}
|
|
153
153
|
return out;
|
|
154
154
|
}
|
|
155
|
-
/**
|
|
156
|
-
|
|
155
|
+
/**
|
|
156
|
+
* Metadata de pantalla por clave a partir de listas de campos/columnas
|
|
157
|
+
* (`/metadata/modal` → fields, `/metadata/table` → columns, campos del tipo).
|
|
158
|
+
* La primera lista que trae etiqueta u opciones para una clave gana.
|
|
159
|
+
*/
|
|
160
|
+
export function fieldDisplayMeta(lists, translate = (s) => s) {
|
|
161
|
+
const out = {};
|
|
162
|
+
for (const list of lists) {
|
|
163
|
+
for (const raw of list ?? []) {
|
|
164
|
+
const f = raw;
|
|
165
|
+
const key = typeof f?.key === 'string' ? f.key : typeof f?.name === 'string' ? f.name : undefined;
|
|
166
|
+
if (!key)
|
|
167
|
+
continue;
|
|
168
|
+
const cur = (out[key] ??= {});
|
|
169
|
+
if (!cur.label && typeof f.label === 'string' && f.label)
|
|
170
|
+
cur.label = translate(f.label);
|
|
171
|
+
if (!cur.options && Array.isArray(f.options) && f.options.length > 0) {
|
|
172
|
+
cur.options = f.options.map((o) => ({ value: o?.value, label: typeof o?.label === 'string' ? translate(o.label) : o?.label }));
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return out;
|
|
177
|
+
}
|
|
178
|
+
/** `tax_id` → «Tax id»: último recurso cuando ningún metadata etiqueta la columna. */
|
|
179
|
+
export function humanizeKey(key) {
|
|
180
|
+
const base = key.replace(EXTENSION_PREFIX, '').replace(/[_.]+/g, ' ').trim();
|
|
181
|
+
return base ? base.charAt(0).toUpperCase() + base.slice(1) : key;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Valor de catálogo legible: `G03` con la opción «Gastos en general» →
|
|
185
|
+
* «G03 · Gastos en general» (si la etiqueta ya trae el código, tal cual).
|
|
186
|
+
*/
|
|
187
|
+
export function formatOptionValue(value, options) {
|
|
188
|
+
const raw = String(value);
|
|
189
|
+
const opt = options?.find((o) => String(o.value) === raw);
|
|
190
|
+
const label = opt && typeof opt.label === 'string' ? opt.label.trim() : '';
|
|
191
|
+
if (!label || label === raw)
|
|
192
|
+
return raw;
|
|
193
|
+
if (label.includes(raw))
|
|
194
|
+
return label;
|
|
195
|
+
const codeLike = /^[A-Z0-9]{1,5}$/.test(raw) && /\d/.test(raw);
|
|
196
|
+
return codeLike ? `${raw} · ${label}` : label;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Filas de la tarjeta de contraparte: resumen declarado + extensiones (máximo
|
|
200
|
+
* `limit`). Etiqueta del campo (metadata / labels declarados, ya traducidos),
|
|
201
|
+
* valores de catálogo con su texto y nunca claves crudas ni vacíos.
|
|
202
|
+
*/
|
|
203
|
+
export function partySummaryRows(party, summary = [], labels = {}, limit = 6, meta = {}) {
|
|
157
204
|
if (!party)
|
|
158
205
|
return [];
|
|
159
206
|
const keys = new Set(summary);
|
|
@@ -166,7 +213,10 @@ export function partySummaryRows(party, summary = [], labels = {}, limit = 6) {
|
|
|
166
213
|
const v = readPath(party, key);
|
|
167
214
|
if (!hasValue(v) || typeof v === 'object')
|
|
168
215
|
continue;
|
|
169
|
-
|
|
216
|
+
if (typeof v === 'string' && !v.trim())
|
|
217
|
+
continue;
|
|
218
|
+
const m = meta[key];
|
|
219
|
+
rows.push({ key, label: labels[key] ?? m?.label ?? humanizeKey(key), value: formatOptionValue(v, m?.options) });
|
|
170
220
|
}
|
|
171
221
|
return rows.slice(0, limit);
|
|
172
222
|
}
|
|
@@ -16,8 +16,13 @@ export interface DocumentEditorProps {
|
|
|
16
16
|
onSaved?: (record?: unknown) => void;
|
|
17
17
|
onCancel: () => void;
|
|
18
18
|
searchProducts?: DocumentLinesGridProps['search'];
|
|
19
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* Modelo de catálogo: buscador por defecto y alta/edición del producto
|
|
21
|
+
* desde la celda del renglón. Default `products.Product`.
|
|
22
|
+
*/
|
|
20
23
|
productModel?: string;
|
|
24
|
+
/** Columna del modelo de catálogo que recibe lo buscado al crear. Default `name`. */
|
|
25
|
+
productLabelField?: string;
|
|
21
26
|
defaultTaxRate?: number;
|
|
22
27
|
currency?: string;
|
|
23
28
|
/** Hoy (días de atraso del reparto; inyectable en tests). */
|
|
@@ -29,5 +34,5 @@ export interface DocumentEditorProps {
|
|
|
29
34
|
*/
|
|
30
35
|
fullscreen?: boolean;
|
|
31
36
|
}
|
|
32
|
-
export declare function DocumentEditor({ model, endpoint, forms, type, record, initialSource, onSaved, onCancel, searchProducts, productModel, defaultTaxRate, currency, today, fullscreen, }: DocumentEditorProps): import("react").JSX.Element;
|
|
37
|
+
export declare function DocumentEditor({ model, endpoint, forms, type, record, initialSource, onSaved, onCancel, searchProducts, productModel, productLabelField, defaultTaxRate, currency, today, fullscreen, }: DocumentEditorProps): import("react").JSX.Element;
|
|
33
38
|
//# sourceMappingURL=document-editor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"document-editor.d.ts","sourceRoot":"","sources":["../../src/business/document-editor.tsx"],"names":[],"mappings":"AA4BA,OAAO,EAAqB,KAAK,sBAAsB,EAAwB,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"document-editor.d.ts","sourceRoot":"","sources":["../../src/business/document-editor.tsx"],"names":[],"mappings":"AA4BA,OAAO,EAAqB,KAAK,sBAAsB,EAAwB,MAAM,qBAAqB,CAAA;AAuD1G,OAAO,KAAK,EAAsC,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAA;AAE3G,MAAM,WAAW,mBAAmB;IAChC,KAAK,EAAE,MAAM,CAAA;IACb,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,qBAAqB,CAAA;IAC5B,IAAI,EAAE,gBAAgB,CAAA;IACtB,sFAAsF;IACtF,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC5B,oEAAoE;IACpE,aAAa,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAA;IAC3C,OAAO,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;IACpC,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,cAAc,CAAC,EAAE,sBAAsB,CAAC,QAAQ,CAAC,CAAA;IACjD;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,qFAAqF;IACrF,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,IAAI,CAAA;IACZ;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;CACvB;AAID,wBAAgB,cAAc,CAAC,EAC3B,KAAK,EACL,QAAQ,EACR,KAAK,EACL,IAAI,EACJ,MAAM,EACN,aAAa,EACb,OAAO,EACP,QAAQ,EACR,cAAc,EACd,YAAY,EACZ,iBAA0B,EAC1B,cAAc,EACd,QAAQ,EACR,KAAK,EACL,UAAkB,GACrB,EAAE,mBAAmB,+BA42BrB"}
|
|
@@ -30,8 +30,10 @@ import { FormErrorBanner } from './feedback';
|
|
|
30
30
|
import { DocumentLinesGrid } from './line-items-editor';
|
|
31
31
|
import { computeTotals, serializeLineItems, taxBreakdown } from './line-items';
|
|
32
32
|
import { roundMoney, toAmount, useFormatter } from './format';
|
|
33
|
-
import { createCatalogProductSearch } from './catalog-product-search';
|
|
34
|
-
import {
|
|
33
|
+
import { catalogRecordToProduct, createCatalogProductSearch } from './catalog-product-search';
|
|
34
|
+
import { withOptionDisplays } from './product-display';
|
|
35
|
+
import { requestRecordCreate, requestRecordEdit, withSearchPrefill } from '../record-picker-actions';
|
|
36
|
+
import { allocationAmountField, allocationIssueMessages, allocationPayload, creditStatus, editorLinesConfig, fieldDisplayMeta, linesFromSource, localIssues, sourceLoadSummary, sourceTracksRemaining, partyDefaults, partySummaryRows, recordLabel, seedRecord, sourceHeaderSeeds, splitEditorFields, toOpenDocuments, friendlyOptionLabel, gatedOptionFixes, gatedOptions, withFriendlyOptions, } from './document-editor-model';
|
|
35
37
|
import { CollapsibleSection, DraftPreview, EditorSection, PartyCard, PreviewPanel, TotalsPanel, ValidationChecklist, } from './document-editor-panels';
|
|
36
38
|
import { PaymentAllocator } from './payment-allocator';
|
|
37
39
|
import { actionErrorBannerMessage, buildFieldDefaults, prefillFromFieldRelationRequest, renderField } from '../action-modal-dispatcher';
|
|
@@ -43,7 +45,7 @@ import { evaluateVisibleWhen, getVisibleWhen } from '../dynamic-form-schema';
|
|
|
43
45
|
import { useInstalledAddons } from '../installed-addons-context';
|
|
44
46
|
import { allocatePayment, validateAllocation } from '../primitives/allocation';
|
|
45
47
|
import { useDocumentContributions } from '../primitives/use-contributions';
|
|
46
|
-
export function DocumentEditor({ model, endpoint, forms, type, record, initialSource, onSaved, onCancel, searchProducts, productModel, defaultTaxRate, currency, today, fullscreen = false, }) {
|
|
48
|
+
export function DocumentEditor({ model, endpoint, forms, type, record, initialSource, onSaved, onCancel, searchProducts, productModel, productLabelField = 'name', defaultTaxRate, currency, today, fullscreen = false, }) {
|
|
47
49
|
const { t, i18n } = useTranslation();
|
|
48
50
|
const lang = i18n?.language;
|
|
49
51
|
const api = useApi();
|
|
@@ -64,7 +66,8 @@ export function DocumentEditor({ model, endpoint, forms, type, record, initialSo
|
|
|
64
66
|
const [linesFromSourceDoc, setLinesFromSourceDoc] = useState(false);
|
|
65
67
|
const [extFields, setExtFields] = useState([]);
|
|
66
68
|
const [party, setParty] = useState(null);
|
|
67
|
-
const [
|
|
69
|
+
const [partyFieldLists, setPartyFieldLists] = useState([]);
|
|
70
|
+
const [catalogMeta, setCatalogMeta] = useState(null);
|
|
68
71
|
// Etiquetas de los selectores que el editor llena por código (contraparte y
|
|
69
72
|
// documento origen de «Cargar desde…»): sin ellas el selector cerrado pinta el UUID.
|
|
70
73
|
const [seeds, setSeeds] = useState({});
|
|
@@ -90,7 +93,10 @@ export function DocumentEditor({ model, endpoint, forms, type, record, initialSo
|
|
|
90
93
|
const [sourceSeed, setSourceSeed] = useState(null);
|
|
91
94
|
const relCache = useRef(new Map());
|
|
92
95
|
const taxRate = defaultTaxRate ?? orgTaxRate;
|
|
93
|
-
|
|
96
|
+
// The header's warehouse (when the document type declares one) scopes the
|
|
97
|
+
// stock the catalog's option_display shows in the product rows.
|
|
98
|
+
const headerWarehouse = typeof header.warehouse_id === 'string' ? header.warehouse_id : '';
|
|
99
|
+
const search = useMemo(() => withOptionDisplays(searchProducts ?? createCatalogProductSearch(api, { model: productModel, defaultTaxRate: taxRate }), api, { model: productModel ?? 'products.Product', context: { warehouse_id: headerWarehouse } }), [searchProducts, api, productModel, taxRate, headerWarehouse]);
|
|
94
100
|
const isInstalled = useCallback((k) => !k || !installed || installed.addons.has(k), [installed]);
|
|
95
101
|
const sources = useMemo(() => (type.sources ?? []).filter((s) => isInstalled(s.requires_addon)), [type.sources, isInstalled]);
|
|
96
102
|
const previewEnabled = !!type.preview && !type.submit_action && isInstalled(type.preview.requires_addon);
|
|
@@ -156,28 +162,86 @@ export function DocumentEditor({ model, endpoint, forms, type, record, initialSo
|
|
|
156
162
|
cancelled = true;
|
|
157
163
|
};
|
|
158
164
|
}, [api, type.party, partyId]);
|
|
159
|
-
// Etiquetas de la tarjeta (RFC, régimen…)
|
|
160
|
-
//
|
|
165
|
+
// Etiquetas de la tarjeta (RFC, régimen…) y texto de sus catálogos: la
|
|
166
|
+
// metadata del modelo de la contraparte (formulario, con extensiones, y
|
|
167
|
+
// tabla); sin ellas se veía la columna cruda (`tax_id`).
|
|
161
168
|
const partyModel = type.party?.model;
|
|
162
169
|
useEffect(() => {
|
|
163
170
|
if (!partyModel)
|
|
164
171
|
return;
|
|
165
172
|
let cancelled = false;
|
|
166
|
-
api.
|
|
167
|
-
.then((res) => {
|
|
168
|
-
const fields = res?.data?.data?.fields ?? res?.data?.fields ?? [];
|
|
169
|
-
const out = {};
|
|
170
|
-
for (const f of fields)
|
|
171
|
-
if (typeof f?.key === 'string' && typeof f?.label === 'string' && f.label)
|
|
172
|
-
out[f.key] = f.label;
|
|
173
|
+
void loadModelFieldLists(api, partyModel).then((lists) => {
|
|
173
174
|
if (!cancelled)
|
|
174
|
-
|
|
175
|
-
})
|
|
176
|
-
.catch(() => { });
|
|
175
|
+
setPartyFieldLists(lists);
|
|
176
|
+
});
|
|
177
177
|
return () => {
|
|
178
178
|
cancelled = true;
|
|
179
179
|
};
|
|
180
180
|
}, [api, partyModel]);
|
|
181
|
+
// Modelo de catálogo del renglón: alta/edición desde la celda y etiquetas
|
|
182
|
+
// de sus catálogos (unidad «unit» → «Pieza»).
|
|
183
|
+
const catalogModel = productModel ?? 'products.Product';
|
|
184
|
+
// Perezoso: solo cuando ya hay un renglón con producto (no compite con la
|
|
185
|
+
// carga inicial del editor).
|
|
186
|
+
const hasCatalogLine = lines.some((l) => l.kind === 'item' && !!l.product_id);
|
|
187
|
+
const wantsCatalogMeta = !!lineCfg && !isAllocation && hasCatalogLine;
|
|
188
|
+
useEffect(() => {
|
|
189
|
+
if (!wantsCatalogMeta)
|
|
190
|
+
return;
|
|
191
|
+
let cancelled = false;
|
|
192
|
+
void loadModelFieldLists(api, catalogModel).then((lists) => {
|
|
193
|
+
if (!cancelled)
|
|
194
|
+
setCatalogMeta(fieldDisplayMeta(lists, tl));
|
|
195
|
+
});
|
|
196
|
+
return () => {
|
|
197
|
+
cancelled = true;
|
|
198
|
+
};
|
|
199
|
+
}, [api, catalogModel, tl, wantsCatalogMeta]);
|
|
200
|
+
/** Lee el producto guardado con la misma proyección del buscador (catalogRecordToProduct). */
|
|
201
|
+
const loadCatalogProduct = useCallback(async (id, saved) => {
|
|
202
|
+
try {
|
|
203
|
+
const res = await api.get(`/data/${catalogModel}`, { params: { f_id: `eq:${id}`, per_page: 1 } });
|
|
204
|
+
const rows = res?.data?.data;
|
|
205
|
+
const row = Array.isArray(rows) ? rows[0] : null;
|
|
206
|
+
if (row)
|
|
207
|
+
return catalogRecordToProduct({ ...(saved ?? {}), ...row }, taxRate);
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
// Sin lectura, lo que devolvió el guardado.
|
|
211
|
+
}
|
|
212
|
+
return saved && saved.id != null ? catalogRecordToProduct(saved, taxRate) : null;
|
|
213
|
+
}, [api, catalogModel, taxRate]);
|
|
214
|
+
const createProduct = useCallback((query) => new Promise((resolve) => {
|
|
215
|
+
requestRecordCreate({
|
|
216
|
+
model: catalogModel,
|
|
217
|
+
defaults: withSearchPrefill(query, productLabelField),
|
|
218
|
+
onCreated: (rec) => {
|
|
219
|
+
if (rec?.id == null)
|
|
220
|
+
return resolve(null);
|
|
221
|
+
void loadCatalogProduct(String(rec.id), rec).then(resolve);
|
|
222
|
+
},
|
|
223
|
+
});
|
|
224
|
+
}), [catalogModel, productLabelField, loadCatalogProduct]);
|
|
225
|
+
const editProduct = useCallback((line) => new Promise((resolve) => {
|
|
226
|
+
const id = line.catalog?.product_ref ?? line.product_id;
|
|
227
|
+
if (!id)
|
|
228
|
+
return resolve(null);
|
|
229
|
+
requestRecordEdit({
|
|
230
|
+
model: catalogModel,
|
|
231
|
+
recordId: id,
|
|
232
|
+
onSaved: (rec) => void loadCatalogProduct(id, rec && typeof rec === 'object' ? { id, ...rec } : undefined).then(resolve),
|
|
233
|
+
});
|
|
234
|
+
}), [catalogModel, loadCatalogProduct]);
|
|
235
|
+
/** Unidad visible: la opción del catálogo; sin opciones declaradas, el valor tal cual. */
|
|
236
|
+
const unitLabel = useCallback((u) => {
|
|
237
|
+
if (!catalogMeta)
|
|
238
|
+
return undefined;
|
|
239
|
+
const opts = catalogMeta.unit_of_measure?.options ?? catalogMeta.unit?.options;
|
|
240
|
+
if (!opts)
|
|
241
|
+
return u;
|
|
242
|
+
const o = opts.find((x) => String(x.value) === u);
|
|
243
|
+
return typeof o?.label === 'string' && o.label && o.label !== u ? o.label : undefined;
|
|
244
|
+
}, [catalogMeta]);
|
|
181
245
|
// Cobro: documentos abiertos de la contraparte.
|
|
182
246
|
const openCfg = lineCfg?.open_documents;
|
|
183
247
|
const allocPartyId = openCfg ? header[openCfg.party_field] ?? partyId : undefined;
|
|
@@ -483,10 +547,10 @@ export function DocumentEditor({ model, endpoint, forms, type, record, initialSo
|
|
|
483
547
|
};
|
|
484
548
|
const fieldRecord = useMemo(() => seedRecord(seeds, record), [seeds, record]);
|
|
485
549
|
const fieldCell = (field, fullWidth = false, className) => visible(field) ? (_jsxs(FieldCell, { fullWidth: fullWidth, className: className, children: [_jsx(FieldLabel, { htmlFor: field.key, required: field.required, tone: "sentence", children: tl(field.label) }), renderField(withFriendlyOptions(gatedOptions(field, header)), header[field.key], (v) => updateField(field.key, v), header, fieldRecord, fieldErrors), fieldErrors[field.key] && _jsx("p", { className: "mt-1 text-xs text-destructive", children: fieldErrors[field.key] })] }, field.key)) : null;
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
});
|
|
550
|
+
// Etiquetas y catálogos: la metadata de la contraparte y, para las
|
|
551
|
+
// extensiones compartidas (`fiscal_data.uso_cfdi`), los campos del propio documento.
|
|
552
|
+
const summaryMeta = useMemo(() => fieldDisplayMeta([...partyFieldLists, allFields], tl), [partyFieldLists, allFields, tl]);
|
|
553
|
+
const summaryRows = partySummaryRows(party, type.party?.summary, {}, 6, summaryMeta);
|
|
490
554
|
const advancedSummary = groups.advanced
|
|
491
555
|
.filter(visible)
|
|
492
556
|
.map((f) => {
|
|
@@ -546,7 +610,7 @@ export function DocumentEditor({ model, endpoint, forms, type, record, initialSo
|
|
|
546
610
|
const linesSection = lineCfg && (_jsxs(EditorSection, { slot: isAllocation ? 'editor-allocation' : 'editor-lines', title: linesTitle, hint: isAllocation && openBalance > 0 && amountKey ? (_jsx("button", { type: "button", className: "underline-offset-2 hover:underline", onClick: () => updateField(amountKey, openBalance), children: t('documentEditor.pay_all', { defaultValue: 'Cobrar todo ({{amount}})', amount: fmt.money(openBalance) }) })) : undefined, children: [isAllocation ? (allocPartyId ? (_jsx(PaymentAllocator, { documents: openDocs, result: allocation, value: alloc, onChange: setAlloc, currency: currency, loading: docsLoading, today: today })) : (_jsx("p", { className: "text-sm text-muted-foreground", children: t('documentEditor.pick_party_first', { defaultValue: 'Elige el cliente para ver sus documentos con saldo.' }) }))) : (_jsx(DocumentLinesGrid, { value: lines, onChange: (next) => {
|
|
547
611
|
setLines(next);
|
|
548
612
|
setServerIssues([]);
|
|
549
|
-
}, columns: lineCfg.columns ?? ['discount', 'tax'], priceSource: lineCfg.price_source ?? (kind === 'purchase' ? 'cost' : 'sale'), discountMode: lineCfg.discount_mode, mode: linesFromSourceDoc ? 'from_source' : 'free', policy: kind === 'credit' ? { allowZeroQuantity: linesFromSourceDoc } : undefined, search: search, currency: currency, showTotals: false })), !fullscreen && totalsPanel] }));
|
|
613
|
+
}, columns: lineCfg.columns ?? ['discount', 'tax'], priceSource: lineCfg.price_source ?? (kind === 'purchase' ? 'cost' : 'sale'), discountMode: lineCfg.discount_mode, mode: linesFromSourceDoc ? 'from_source' : 'free', policy: kind === 'credit' ? { allowZeroQuantity: linesFromSourceDoc } : undefined, search: search, currency: currency, showTotals: false, onCreateProduct: kind === 'credit' ? undefined : createProduct, onEditProduct: editProduct, unitLabel: unitLabel })), !fullscreen && totalsPanel] }));
|
|
550
614
|
const advanced = (groups.advanced.length > 0 || headerContribs.length > 0) && (_jsxs(CollapsibleSection, { slot: "advanced-options", title: t('documentEditor.advanced', { defaultValue: 'Opciones fiscales' }), summary: advancedSummary || t('documentEditor.advanced_defaults', { defaultValue: 'Valores sugeridos' }), open: advancedOpen, onOpenChange: setAdvancedOpen, children: [groups.advanced.length > 0 && _jsx(FieldGrid, { children: groups.advanced.map((f) => fieldCell(f)) }), headerContribs.map(({ id, component: C }) => (_jsx(C, { ...contribProps }, id)))] }));
|
|
551
615
|
const contributedSections = [...bodyContribs, ...sideContribs].map(({ id, component: C }) => (_jsx("section", { "data-contribution": id, children: _jsx(C, { ...contribProps }) }, id)));
|
|
552
616
|
const notes = groups.notes.length > 0 && _jsx(FieldGrid, { children: groups.notes.map((f) => fieldCell(f, true)) });
|
|
@@ -580,3 +644,38 @@ function SourcePicker({ source, value, seed, header, label, onPick, }) {
|
|
|
580
644
|
}), [source, label]);
|
|
581
645
|
return (_jsx("div", { className: "min-w-60 flex-1", "data-source": source.key, children: renderField(field, value, (v) => onPick(v == null || v === '' ? '' : String(v)), header, seed ? { id: seed.value, label: seed.label } : undefined) }));
|
|
582
646
|
}
|
|
647
|
+
/**
|
|
648
|
+
* Campos y columnas de un modelo para etiquetar sus valores: formulario
|
|
649
|
+
* (`/metadata/modal`, con extensiones) y tabla (`/metadata/table`). Si la
|
|
650
|
+
* clave con módulo (`customers.Customer`) no resuelve en el host, prueba la
|
|
651
|
+
* corta (`Customer`), como el puente de alta del host. Nunca lanza.
|
|
652
|
+
*/
|
|
653
|
+
async function loadModelFieldLists(api, model) {
|
|
654
|
+
const short = model.includes('.') ? model.slice(model.lastIndexOf('.') + 1) : undefined;
|
|
655
|
+
// `undefined` = la petición falló (el host no conoce esa clave); `[]` = respondió sin campos.
|
|
656
|
+
const read = async (url, key) => {
|
|
657
|
+
try {
|
|
658
|
+
const res = await api.get(url);
|
|
659
|
+
const list = res?.data?.data?.[key] ?? res?.data?.[key];
|
|
660
|
+
return Array.isArray(list) ? list : [];
|
|
661
|
+
}
|
|
662
|
+
catch {
|
|
663
|
+
return undefined;
|
|
664
|
+
}
|
|
665
|
+
};
|
|
666
|
+
// En serie y solo lo necesario (una lectura en el caso normal): el
|
|
667
|
+
// formulario; la clave corta solo si la larga falló; la tabla solo si
|
|
668
|
+
// ningún formulario respondió con campos.
|
|
669
|
+
const candidates = short ? [model, short] : [model];
|
|
670
|
+
for (const kind of ['modal', 'table']) {
|
|
671
|
+
for (const m of candidates) {
|
|
672
|
+
const list = await read(`/metadata/${kind}/${m}`, kind === 'modal' ? 'fields' : 'columns');
|
|
673
|
+
if (list === undefined)
|
|
674
|
+
continue;
|
|
675
|
+
if (list.length > 0)
|
|
676
|
+
return [list];
|
|
677
|
+
break;
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
return [];
|
|
681
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type LineItem } from './line-items';
|
|
1
|
+
import { type CatalogLineField, type LineItem } from './line-items';
|
|
2
2
|
import { type ProductResult, type ProductVariant } from './product-search';
|
|
3
3
|
export type PriceSource = 'sale' | 'cost' | 'origin';
|
|
4
4
|
export type DocumentLinesMode = 'free' | 'from_source';
|
|
@@ -10,6 +10,26 @@ export declare function applyProductToLine(line: LineItem, product: ProductResul
|
|
|
10
10
|
warehouseId?: string;
|
|
11
11
|
quantity?: number;
|
|
12
12
|
}): LineItem;
|
|
13
|
+
/**
|
|
14
|
+
* Campos que el usuario cambió a mano respecto de lo que puso el catálogo
|
|
15
|
+
* («dirty» por campo). Sin foto (renglón libre, o cargado de un documento
|
|
16
|
+
* origen con sus propios precios) todo cuenta como capturado: nada se pisa.
|
|
17
|
+
*/
|
|
18
|
+
export declare function lineOverrides(line: LineItem): Set<CatalogLineField>;
|
|
19
|
+
/**
|
|
20
|
+
* El producto del renglón cambió en el catálogo (se editó desde la celda):
|
|
21
|
+
* actualiza SOLO los campos que siguen igual a lo que el catálogo había puesto;
|
|
22
|
+
* lo que el usuario sobrescribió se respeta y el valor nuevo queda en
|
|
23
|
+
* `catalog_pending` para ofrecer «aplicar». Nunca toca la cantidad, el tope de
|
|
24
|
+
* lo pendiente ni el vínculo con el documento origen. Siempre refresca lo que
|
|
25
|
+
* no se captura en el renglón (precio de catálogo, costo, extensiones, existencia).
|
|
26
|
+
*/
|
|
27
|
+
export declare function refreshLineFromProduct(line: LineItem, product: ProductResult, opts?: {
|
|
28
|
+
priceSource?: PriceSource;
|
|
29
|
+
warehouseId?: string;
|
|
30
|
+
}): LineItem;
|
|
31
|
+
/** «Aplicar» el aviso del catálogo: los valores pendientes entran al renglón. */
|
|
32
|
+
export declare function applyCatalogPending(line: LineItem): LineItem;
|
|
13
33
|
/**
|
|
14
34
|
* Agrega el producto como renglón. Por defecto, un segundo clic del mismo
|
|
15
35
|
* producto incrementa la cantidad (como el catálogo de Compras) y respeta `max_quantity`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"document-lines.d.ts","sourceRoot":"","sources":["../../src/business/document-lines.ts"],"names":[],"mappings":"AAGA,OAAO,
|
|
1
|
+
{"version":3,"file":"document-lines.d.ts","sourceRoot":"","sources":["../../src/business/document-lines.ts"],"names":[],"mappings":"AAGA,OAAO,EAAiC,KAAK,gBAAgB,EAA4B,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAA;AAC5H,OAAO,EAAkB,KAAK,aAAa,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAE1F,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAA;AACpD,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,aAAa,CAAA;AAEtD,8DAA8D;AAC9D,wBAAgB,gBAAgB,CAC5B,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,cAAc,GAAG,SAAS,EACnC,MAAM,EAAE,WAAW,GACpB,MAAM,CAKR;AAED,uGAAuG;AACvG,wBAAgB,kBAAkB,CAC9B,IAAI,EAAE,QAAQ,EACd,OAAO,EAAE,aAAa,EACtB,OAAO,CAAC,EAAE,cAAc,EACxB,IAAI,GAAE;IAAE,WAAW,CAAC,EAAE,WAAW,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAClF,QAAQ,CAsBV;AAwBD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,QAAQ,GAAG,GAAG,CAAC,gBAAgB,CAAC,CAInE;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAClC,IAAI,EAAE,QAAQ,EACd,OAAO,EAAE,aAAa,EACtB,IAAI,GAAE;IAAE,WAAW,CAAC,EAAE,WAAW,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/D,QAAQ,CAmBV;AAED,iFAAiF;AACjF,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAI5D;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC1B,KAAK,EAAE,QAAQ,EAAE,EACjB,OAAO,EAAE,aAAa,EACtB,OAAO,CAAC,EAAE,cAAc,EACxB,IAAI,GAAE;IACF,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,gBAAgB,CAAC,EAAE,OAAO,CAAA;CACxB,GACP,QAAQ,EAAE,CAeZ;AAED,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAA;AAEhE,2GAA2G;AAC3G,wBAAgB,kBAAkB,CAC9B,GAAG,EAAE,MAAM,EACX,IAAI,GAAE;IAAE,eAAe,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,iBAAiB,CAAA;CAAO,GACxF,eAAe,CAKjB"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Helpers del editor único de renglones (DocumentLinesGrid / LineItemsEditor).
|
|
2
2
|
// Puros: el componente solo pinta. `serializeLineItems` sigue siendo la puerta al backend.
|
|
3
3
|
import { toAmount } from './format';
|
|
4
|
-
import { makeLine } from './line-items';
|
|
4
|
+
import { CATALOG_LINE_FIELDS, makeLine } from './line-items';
|
|
5
5
|
import { availableStock } from './product-search';
|
|
6
6
|
/** Precio que se escribe en el renglón según el documento. */
|
|
7
7
|
export function priceFromProduct(product, variant, source) {
|
|
@@ -20,22 +20,84 @@ export function applyProductToLine(line, product, variant, opts = {}) {
|
|
|
20
20
|
const catalog = source === 'cost' ? (cost ?? list) : list;
|
|
21
21
|
// Nunca cantidad 0: un renglón vacío (o con la celda borrada) entra con 1.
|
|
22
22
|
const qty = opts.quantity ?? toAmount(line.quantity);
|
|
23
|
+
const values = catalogLineValues(line, product, variant, source);
|
|
24
|
+
const { catalog_pending: _pending, ...rest } = line;
|
|
23
25
|
return {
|
|
24
|
-
...
|
|
26
|
+
...rest,
|
|
25
27
|
kind: 'item',
|
|
26
28
|
product_id: variant?.id ?? product.id,
|
|
27
|
-
|
|
28
|
-
description: variant ? `${product.name} · ${variant.label}` : product.name,
|
|
29
|
+
...values,
|
|
29
30
|
quantity: qty !== 0 ? qty : 1,
|
|
30
|
-
unit_price: priceFromProduct(product, variant, source),
|
|
31
31
|
catalog_price: catalog,
|
|
32
32
|
cost,
|
|
33
|
-
tax_rate: product.tax_rate ?? line.tax_rate ?? 0,
|
|
34
|
-
unit: product.unit ?? line.unit,
|
|
35
33
|
extensions: product.extensions ? { ...(line.extensions ?? {}), ...product.extensions } : line.extensions,
|
|
36
34
|
available: availableStock(src, opts.warehouseId) ?? availableStock(product, opts.warehouseId),
|
|
35
|
+
catalog: { ...values, product_ref: product.id, variant },
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Lo que el producto escribe en los campos editables del renglón. Es EL mapeo
|
|
40
|
+
* producto → renglón: lo usan elegir, crear y editar desde la celda.
|
|
41
|
+
*/
|
|
42
|
+
function catalogLineValues(line, product, variant, source) {
|
|
43
|
+
return {
|
|
44
|
+
description: variant ? `${product.name} · ${variant.label}` : product.name,
|
|
45
|
+
sku: variant?.sku ?? product.sku,
|
|
46
|
+
unit_price: priceFromProduct(product, variant, source),
|
|
47
|
+
tax_rate: product.tax_rate ?? line.tax_rate ?? 0,
|
|
48
|
+
unit: product.unit ?? line.unit,
|
|
37
49
|
};
|
|
38
50
|
}
|
|
51
|
+
const sameValue = (a, b) => typeof a === 'number' || typeof b === 'number' ? toAmount(a) === toAmount(b) : (a ?? '') === (b ?? '');
|
|
52
|
+
/**
|
|
53
|
+
* Campos que el usuario cambió a mano respecto de lo que puso el catálogo
|
|
54
|
+
* («dirty» por campo). Sin foto (renglón libre, o cargado de un documento
|
|
55
|
+
* origen con sus propios precios) todo cuenta como capturado: nada se pisa.
|
|
56
|
+
*/
|
|
57
|
+
export function lineOverrides(line) {
|
|
58
|
+
const snap = line.catalog;
|
|
59
|
+
if (!snap)
|
|
60
|
+
return new Set(CATALOG_LINE_FIELDS);
|
|
61
|
+
return new Set(CATALOG_LINE_FIELDS.filter((f) => !sameValue(line[f], snap[f])));
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* El producto del renglón cambió en el catálogo (se editó desde la celda):
|
|
65
|
+
* actualiza SOLO los campos que siguen igual a lo que el catálogo había puesto;
|
|
66
|
+
* lo que el usuario sobrescribió se respeta y el valor nuevo queda en
|
|
67
|
+
* `catalog_pending` para ofrecer «aplicar». Nunca toca la cantidad, el tope de
|
|
68
|
+
* lo pendiente ni el vínculo con el documento origen. Siempre refresca lo que
|
|
69
|
+
* no se captura en el renglón (precio de catálogo, costo, extensiones, existencia).
|
|
70
|
+
*/
|
|
71
|
+
export function refreshLineFromProduct(line, product, opts = {}) {
|
|
72
|
+
const source = opts.priceSource ?? 'sale';
|
|
73
|
+
const variant = line.catalog?.variant;
|
|
74
|
+
const fresh = applyProductToLine(line, product, variant, { ...opts, quantity: toAmount(line.quantity) });
|
|
75
|
+
const overrides = lineOverrides(line);
|
|
76
|
+
const next = { ...fresh, product_id: line.product_id ?? fresh.product_id, quantity: line.quantity, max_quantity: line.max_quantity, source_line_id: line.source_line_id };
|
|
77
|
+
const pending = {};
|
|
78
|
+
const values = catalogLineValues(line, product, variant, source);
|
|
79
|
+
for (const f of CATALOG_LINE_FIELDS) {
|
|
80
|
+
if (!overrides.has(f))
|
|
81
|
+
continue;
|
|
82
|
+
next[f] = line[f];
|
|
83
|
+
if (!sameValue(values[f], line[f]))
|
|
84
|
+
pending[f] = values[f];
|
|
85
|
+
}
|
|
86
|
+
// La foto avanza a los valores nuevos del catálogo: el override sigue siéndolo.
|
|
87
|
+
next.catalog = { ...values, product_ref: line.catalog?.product_ref ?? product.id, variant };
|
|
88
|
+
if (Object.keys(pending).length > 0)
|
|
89
|
+
next.catalog_pending = pending;
|
|
90
|
+
else
|
|
91
|
+
delete next.catalog_pending;
|
|
92
|
+
return next;
|
|
93
|
+
}
|
|
94
|
+
/** «Aplicar» el aviso del catálogo: los valores pendientes entran al renglón. */
|
|
95
|
+
export function applyCatalogPending(line) {
|
|
96
|
+
if (!line.catalog_pending)
|
|
97
|
+
return line;
|
|
98
|
+
const { catalog_pending: pending, ...rest } = line;
|
|
99
|
+
return { ...rest, ...pending };
|
|
100
|
+
}
|
|
39
101
|
/**
|
|
40
102
|
* Agrega el producto como renglón. Por defecto, un segundo clic del mismo
|
|
41
103
|
* producto incrementa la cantidad (como el catálogo de Compras) y respeta `max_quantity`.
|
package/dist/business/index.d.ts
CHANGED
|
@@ -22,6 +22,7 @@ export * from './vehicle-picker';
|
|
|
22
22
|
export * from './relate-documents';
|
|
23
23
|
export * from './print-send-dialog';
|
|
24
24
|
export * from './catalog-product-search';
|
|
25
|
+
export * from './product-display';
|
|
25
26
|
export * from './document-editor-model';
|
|
26
27
|
export * from './document-editor-panels';
|
|
27
28
|
export * from './payment-allocator';
|
|
@@ -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,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,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"}
|
|
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,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,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,mBAAmB,CAAA;AACjC,cAAc,yBAAyB,CAAA;AACvC,cAAc,0BAA0B,CAAA;AACxC,cAAc,qBAAqB,CAAA;AACnC,cAAc,mBAAmB,CAAA"}
|
package/dist/business/index.js
CHANGED
|
@@ -22,6 +22,7 @@ export * from './vehicle-picker';
|
|
|
22
22
|
export * from './relate-documents';
|
|
23
23
|
export * from './print-send-dialog';
|
|
24
24
|
export * from './catalog-product-search';
|
|
25
|
+
export * from './product-display';
|
|
25
26
|
export * from './document-editor-model';
|
|
26
27
|
export * from './document-editor-panels';
|
|
27
28
|
export * from './payment-allocator';
|
|
@@ -45,10 +45,30 @@ export interface DocumentLinesGridProps {
|
|
|
45
45
|
* ya muestra sus propios totales (DocumentEditor) lo apaga.
|
|
46
46
|
*/
|
|
47
47
|
showTotals?: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Alta del producto desde la celda («+» y «Crear producto «texto»»). Resuelve
|
|
50
|
+
* con el producto guardado (o nada si se canceló): el renglón se llena con
|
|
51
|
+
* el mismo mapeo que al elegir uno existente.
|
|
52
|
+
*/
|
|
53
|
+
onCreateProduct?: (query: string) => Promise<ProductResult | null | undefined>;
|
|
54
|
+
/**
|
|
55
|
+
* Edición del producto del renglón (lápiz en la celda). Resuelve con el
|
|
56
|
+
* producto ya guardado: el renglón se actualiza salvo los campos que el
|
|
57
|
+
* usuario sobrescribió (ver `refreshLineFromProduct`).
|
|
58
|
+
*/
|
|
59
|
+
onEditProduct?: (line: LineItem) => Promise<ProductResult | null | undefined>;
|
|
60
|
+
/** Nombre del modelo de catálogo para «Crear …» / «Editar …» (default «producto»). */
|
|
61
|
+
productLabel?: string;
|
|
62
|
+
/**
|
|
63
|
+
* Etiqueta visible de la unidad (`unit` → «pza»). Si devuelve vacío, la
|
|
64
|
+
* unidad no se muestra bajo el SKU (nunca la clave cruda). Sin esta prop se
|
|
65
|
+
* muestra el valor tal cual.
|
|
66
|
+
*/
|
|
67
|
+
unitLabel?: (unit: string) => string | undefined;
|
|
48
68
|
}
|
|
49
69
|
/** @deprecated Usa `DocumentLinesGridProps`. Es el mismo contrato. */
|
|
50
70
|
export type LineItemsEditorProps = DocumentLinesGridProps;
|
|
51
|
-
export declare function DocumentLinesGrid({ value, onChange, columns, policy, serverErrors, onValidate, onRequestProduct, search, priceSource, mode, discountMode, quantityStepper, mergeSameProduct, warehouseId, allowSections, readOnly, editPermission, currency, showTotals, }: DocumentLinesGridProps): import("react").JSX.Element;
|
|
71
|
+
export declare function DocumentLinesGrid({ value, onChange, columns, policy, serverErrors, onValidate, onRequestProduct, search, priceSource, mode, discountMode, quantityStepper, mergeSameProduct, warehouseId, allowSections, readOnly, editPermission, currency, showTotals, onCreateProduct, onEditProduct, productLabel, unitLabel, }: DocumentLinesGridProps): import("react").JSX.Element;
|
|
52
72
|
/** Mismo componente. El nombre anterior sigue exportado. */
|
|
53
73
|
export declare const LineItemsEditor: typeof DocumentLinesGrid;
|
|
54
74
|
//# sourceMappingURL=line-items-editor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"line-items-editor.d.ts","sourceRoot":"","sources":["../../src/business/line-items-editor.tsx"],"names":[],"mappings":"AASA,OAAO,
|
|
1
|
+
{"version":3,"file":"line-items-editor.d.ts","sourceRoot":"","sources":["../../src/business/line-items-editor.tsx"],"names":[],"mappings":"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"}
|