"""Phase 1 financial model migration. Before: laundry_order.amount_paid was blindly copied from pos_order.amount_paid, which includes Customer Account / pay-later payments. Every deferred sale appeared fully paid → amount_due was always 0 → Settle Dues was non-functional. After: amount_paid_cash + amount_deferred are computed from pos_payment rows, classified by pos_payment_method.split_transactions. amount_due is recomputed as amount_deferred - amount_settled. This script rebuilds the split for every existing laundry.order by replaying its linked pos_order's payment history. """ import logging _logger = logging.getLogger(__name__) def migrate(cr, version): if not version: return _logger.info('laundry_management: rebuilding financial split for existing orders') # Ensure the new columns exist (ORM will have added them, but be defensive) cr.execute(""" ALTER TABLE laundry_order ADD COLUMN IF NOT EXISTS amount_paid_cash numeric DEFAULT 0, ADD COLUMN IF NOT EXISTS amount_deferred numeric DEFAULT 0; """) # Rebuild amount_paid_cash / amount_deferred per laundry order # from pos_payment rows classified by pos_payment_method.split_transactions. cr.execute(""" WITH classified AS ( SELECT lo.id AS lo_id, COALESCE(SUM(CASE WHEN pm.split_transactions = FALSE THEN pp.amount ELSE 0 END), 0) AS cash, COALESCE(SUM(CASE WHEN pm.split_transactions = TRUE THEN pp.amount ELSE 0 END), 0) AS deferred FROM laundry_order lo LEFT JOIN pos_payment pp ON pp.pos_order_id = lo.pos_order_id LEFT JOIN pos_payment_method pm ON pm.id = pp.payment_method_id GROUP BY lo.id ) UPDATE laundry_order lo SET amount_paid_cash = c.cash, amount_deferred = c.deferred, amount_settled = COALESCE(lo.amount_settled, 0) FROM classified c WHERE c.lo_id = lo.id; """) # amount_due is a stored compute (amount_deferred - amount_settled). # Populate it directly here so the values are correct before the ORM # recomputes (ORM recompute on install will overwrite with same result). cr.execute(""" UPDATE laundry_order SET amount_due = GREATEST( COALESCE(amount_deferred, 0) - COALESCE(amount_settled, 0), 0 ); """) cr.execute(""" SELECT COUNT(*), SUM(amount_paid_cash), SUM(amount_deferred), SUM(amount_due) FROM laundry_order """) row = cr.fetchone() _logger.info( 'laundry_management migration: %s orders — cash=%.2f, deferred=%.2f, due=%.2f', row[0] or 0, row[1] or 0.0, row[2] or 0.0, row[3] or 0.0, )