Files
Autoparts-DB/scripts/allocate_existing_customer_payments.py
consultoria-as 2bdeb2973a
Some checks failed
CI / lint-and-test (3.11) (push) Has been cancelled
CI / lint-and-test (3.13) (push) Has been cancelled
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
2026-06-29 23:54:58 +00:00

71 lines
2.1 KiB
Python

#!/usr/bin/env python3
"""
One-off helper: allocate existing customer_payments (abonos) to the oldest
unpaid credit sales for each customer.
This fixes historical data recorded before the customer-payment endpoint
started creating sale_payments rows automatically.
Run against a tenant database, e.g.:
DATABASE_URL=postgresql://postgres@localhost/tenant_refaccionaria_la_casita \
python3 scripts/allocate_existing_customer_payments.py
"""
import os
import sys
import psycopg2
DB_URL = os.environ.get('DATABASE_URL')
if not DB_URL:
print('DATABASE_URL is required')
sys.exit(1)
conn = psycopg2.connect(DB_URL)
cur = conn.cursor()
cur.execute("""
SELECT customer_id, SUM(amount) as total_paid
FROM customer_payments
GROUP BY customer_id
ORDER BY customer_id
""")
customer_payments = cur.fetchall()
inserted = 0
for customer_id, total_paid in customer_payments:
total_paid = float(total_paid or 0)
if total_paid <= 0:
continue
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,))
remaining = round(total_paid, 2)
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, method, amount, reference)
VALUES (%s, 'efectivo', %s, %s)
""", (sale_id, pay, f'Abono cliente #{customer_id} (reproceso)'))
remaining = round(remaining - pay, 2)
inserted += 1
if remaining > 0:
print(f' Warning: customer {customer_id} has ${remaining} not allocated to any sale')
conn.commit()
cur.close()
conn.close()
print(f'Allocated existing customer payments into {inserted} sale_payments rows.')