Productos: allowed_order_units + fix sync que pisaba overrides
Introduce un campo nuevo allowed_order_units por producto (array kg/unit) que separa "cómo se vende" de "cómo se puede pedir". Productos sell_unit=unit solo aceptan unit (regla dura aplicada por código y handler). Productos sell_unit=kg defaultean a ambos, editable desde la UI con checkboxes. Fixea bug crítico de wooSnapshot.upsertSnapshotItems que pisaba raw entero en cada sync, perdiendo overrides locales (_sell_unit_override, _categories_override y el nuevo _allowed_order_units). El UPDATE ahora mergea preservando los overrides. Las tools del agente (addToCart, setQuantity, selectCandidate) validan unit contra allowed_order_units y devuelven unit_not_allowed para que el LLM re-pregunte. workingMemory expone allowed_order_units y needs_unit_choice. buildLineItems agrega meta_data unit/sell_unit_product/unit_mode_mismatch y omite subtotal/total cuando hay mismatch para que Woo recalcule. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -34,28 +34,31 @@ export function createEmptyOrder() {
|
||||
/**
|
||||
* Crea un item de carrito confirmado
|
||||
*/
|
||||
export function createCartItem({ woo_id, qty, unit, name = null, price = null }) {
|
||||
export function createCartItem({ woo_id, qty, unit, name = null, price = null, allowed_order_units = null }) {
|
||||
return {
|
||||
woo_id,
|
||||
qty: Number(qty) || 1,
|
||||
unit: unit || "unit", // "kg" | "g" | "unit"
|
||||
name,
|
||||
price,
|
||||
allowed_order_units,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Crea un item pendiente de clarificación
|
||||
*/
|
||||
export function createPendingItem({
|
||||
export function createPendingItem({
|
||||
id,
|
||||
query,
|
||||
candidates = [],
|
||||
query,
|
||||
candidates = [],
|
||||
selected_woo_id = null,
|
||||
selected_name = null,
|
||||
selected_price = null,
|
||||
selected_unit = null,
|
||||
qty = null,
|
||||
selected_allowed_order_units = null,
|
||||
needs_unit_choice = false,
|
||||
qty = null,
|
||||
unit = null,
|
||||
status = PendingStatus.NEEDS_TYPE,
|
||||
requested_qty = null,
|
||||
@@ -64,16 +67,18 @@ export function createPendingItem({
|
||||
return {
|
||||
id: id || `pending_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,
|
||||
query,
|
||||
candidates, // [{ woo_id, name, price, display_unit }]
|
||||
selected_woo_id, // Producto elegido (null si NEEDS_TYPE)
|
||||
candidates, // [{ woo_id, name, price, display_unit, allowed_order_units }]
|
||||
selected_woo_id, // Producto elegido (null si NEEDS_TYPE)
|
||||
selected_name,
|
||||
selected_price,
|
||||
selected_unit, // Unidad del producto seleccionado
|
||||
qty, // Cantidad (null si NEEDS_QUANTITY)
|
||||
unit, // Unidad elegida por usuario
|
||||
selected_unit, // Unidad del producto seleccionado
|
||||
selected_allowed_order_units, // Unidades válidas para este producto (cache)
|
||||
needs_unit_choice, // Si true, el LLM tiene que preguntar la unidad antes de cerrar
|
||||
qty, // Cantidad (null si NEEDS_QUANTITY)
|
||||
unit, // Unidad elegida por usuario
|
||||
status,
|
||||
requested_qty, // Cantidad pedida originalmente por el usuario (para usar después de selección)
|
||||
requested_unit, // Unidad pedida originalmente por el usuario
|
||||
requested_qty, // Cantidad pedida originalmente por el usuario (para usar después de selección)
|
||||
requested_unit, // Unidad pedida originalmente por el usuario
|
||||
};
|
||||
}
|
||||
|
||||
@@ -96,6 +101,7 @@ export function moveReadyToCart(order) {
|
||||
unit: item.unit || item.selected_unit || "unit",
|
||||
name: item.selected_name,
|
||||
price: item.selected_price,
|
||||
allowed_order_units: item.selected_allowed_order_units || null,
|
||||
});
|
||||
|
||||
if (existingIdx >= 0) {
|
||||
|
||||
Reference in New Issue
Block a user