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

@@ -20,6 +20,7 @@ from services.cfdi_facturapi_builder import (
from services.cfdi_queue import (
cancel_cfdi,
enqueue_cfdi,
enqueue_pending_complements,
get_queue_status,
process_queue,
retry_failed,
@@ -62,7 +63,7 @@ def _get_issuer_config(cur, branch_id=None):
if branch_id:
cur.execute(
"""
SELECT rfc, razon_social, regimen_fiscal, codigo_postal, serie_cfdi
SELECT rfc, razon_social, regimen_fiscal, cp, serie_cfdi
FROM branches WHERE id = %s
""",
(branch_id,),
@@ -84,7 +85,8 @@ def _get_sale_with_items(cur, sale_id):
"""
SELECT id, branch_id, customer_id, employee_id, sale_type,
payment_method, subtotal, discount_total, tax_total, total,
metodo_pago_sat, forma_pago_sat, status, created_at
metodo_pago_sat, forma_pago_sat, status, created_at,
currency, exchange_rate
FROM sales WHERE id = %s
""",
(sale_id,),
@@ -108,6 +110,8 @@ def _get_sale_with_items(cur, sale_id):
"forma_pago_sat": row[11] or "01",
"status": row[12],
"created_at": str(row[13]),
"currency": row[14] or "MXN",
"exchange_rate": float(row[15]) if row[15] else None,
}
cur.execute(
@@ -366,6 +370,44 @@ def trigger_process_queue():
return jsonify({"error": str(e)}), 500
@invoicing_bp.route("/complementos/sync", methods=["POST"])
@require_auth("invoicing.create")
def sync_complementos():
"""Enqueue the missing payment complements (REP) and credit notes (egreso).
Payments on stamped PPD invoices become CFDI type "P" linked to the
original UUID; returns of stamped sales become CFDI type "E". Already
enqueued movements are not duplicated.
Body: {
backfill: bool (default false) — reconcile the whole history,
since: ISO date (optional) — reconcile movements created after it
}
"""
data = request.get_json() or {}
backfill = bool(data.get("backfill"))
since = data.get("since")
if since:
try:
datetime.fromisoformat(str(since))
except ValueError:
return jsonify({"error": "since must be an ISO 8601 date/datetime"}), 400
conn = get_tenant_conn(g.tenant_id)
try:
result = enqueue_pending_complements(conn, since=since, backfill=backfill)
conn.close()
result["enqueued"] = len(result["pagos"]) + len(result["egresos"])
return jsonify(result), 201
except Exception as e:
conn.rollback()
conn.close()
return jsonify({"error": str(e)}), 500
# ─── Cancel CFDI ────────────────────────────────────