Agrega verificación de stock para ventas de kits múltiples
- Nueva tool verificar_stock_kit() para calcular cuántos kits se pueden armar - Nueva función db_verificar_stock_kit() que verifica stock de todos los productos - Calcula kits_posibles basado en el producto con menor stock relativo - Actualiza skill armar_kits.md con proceso de verificación obligatoria - Ahora advierte antes de vender: 'Solo podés armar X kits, pediste Y' - Prevents ventas parciales no deseadas de kits
This commit is contained in:
@@ -329,6 +329,89 @@ def db_confirmar_venta_kit(items: list) -> dict:
|
||||
}
|
||||
|
||||
|
||||
def db_verificar_stock_kit(items: list, cantidad_kits: int) -> dict:
|
||||
"""Verifica si hay stock suficiente para armar N kits completos"""
|
||||
conn = sqlite3.connect(DB_PATH)
|
||||
conn.row_factory = sqlite3.Row
|
||||
cursor = conn.cursor()
|
||||
|
||||
productos_info = []
|
||||
kits_posibles = float("inf")
|
||||
faltantes = []
|
||||
|
||||
for item in items:
|
||||
producto_nombre = item.get("producto_nombre", "")
|
||||
cantidad_por_kit = item.get("cantidad", 1)
|
||||
|
||||
query_normalized = normalize_text(producto_nombre.lower())
|
||||
search_term = f"%{query_normalized}%"
|
||||
|
||||
cursor.execute(
|
||||
"""
|
||||
SELECT nombre, stock FROM productos
|
||||
WHERE activo = 1 AND (
|
||||
REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(LOWER(nombre), 'á', 'a'), 'é', 'e'), 'í', 'i'), 'ó', 'o'), 'ú', 'u') LIKE ?
|
||||
)
|
||||
LIMIT 1
|
||||
""",
|
||||
(search_term,),
|
||||
)
|
||||
|
||||
producto = cursor.fetchone()
|
||||
|
||||
if not producto:
|
||||
faltantes.append(f"Producto no encontrado: {producto_nombre}")
|
||||
continue
|
||||
|
||||
stock_disponible = producto["stock"]
|
||||
kits_con_este_producto = stock_disponible // cantidad_por_kit
|
||||
|
||||
productos_info.append(
|
||||
{
|
||||
"nombre": producto["nombre"],
|
||||
"stock": stock_disponible,
|
||||
"cantidad_por_kit": cantidad_por_kit,
|
||||
"kits_posibles": kits_con_este_producto,
|
||||
}
|
||||
)
|
||||
|
||||
# El límite es el producto con menos kits posibles
|
||||
if kits_con_este_producto < kits_posibles:
|
||||
kits_posibles = kits_con_este_producto
|
||||
|
||||
conn.close()
|
||||
|
||||
# Si no hay productos válidos
|
||||
if not productos_info:
|
||||
return {
|
||||
"puede_vender": False,
|
||||
"kits_solicitados": cantidad_kits,
|
||||
"kits_posibles": 0,
|
||||
"mensaje": "No se encontraron los productos del kit",
|
||||
"detalles": faltantes,
|
||||
}
|
||||
|
||||
# Si puede vender todos los kits solicitados
|
||||
if kits_posibles >= cantidad_kits:
|
||||
return {
|
||||
"puede_vender": True,
|
||||
"kits_solicitados": cantidad_kits,
|
||||
"kits_posibles": cantidad_kits,
|
||||
"mensaje": f"✅ Stock suficiente para {cantidad_kits} kits",
|
||||
"productos": productos_info,
|
||||
}
|
||||
|
||||
# Si no alcanza el stock
|
||||
return {
|
||||
"puede_vender": False,
|
||||
"kits_solicitados": cantidad_kits,
|
||||
"kits_posibles": kits_posibles,
|
||||
"mensaje": f"⚠️ Solo podés armar {kits_posibles} kits completos (pediste {cantidad_kits})",
|
||||
"productos": productos_info,
|
||||
"sugerencia": f"Con el stock actual solo alcanza para {kits_posibles} kits. ¿Vendés {kits_posibles} o preferís ver otros productos?",
|
||||
}
|
||||
|
||||
|
||||
async def chat_with_ai(message: str, session_id: str = "pymesbot") -> Optional[str]:
|
||||
"""Send message to Anthropic API with tools"""
|
||||
|
||||
@@ -402,6 +485,38 @@ async def chat_with_ai(message: str, session_id: str = "pymesbot") -> Optional[s
|
||||
"required": ["items"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "verificar_stock_kit",
|
||||
"description": "Verifica si hay stock suficiente para armar N kits completos ANTES de vender. Usar SIEMPRE cuando el usuario quiera vender múltiples kits para calcular cuántos se pueden armar con el stock actual.",
|
||||
"input_schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"items": {
|
||||
"type": "array",
|
||||
"description": "Lista de productos que componen un kit",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"producto_nombre": {
|
||||
"type": "string",
|
||||
"description": "Nombre del producto",
|
||||
},
|
||||
"cantidad": {
|
||||
"type": "integer",
|
||||
"description": "Cantidad que lleva el kit de este producto",
|
||||
},
|
||||
},
|
||||
"required": ["producto_nombre", "cantidad"],
|
||||
},
|
||||
},
|
||||
"cantidad_kits": {
|
||||
"type": "integer",
|
||||
"description": "Cantidad de kits que quiere vender",
|
||||
},
|
||||
},
|
||||
"required": ["items", "cantidad_kits"],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
messages = [{"role": "user", "content": message}]
|
||||
@@ -497,6 +612,17 @@ async def chat_with_ai(message: str, session_id: str = "pymesbot") -> Optional[s
|
||||
"content": json.dumps(resultado),
|
||||
}
|
||||
)
|
||||
elif tool_name == "verificar_stock_kit":
|
||||
items = tool_input.get("items", [])
|
||||
cantidad_kits = tool_input.get("cantidad_kits", 1)
|
||||
resultado = db_verificar_stock_kit(items, cantidad_kits)
|
||||
tool_results.append(
|
||||
{
|
||||
"type": "tool_result",
|
||||
"tool_use_id": tool_call.get("id"),
|
||||
"content": json.dumps(resultado),
|
||||
}
|
||||
)
|
||||
|
||||
# Agregar el tool use y los resultados a los mensajes
|
||||
messages.append({"role": "assistant", "content": json.dumps(content)})
|
||||
|
||||
@@ -37,11 +37,39 @@ Formato de presentación:
|
||||
|
||||
## Venta de Kits
|
||||
|
||||
### VERIFICACIÓN CRÍTICA - Antes de Vender Múltiples Kits
|
||||
|
||||
**SIEMPRE** verificar stock antes de confirmar venta de múltiples kits.
|
||||
|
||||
**Proceso:**
|
||||
1. Usar `verificar_stock_kit` con:
|
||||
- `items`: Lista de productos del kit
|
||||
- `cantidad_kits`: Cuántos kits quiere vender
|
||||
2. Si `puede_vender: true` → Proceder con `confirmar_venta_kit`
|
||||
3. Si `puede_vender: false` → Informar límite y preguntar si vende esa cantidad
|
||||
|
||||
**Ejemplo:**
|
||||
Usuario: "Se vendieron 10 kits"
|
||||
Bot: [USAR verificar_stock_kit(items=[...], cantidad_kits=10)]
|
||||
|
||||
Si alcanza:
|
||||
"✅ Tenés stock para 10 kits. ¿Confirmamos la venta?"
|
||||
|
||||
Si no alcanza (solo hay para 7):
|
||||
"⚠️ Solo podés armar 7 kits completos con el stock actual.
|
||||
¿Vendemos 7 kits o preferís ver otros productos?"
|
||||
|
||||
### Confirmación de Venta de Kit
|
||||
Cuando el usuario diga "se vendió el kit", "concretamos", "dale, lo lleva", etc:
|
||||
|
||||
**Si es UN solo kit:**
|
||||
**Acción:** Usar `confirmar_venta_kit` con TODOS los productos del kit.
|
||||
|
||||
**Si son MÚLTIPLES kits:**
|
||||
**Acción:**
|
||||
1. PRIMERO `verificar_stock_kit` para verificar cuántos se pueden armar
|
||||
2. LUEGO `confirmar_venta_kit` SOLO si hay stock suficiente
|
||||
|
||||
**Ejemplo:**
|
||||
Usuario: "Se vendió el kit de 15mil"
|
||||
Bot: [USAR confirmar_venta_kit con items=[
|
||||
|
||||
Reference in New Issue
Block a user