fix(audit): corrige errores criticos y mayores, mejora UX/accesibilidad y optimiza rendimiento
- Arregla @require_auth, permisos, race conditions, locks de caja/stock - Elimina N+1 en layaway, flotilla, dashboard y global_invoice - Asegura folios atomicos para CFDI, ordenes de servicio y polizas - Protege client_secret de MercadoLibre en backend - Conecta botones/filtros de config, customers, accounting e invoicing - Mejora accesibilidad (labels/aria-label) y estados de carga/vacio - Limpia accounting.js obsoleto y consolida accounting.v9.js - Actualiza cache busting a v32 y Service Worker a v32 - Documenta todo en docs/AUDIT_Y_MEJORAS_2026-06-15.md Tests: 35 passed
This commit is contained in:
@@ -30,10 +30,24 @@ def list_customers():
|
||||
per_page = min(int(request.args.get('per_page', 50)), 200)
|
||||
search = request.args.get('q', '').strip()
|
||||
branch_id = request.args.get('branch_id')
|
||||
price_tier = request.args.get('price_tier', '').strip()
|
||||
status = request.args.get('status', '').strip().lower()
|
||||
|
||||
where_clauses = ["c.is_active = true"]
|
||||
where_clauses = []
|
||||
params = []
|
||||
|
||||
if status == 'inactive':
|
||||
where_clauses.append("c.is_active = false")
|
||||
elif status == 'overdue':
|
||||
where_clauses.append(
|
||||
"c.is_active = true AND c.credit_limit > 0 AND c.credit_balance > c.credit_limit"
|
||||
)
|
||||
elif status == 'all':
|
||||
pass # no is_active filter
|
||||
else:
|
||||
# Default to active customers for backwards compatibility
|
||||
where_clauses.append("c.is_active = true")
|
||||
|
||||
if branch_id:
|
||||
where_clauses.append("c.branch_id = %s")
|
||||
params.append(int(branch_id))
|
||||
@@ -42,8 +56,20 @@ def list_customers():
|
||||
"(c.name ILIKE %s OR c.rfc ILIKE %s OR c.phone ILIKE %s OR c.razon_social ILIKE %s)"
|
||||
)
|
||||
params.extend([f'%{search}%'] * 4)
|
||||
if price_tier:
|
||||
# Support numeric tier or Spanish labels
|
||||
tier_map = {'taller': 2, 'mostrador': 1, 'mayoreo': 3}
|
||||
tier_val = tier_map.get(price_tier.lower())
|
||||
if tier_val is None:
|
||||
try:
|
||||
tier_val = int(price_tier)
|
||||
except ValueError:
|
||||
tier_val = None
|
||||
if tier_val in (1, 2, 3):
|
||||
where_clauses.append("c.price_tier = %s")
|
||||
params.append(tier_val)
|
||||
|
||||
where = " AND ".join(where_clauses)
|
||||
where = " AND ".join(where_clauses) if where_clauses else "true"
|
||||
|
||||
# Count
|
||||
cur.execute(f"SELECT count(*) FROM customers c WHERE {where}", params)
|
||||
@@ -54,7 +80,7 @@ def list_customers():
|
||||
SELECT c.id, c.name, c.rfc, c.razon_social, c.phone, c.email,
|
||||
c.address, c.cp,
|
||||
c.price_tier, c.credit_limit, c.credit_balance, c.vehicle_info,
|
||||
c.branch_id
|
||||
c.branch_id, c.is_active, c.created_at, c.last_purchase
|
||||
FROM customers c
|
||||
WHERE {where}
|
||||
ORDER BY c.name
|
||||
@@ -71,6 +97,9 @@ def list_customers():
|
||||
'credit_balance': float(r[10]) if r[10] else 0,
|
||||
'vehicle_info': r[11],
|
||||
'branch_id': r[12],
|
||||
'is_active': r[13],
|
||||
'created_at': str(r[14]) if r[14] else None,
|
||||
'last_purchase': str(r[15]) if r[15] else None,
|
||||
})
|
||||
|
||||
cur.close()
|
||||
@@ -472,6 +501,32 @@ def record_customer_payment(customer_id):
|
||||
UPDATE customers SET credit_balance = %s WHERE id = %s
|
||||
""", (new_balance, customer_id))
|
||||
|
||||
# Allocate the customer payment to oldest unpaid credit sales so the
|
||||
# aging report and per-sale balances reflect the remaining debt.
|
||||
remaining = amount
|
||||
cur.execute("""
|
||||
SELECT s.id, s.total - COALESCE(SUM(sp.amount), 0) as balance
|
||||
FROM sales s
|
||||
LEFT JOIN sale_payments sp ON sp.sale_id = s.id
|
||||
WHERE s.customer_id = %s
|
||||
AND s.sale_type = 'credit'
|
||||
AND s.status = 'completed'
|
||||
GROUP BY s.id, s.total, s.created_at
|
||||
HAVING s.total - COALESCE(SUM(sp.amount), 0) > 0
|
||||
ORDER BY s.created_at
|
||||
""", (customer_id,))
|
||||
for sale_id, balance in cur.fetchall():
|
||||
if remaining <= 0:
|
||||
break
|
||||
pay = round(min(remaining, float(balance)), 2)
|
||||
cur.execute("""
|
||||
INSERT INTO sale_payments
|
||||
(sale_id, register_id, method, amount, reference)
|
||||
VALUES (%s, %s, %s, %s, %s)
|
||||
""", (sale_id, register_id, payment_method, pay,
|
||||
f'Abono cliente #{customer_id}'))
|
||||
remaining = round(remaining - pay, 2)
|
||||
|
||||
# Record cash movement on register if cash payment
|
||||
if register_id and payment_method == 'efectivo':
|
||||
cur.execute("""
|
||||
|
||||
Reference in New Issue
Block a user