Mejoras de sesion: estabilizacion, IA, Nexus Yonke y marketplace B2B
- 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:
@@ -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 ────────────────────────────────────
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user