fix: resolve payment state calculation and enable expense sheet refusal by handling move reversals and cancellations
This commit is contained in:
parent
fa8f270c5b
commit
b916bedbbc
@ -137,6 +137,82 @@ class HrExpenseSheet(models.Model):
|
||||
else:
|
||||
sheet.receipt_status = 'pending'
|
||||
|
||||
@api.depends('account_move_ids.payment_state', 'account_move_ids.amount_residual', 'account_move_ids.state')
|
||||
def _compute_from_account_move_ids(self):
|
||||
"""
|
||||
Overriding to fix the 'IN PAYMENT' ribbon issue.
|
||||
Standard Odoo assumes 'paid' if any move exists for company_account.
|
||||
We check if the moves are actually in 'posted' state.
|
||||
"""
|
||||
for sheet in self:
|
||||
if sheet.payment_mode == 'company_account':
|
||||
if sheet.account_move_ids:
|
||||
# Filter for moves that are NOT canceled
|
||||
active_moves = sheet.account_move_ids.filtered(lambda m: m.state == 'posted')
|
||||
if active_moves:
|
||||
# If there are active moves that are not reversed
|
||||
if active_moves - active_moves.filtered('reversal_move_id'):
|
||||
sheet.payment_state = 'paid'
|
||||
sheet.amount_residual = 0.
|
||||
else:
|
||||
sheet.payment_state = 'reversed'
|
||||
sheet.amount_residual = sum(sheet.account_move_ids.mapped('amount_residual'))
|
||||
else:
|
||||
# Moves exist but none are 'posted' (e.g. they are all 'cancel' or 'draft')
|
||||
sheet.payment_state = 'not_paid'
|
||||
sheet.amount_residual = sum(sheet.account_move_ids.mapped('amount_residual'))
|
||||
else:
|
||||
sheet.payment_state = 'not_paid'
|
||||
sheet.amount_residual = 0.0
|
||||
else:
|
||||
# Standard Odoo logic for own_account
|
||||
if sheet.account_move_ids:
|
||||
sheet.amount_residual = sum(sheet.account_move_ids.mapped('amount_residual'))
|
||||
sheet.payment_state = sheet.account_move_ids[:1].payment_state
|
||||
else:
|
||||
sheet.amount_residual = 0.0
|
||||
sheet.payment_state = 'not_paid'
|
||||
|
||||
def _do_refuse(self, reason):
|
||||
"""
|
||||
Bypass the standard Odoo lock: 'You cannot cancel an expense sheet linked to a journal entry'.
|
||||
We allow it but we'll try to cancel the moves first.
|
||||
"""
|
||||
self._do_reverse_moves()
|
||||
# Explicitly call the original _do_refuse but WITHOUT the check,
|
||||
# but since we already reversed/deleted moves, the original check won't trigger.
|
||||
return super()._do_refuse(reason)
|
||||
|
||||
def _do_reverse_moves(self):
|
||||
"""
|
||||
Overriding to handle account.payment explicitly.
|
||||
Odoo's _do_reverse_moves calls _reverse_moves, which fails for payments.
|
||||
"""
|
||||
self = self.with_context(clean_context(self.env.context))
|
||||
moves = self.account_move_ids
|
||||
if moves:
|
||||
for sheet in self:
|
||||
# Handle payments linked to this sheet
|
||||
payments = sheet.account_move_ids.mapped('payment_id')
|
||||
if payments:
|
||||
# Cancel the payments directly
|
||||
for payment in payments:
|
||||
if payment.state == 'posted':
|
||||
payment.action_cancel()
|
||||
elif payment.state == 'draft':
|
||||
payment.action_cancel()
|
||||
|
||||
# Standard reversal for non-payment moves (if any)
|
||||
non_payment_moves = sheet.account_move_ids.filtered(lambda m: not m.payment_id)
|
||||
if non_payment_moves:
|
||||
non_payment_moves._reverse_moves(
|
||||
default_values_list=[{'invoice_date': fields.Date.context_today(move), 'ref': False} for move in non_payment_moves],
|
||||
cancel=True
|
||||
)
|
||||
|
||||
# Unlink draft moves (including payment moves that are now draft/cancel)
|
||||
sheet.account_move_ids.filtered(lambda m: m.state == 'draft').unlink()
|
||||
|
||||
def action_reset_expense_sheets(self):
|
||||
"""
|
||||
Overriding reset to handle realizations.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user