80 lines
2.8 KiB
Python
80 lines
2.8 KiB
Python
from odoo import fields, models, api, _
|
|
from datetime import date
|
|
|
|
|
|
class Partner(models.Model):
|
|
_inherit = "res.partner"
|
|
|
|
postpone_hold_until = fields.Date(
|
|
string="Postpone Hold",
|
|
help="Grace period specific to this partner despite unpaid invoices.",
|
|
tracking=True,
|
|
)
|
|
|
|
hold_bg = fields.Boolean(
|
|
string="Hold (technical)",
|
|
compute="_compute_hold_bg",
|
|
store=True,
|
|
default=False,
|
|
compute_sudo=True,
|
|
tracking=True,
|
|
)
|
|
on_hold = fields.Boolean(
|
|
string="Account on Hold",
|
|
help="Client account is on hold for unpaid overdue invoices.",
|
|
compute="_compute_on_hold",
|
|
compute_sudo=True,
|
|
)
|
|
|
|
@api.depends("postpone_hold_until", "hold_bg")
|
|
def _compute_on_hold(self):
|
|
# manually re-compute hold_bg since followup_status doesn't get updated in Python but gets recalculated
|
|
# by an SQL query every time
|
|
self._compute_hold_bg()
|
|
for rec in self:
|
|
# If the parent company is on hold, so are all its sub-contacts and subsidiaries
|
|
if rec.commercial_partner_id and rec.commercial_partner_id.on_hold:
|
|
rec.on_hold = True
|
|
return
|
|
# If there is no parent company or the parent is not on hold, we compute for ourselves
|
|
if rec.hold_bg and not (
|
|
rec.postpone_hold_until and rec.postpone_hold_until > date.today()
|
|
):
|
|
rec.on_hold = True
|
|
else:
|
|
if rec.on_hold:
|
|
rec.message_post(_("Credit hold lifted."))
|
|
rec.on_hold = False
|
|
|
|
@api.autovacuum
|
|
def _cleanup_expired_hold_postponements(self):
|
|
expired_holds = self.search([("postpone_hold_until", "<=", date.today())])
|
|
expired_holds.write({"postpone_hold_until": False})
|
|
|
|
def action_credit_hold(self):
|
|
for rec in self:
|
|
rec.hold_bg = True
|
|
rec.message_post(body=_("Placed on credit hold."))
|
|
|
|
def action_lift_credit_hold(self):
|
|
for rec in self:
|
|
rec.hold_bg = False
|
|
rec.message_post(body=_("Credit hold lifted."))
|
|
|
|
def _execute_followup_partner(self, options=None):
|
|
res = super()._execute_followup_partner(options)
|
|
if self.followup_status == "in_need_of_action":
|
|
if self.followup_line_id.account_hold:
|
|
self.action_credit_hold()
|
|
return res
|
|
|
|
@api.depends("followup_status", "followup_line_id")
|
|
def _compute_hold_bg(self):
|
|
first_followup_level = self._get_first_followup_level()
|
|
for rec in self:
|
|
prev_hold_bg = rec.hold_bg
|
|
level = rec.followup_line_id
|
|
if rec.followup_status == "no_action_needed" and not level:
|
|
rec.hold_bg = False
|
|
else:
|
|
rec.hold_bg = prev_hold_bg
|