diff --git a/addons/laundry_management/migrations/19.0.19.0.2/post-migrate.py b/addons/laundry_management/migrations/19.0.19.0.2/post-migrate.py new file mode 100644 index 0000000..1d056d6 --- /dev/null +++ b/addons/laundry_management/migrations/19.0.19.0.2/post-migrate.py @@ -0,0 +1,75 @@ +"""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, + )