@asteby/metacore-runtime-react 46.2.3 → 46.4.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 +12 -0
- package/dist/business/catalog.d.ts.map +1 -1
- package/dist/business/catalog.js +16 -4
- package/dist/business/document-lines.d.ts +30 -0
- package/dist/business/document-lines.d.ts.map +1 -0
- package/dist/business/document-lines.js +65 -0
- 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 +28 -4
- package/dist/business/line-items-editor.d.ts.map +1 -1
- package/dist/business/line-items-editor.js +139 -14
- package/dist/business/line-items.d.ts +24 -2
- package/dist/business/line-items.d.ts.map +1 -1
- package/dist/business/line-items.js +50 -5
- package/dist/business/product-search.d.ts +4 -0
- package/dist/business/product-search.d.ts.map +1 -1
- package/dist/business/product-search.js +5 -1
- package/dist/dynamic-crud-page.d.ts.map +1 -1
- package/dist/dynamic-crud-page.js +14 -6
- 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 +61 -0
- package/dist/dynamic-line-items.d.ts.map +1 -1
- package/dist/dynamic-line-items.js +18 -8
- package/dist/dynamic-select-field.d.ts +3 -1
- package/dist/dynamic-select-field.d.ts.map +1 -1
- package/dist/dynamic-select-field.js +2 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/list-primary-action.d.ts +31 -0
- package/dist/list-primary-action.d.ts.map +1 -0
- package/dist/list-primary-action.js +35 -0
- package/dist/model-action-toolbar.d.ts +7 -1
- package/dist/model-action-toolbar.d.ts.map +1 -1
- package/dist/model-action-toolbar.js +10 -3
- package/dist/model-extension-registry.d.ts +7 -0
- package/dist/model-extension-registry.d.ts.map +1 -1
- package/dist/types.d.ts +14 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/use-options-resolver.d.ts +5 -5
- package/dist/use-options-resolver.d.ts.map +1 -1
- package/dist/use-options-resolver.js +11 -0
- package/package.json +1 -1
- package/src/__tests__/document-lines-grid.test.tsx +79 -0
- package/src/__tests__/line-item-formulas.test.ts +18 -1
- package/src/__tests__/list-primary-action.test.tsx +157 -0
- package/src/__tests__/use-options-resolver.test.ts +5 -0
- package/src/business/business.test.ts +43 -0
- package/src/business/catalog.ts +16 -4
- package/src/business/document-lines.ts +91 -0
- package/src/business/index.ts +1 -0
- package/src/business/line-items-editor.tsx +365 -46
- package/src/business/line-items.ts +65 -7
- package/src/business/product-search.ts +9 -1
- package/src/dynamic-crud-page.tsx +15 -5
- package/src/dynamic-form-schema.ts +60 -0
- package/src/dynamic-line-items.tsx +23 -3
- package/src/dynamic-select-field.tsx +4 -0
- package/src/index.ts +8 -0
- package/src/list-primary-action.ts +71 -0
- package/src/model-action-toolbar.tsx +18 -3
- package/src/model-extension-registry.tsx +7 -0
- package/src/types.ts +14 -0
- package/src/use-options-resolver.ts +15 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// Helpers del editor único de renglones (DocumentLinesGrid / LineItemsEditor).
|
|
2
|
+
// Puros: el componente solo pinta. `serializeLineItems` sigue siendo la puerta al backend.
|
|
3
|
+
import { toAmount } from './format'
|
|
4
|
+
import { makeLine, type LineItem } from './line-items'
|
|
5
|
+
import { availableStock, type ProductResult, type ProductVariant } from './product-search'
|
|
6
|
+
|
|
7
|
+
export type PriceSource = 'sale' | 'cost' | 'origin'
|
|
8
|
+
export type DocumentLinesMode = 'free' | 'from_source'
|
|
9
|
+
|
|
10
|
+
/** Precio que se escribe en el renglón según el documento. */
|
|
11
|
+
export function priceFromProduct(
|
|
12
|
+
product: ProductResult,
|
|
13
|
+
variant: ProductVariant | undefined,
|
|
14
|
+
source: PriceSource,
|
|
15
|
+
): number {
|
|
16
|
+
const list = variant?.price ?? product.price
|
|
17
|
+
const cost = variant?.cost ?? product.cost
|
|
18
|
+
if (source === 'cost') return cost ?? list ?? 0
|
|
19
|
+
return list ?? 0
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Rellena un renglón con el producto elegido (nombre, SKU, precio, costo de catálogo, existencia). */
|
|
23
|
+
export function applyProductToLine(
|
|
24
|
+
line: LineItem,
|
|
25
|
+
product: ProductResult,
|
|
26
|
+
variant?: ProductVariant,
|
|
27
|
+
opts: { priceSource?: PriceSource; warehouseId?: string; quantity?: number } = {},
|
|
28
|
+
): LineItem {
|
|
29
|
+
const source = opts.priceSource ?? 'sale'
|
|
30
|
+
const src = variant ?? product
|
|
31
|
+
const list = variant?.price ?? product.price
|
|
32
|
+
const cost = variant?.cost ?? product.cost
|
|
33
|
+
const catalog = source === 'cost' ? (cost ?? list) : list
|
|
34
|
+
return {
|
|
35
|
+
...line,
|
|
36
|
+
kind: 'item',
|
|
37
|
+
product_id: variant?.id ?? product.id,
|
|
38
|
+
sku: variant?.sku ?? product.sku,
|
|
39
|
+
description: variant ? `${product.name} · ${variant.label}` : product.name,
|
|
40
|
+
quantity: opts.quantity ?? (toAmount(line.quantity) || 1),
|
|
41
|
+
unit_price: priceFromProduct(product, variant, source),
|
|
42
|
+
catalog_price: catalog,
|
|
43
|
+
cost,
|
|
44
|
+
tax_rate: product.tax_rate ?? line.tax_rate ?? 0,
|
|
45
|
+
available: availableStock(src, opts.warehouseId) ?? availableStock(product, opts.warehouseId),
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Agrega el producto como renglón. Por defecto, un segundo clic del mismo
|
|
51
|
+
* producto incrementa la cantidad (como el catálogo de Compras) y respeta `max_quantity`.
|
|
52
|
+
*/
|
|
53
|
+
export function addProductLine(
|
|
54
|
+
lines: LineItem[],
|
|
55
|
+
product: ProductResult,
|
|
56
|
+
variant?: ProductVariant,
|
|
57
|
+
opts: {
|
|
58
|
+
priceSource?: PriceSource
|
|
59
|
+
warehouseId?: string
|
|
60
|
+
quantity?: number
|
|
61
|
+
mergeSameProduct?: boolean
|
|
62
|
+
} = {},
|
|
63
|
+
): LineItem[] {
|
|
64
|
+
const id = variant?.id ?? product.id
|
|
65
|
+
const addQty = opts.quantity ?? 1
|
|
66
|
+
if (opts.mergeSameProduct !== false) {
|
|
67
|
+
const idx = lines.findIndex((l) => l.kind === 'item' && l.product_id === id)
|
|
68
|
+
if (idx >= 0) {
|
|
69
|
+
return lines.map((l, i) => {
|
|
70
|
+
if (i !== idx) return l
|
|
71
|
+
const next = toAmount(l.quantity) + addQty
|
|
72
|
+
const capped = l.max_quantity != null ? Math.min(next, toAmount(l.max_quantity)) : next
|
|
73
|
+
return { ...l, quantity: capped }
|
|
74
|
+
})
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return [...lines, applyProductToLine(makeLine(), product, variant, { ...opts, quantity: addQty })]
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export type LineGridCommand = 'add' | 'next' | 'delete' | 'none'
|
|
81
|
+
|
|
82
|
+
/** Enter agrega, Tab avanza, Supr/Backspace en celda vacía borra. No actúa si hay sugerencias abiertas. */
|
|
83
|
+
export function lineGridKeyCommand(
|
|
84
|
+
key: string,
|
|
85
|
+
opts: { suggestionsOpen?: boolean; cellEmpty?: boolean; mode?: DocumentLinesMode } = {},
|
|
86
|
+
): LineGridCommand {
|
|
87
|
+
if (key === 'Tab') return 'next'
|
|
88
|
+
if (key === 'Enter' && !opts.suggestionsOpen && opts.mode !== 'from_source') return 'add'
|
|
89
|
+
if ((key === 'Delete' || key === 'Backspace') && opts.cellEmpty && opts.mode !== 'from_source') return 'delete'
|
|
90
|
+
return 'none'
|
|
91
|
+
}
|
package/src/business/index.ts
CHANGED