Mejoras de sesion: estabilizacion, IA, Nexus Yonke y marketplace B2B
Some checks failed
CI / lint-and-test (3.11) (push) Has been cancelled
CI / lint-and-test (3.13) (push) Has been cancelled

- F0 blindaje: Redis/Celery, pg_hba sin trust LAN, secretos a env 600, backups, webhook auth, jobs muertos
- F1 caja: bugs POS, reembolsos al corte, apartados, CFDI, topes de descuento en cotizacion/apartado
- F2/F7 IA de catalogo: autocategorizacion, dedup de SKUs con embeddings, OCR de facturas, descripciones, claves SAT, limpieza de fitment
- F3 IA en el flujo: vision Yonke, preguntas MeLi, venta cruzada, anomalias, sinonimos, busqueda semantica (rerank/embeddings)
- F4/F8 escala y cartera: /metrics+Prometheus+Grafana, pool, score de credito, churn, metricas multi-tenant
- Nexus Yonke (M1-M6): modelo de datos 1-de-1, alta por donador, vitrina publica, MeLi usado, consignacion, garantia por dias, reportes, etiquetas
- Marketplace B2B entre yonkes (catalogo + pedidos cross-tenant)
- Seguridad: auth en /api/admin/* (35 endpoints), alertas por tenant
- Migraciones v4.27/v4.28; timers expire-demos y rollup-metrics
This commit is contained in:
2026-10-12 00:57:31 +00:00
parent f2d4558b80
commit a386ca5b4a
165 changed files with 31313 additions and 2203 deletions

View File

@@ -193,40 +193,59 @@ def reset_tenant(tenant_id, keep_config=True):
db_name = tenant["db_name"]
dsn = TENANT_DB_URL_TEMPLATE.format(db_name=db_name)
tables_to_truncate = [
"inventory_operations",
"inventory",
"sale_items",
"sales",
"customer_payments",
"cash_register_closings",
"cash_register_movements",
"cash_registers",
"invoices",
"accounting_entries",
"journal_entries",
"service_orders",
"fleet_vehicles",
"crm_activities",
"quotations",
"quotation_items",
"savings_transactions",
"savings_accounts",
"supplier_orders",
"supplier_order_items",
"warranty_claims",
"notifications",
"inventory_uploads",
# Whitelist de tablas de NEGOCIO/PII a limpiar. Antes faltaban customers,
# whatsapp/wa_*, audit_log, layaways, returns, marketplace_*, consignaciones
# → el "reset" dejaba datos personales e historial de conversaciones.
candidate_tables = [
# Inventario
"inventory_operations", "inventory_stock", "inventory_stock_summary",
"inventory_images", "inventory_sku_aliases", "inventory_vehicle_compat",
"inventory_transfer_lines", "inventory_transfers", "physical_count_lines",
"physical_counts", "reorder_alerts", "inventory", "inventory_uploads",
# Ventas / caja
"sale_payments", "sale_items", "sales", "customer_payments",
"cash_movements", "cash_register_movements", "cash_registers",
"layaway_payments", "layaway_items", "layaways",
# Devoluciones / garantías
"return_items", "returns", "warranty_claims", "warranties",
# Cotizaciones / compras
"quotation_items", "quotations",
"purchase_order_items", "purchase_orders",
# Taller / flotilla
"service_order_items", "service_order_labor", "service_orders",
"fleet_maintenance_logs", "fleet_vehicles",
# CRM / clientes (PII)
"customer_activities", "crm_activities", "loyalty_transactions",
"loyalty_points", "customers",
# Marketplace / MeLi
"marketplace_order_items", "marketplace_orders", "marketplace_listings",
"marketplace_questions", "meli_sync_queue",
# WhatsApp (PII)
"whatsapp_messages", "whatsapp_sessions", "wa_customer_links",
"wa_learning_sessions",
# Contabilidad / fiscal
"cfdi_queue", "invoices", "journal_lines", "journal_entries",
# Auditoría / sesiones
"audit_log", "employee_sessions", "notifications",
# Consignación (Yonke)
"consignment_items", "consignments",
]
conn = psycopg2.connect(dsn)
cur = conn.cursor()
try:
for table in tables_to_truncate:
# Solo se truncan las que existan en este tenant (esquema puede variar).
cur.execute("SELECT tablename FROM pg_tables WHERE schemaname = 'public'")
existing = {r[0] for r in cur.fetchall()}
truncated = 0
for table in candidate_tables:
if table not in existing:
continue
try:
cur.execute(f"TRUNCATE TABLE {table} RESTART IDENTITY CASCADE")
cur.execute(f'TRUNCATE TABLE public."{table}" RESTART IDENTITY CASCADE')
truncated += 1
except Exception:
pass # Table may not exist
conn.rollback()
conn.commit()
success = True
except Exception as e:
@@ -237,7 +256,7 @@ def reset_tenant(tenant_id, keep_config=True):
cur.close()
conn.close()
return {"success": success, "tenant_id": tenant_id, "tables_reset": len(tables_to_truncate)}
return {"success": success, "tenant_id": tenant_id, "tables_reset": truncated}
def delete_tenant(tenant_id):