From 70ac4baf8b0dbd29ad457cd5152846ae50edc242 Mon Sep 17 00:00:00 2001 From: Suherdy Yacob Date: Mon, 6 Apr 2026 12:04:09 +0700 Subject: [PATCH] fix: bypass hr_expense lock during payment posting by temporarily clearing expense sheet cache --- models/account_payment.py | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/models/account_payment.py b/models/account_payment.py index ae7a219..8335c34 100644 --- a/models/account_payment.py +++ b/models/account_payment.py @@ -10,11 +10,28 @@ class AccountPayment(models.Model): """ Force synchronization before posting to ensure deductions are included, even if the payment was previously 'Reset to Draft' without edits. + We must wrap this in the same bypass logic as _synchronize_to_moves + to avoid the 'Invalid Operation' error from hr_expense. """ - for payment in self: - if payment.state == 'draft' and payment.expense_sheet_id: - # Force sync by pretending amount changed to refresh the lines - payment._synchronize_to_moves({'amount', 'deduction_line_ids', 'amount_substract'}) + # If we have draft payments linked to a sheet, we must bypass the hr_expense lock during posting + draft_payouts = self.filtered(lambda p: p.state == 'draft' and p.expense_sheet_id) + if draft_payouts: + links = {p.id: p.expense_sheet_id.id for p in draft_payouts} + # Hide the links temporarily + for p in draft_payouts: + p.env.cache.set(p, p._fields['expense_sheet_id'], False) + try: + # Force sync deductions + for p in draft_payouts: + p._synchronize_to_moves({'amount', 'deduction_line_ids', 'amount_substract'}) + # Call original post logic + return super().action_post() + finally: + # Restore links + for p in draft_payouts: + if p.id in links: + p.env.cache.set(p, p._fields['expense_sheet_id'], self.env['hr.expense.sheet'].browse(links[p.id])) + return super().action_post() def _synchronize_to_moves(self, changed_fields):