fix: improve expense payment computation logic and allow manual overrides in payment wizard
This commit is contained in:
parent
7da10ccb15
commit
8dccf0cd9a
@ -6,7 +6,7 @@ class HrExpensePaymentWizard(models.TransientModel):
|
|||||||
_description = 'Expense Payment Wizard'
|
_description = 'Expense Payment Wizard'
|
||||||
|
|
||||||
expense_sheet_id = fields.Many2one('hr.expense.sheet', required=True)
|
expense_sheet_id = fields.Many2one('hr.expense.sheet', required=True)
|
||||||
amount = fields.Monetary(string='Payment Amount', required=True, readonly=True)
|
amount = fields.Monetary(string='Payment Amount', required=True)
|
||||||
currency_id = fields.Many2one('res.currency', related='expense_sheet_id.currency_id')
|
currency_id = fields.Many2one('res.currency', related='expense_sheet_id.currency_id')
|
||||||
company_id = fields.Many2one('res.company', related='expense_sheet_id.company_id')
|
company_id = fields.Many2one('res.company', related='expense_sheet_id.company_id')
|
||||||
|
|
||||||
|
|||||||
@ -155,7 +155,12 @@ class HrExpenseRealization(models.Model):
|
|||||||
|
|
||||||
# Credit for Advance clearing
|
# Credit for Advance clearing
|
||||||
# We clear the remaining advance amount in the first realization for an expense.
|
# We clear the remaining advance amount in the first realization for an expense.
|
||||||
original_paid = self.expense_id.total_amount
|
# Use proportional share of actual amount paid if payment was different from requested total
|
||||||
|
sheet = self.expense_id.sheet_id
|
||||||
|
if sheet.total_amount:
|
||||||
|
original_paid = self.expense_id.total_amount * (sheet.amount_paid / sheet.total_amount)
|
||||||
|
else:
|
||||||
|
original_paid = 0.0
|
||||||
|
|
||||||
# Find already cleared advance amount from previous posted moves targeting this expense and advance account
|
# Find already cleared advance amount from previous posted moves targeting this expense and advance account
|
||||||
cleared_before = sum(self.env['account.move.line'].search([
|
cleared_before = sum(self.env['account.move.line'].search([
|
||||||
|
|||||||
@ -81,7 +81,7 @@ class HrExpenseSheet(models.Model):
|
|||||||
help="Total amount paid by the finance team (Total - Residual)."
|
help="Total amount paid by the finance team (Total - Residual)."
|
||||||
)
|
)
|
||||||
|
|
||||||
@api.depends('account_move_ids.line_ids.matched_debit_ids', 'account_move_ids.line_ids.matched_credit_ids', 'total_amount', 'amount_residual')
|
@api.depends('account_move_ids.line_ids.matched_debit_ids', 'account_move_ids.line_ids.matched_credit_ids', 'account_move_ids.payment_id.amount', 'account_move_ids.payment_id.state', 'total_amount', 'amount_residual')
|
||||||
def _compute_amount_paid(self):
|
def _compute_amount_paid(self):
|
||||||
for sheet in self:
|
for sheet in self:
|
||||||
total_paid = 0.0
|
total_paid = 0.0
|
||||||
@ -120,6 +120,13 @@ class HrExpenseSheet(models.Model):
|
|||||||
total_paid += abs(counterpart.balance)
|
total_paid += abs(counterpart.balance)
|
||||||
seen_move_line_ids.add(counterpart.id)
|
seen_move_line_ids.add(counterpart.id)
|
||||||
|
|
||||||
|
# Direct payments linked to moves (handles non-reconciled company advances)
|
||||||
|
for move in sheet.account_move_ids:
|
||||||
|
if move.payment_id and move.payment_id.state not in ('draft', 'cancel'):
|
||||||
|
if move.payment_id.id not in seen_payment_ids:
|
||||||
|
total_paid += move.payment_id.amount
|
||||||
|
seen_payment_ids.add(move.payment_id.id)
|
||||||
|
|
||||||
# If no bank transactions found but report is clearly paid/partially paid,
|
# If no bank transactions found but report is clearly paid/partially paid,
|
||||||
# fall back to standard calculation for non-bank flows (e.g. manual journal reconciliation)
|
# fall back to standard calculation for non-bank flows (e.g. manual journal reconciliation)
|
||||||
if not total_paid and sheet.total_amount != sheet.amount_residual:
|
if not total_paid and sheet.total_amount != sheet.amount_residual:
|
||||||
@ -169,11 +176,14 @@ class HrExpenseSheet(models.Model):
|
|||||||
payments = moves.mapped('payment_id')
|
payments = moves.mapped('payment_id')
|
||||||
unmatched_payments = payments.filtered(lambda p: not p.is_matched)
|
unmatched_payments = payments.filtered(lambda p: not p.is_matched)
|
||||||
|
|
||||||
if unmatched_payments:
|
if sheet.amount_paid < sheet.total_amount:
|
||||||
|
sheet.payment_state = 'partial'
|
||||||
|
elif unmatched_payments:
|
||||||
sheet.payment_state = 'in_payment'
|
sheet.payment_state = 'in_payment'
|
||||||
else:
|
else:
|
||||||
sheet.payment_state = 'paid'
|
sheet.payment_state = 'paid'
|
||||||
sheet.amount_residual = 0.
|
|
||||||
|
sheet.amount_residual = max(0.0, sheet.total_amount - sheet.amount_paid)
|
||||||
else:
|
else:
|
||||||
sheet.payment_state = 'reversed'
|
sheet.payment_state = 'reversed'
|
||||||
sheet.amount_residual = sum(sheet.account_move_ids.mapped('amount_residual'))
|
sheet.amount_residual = sum(sheet.account_move_ids.mapped('amount_residual'))
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user