bank-payment/account_banking_mandate/models/account_banking_mandate.py
2024-05-03 10:36:50 +02:00

211 lines
7.6 KiB
Python

# Copyright 2014 Compassion CH - Cyril Sester <csester@compassion.ch>
# Copyright 2014 Tecnativa - Pedro M. Baeza
# Copyright 2015-2020 Akretion - Alexis de Lattre <alexis.delattre@akretion.com>
# Copyright 2020 Tecnativa - Carlos Dauden
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from flectra import _, api, fields, models
from flectra.exceptions import UserError, ValidationError
class AccountBankingMandate(models.Model):
"""The banking mandate is attached to a bank account and represents an
authorization that the bank account owner gives to a company for a
specific operation (such as direct debit)
"""
_name = "account.banking.mandate"
_description = "A generic banking mandate"
_inherit = ["mail.thread", "mail.activity.mixin"]
_order = "signature_date desc"
_check_company_auto = True
def _get_default_partner_bank_id_domain(self):
if "default_partner_id" in self.env.context:
return [("partner_id", "=", self.env.context.get("default_partner_id"))]
else:
return []
format = fields.Selection(
[("basic", "Basic Mandate")],
default="basic",
required=True,
string="Mandate Format",
tracking=20,
)
type = fields.Selection(
[("generic", "Generic Mandate")],
string="Type of Mandate",
tracking=30,
)
partner_bank_id = fields.Many2one(
comodel_name="res.partner.bank",
string="Bank Account",
tracking=40,
domain=lambda self: self._get_default_partner_bank_id_domain(),
ondelete="restrict",
index="btree",
check_company=True,
)
partner_id = fields.Many2one(
comodel_name="res.partner",
related="partner_bank_id.partner_id",
string="Partner",
store=True,
index="btree",
)
company_id = fields.Many2one(
comodel_name="res.company",
string="Company",
required=True,
default=lambda self: self.env.company,
)
unique_mandate_reference = fields.Char(tracking=10, copy=False, default="/")
signature_date = fields.Date(
string="Date of Signature of the Mandate",
tracking=50,
)
scan = fields.Binary(string="Scan of the Mandate")
last_debit_date = fields.Date(string="Date of the Last Debit", readonly=True)
state = fields.Selection(
[
("draft", "Draft"),
("valid", "Valid"),
("expired", "Expired"),
("cancel", "Cancelled"),
],
string="Status",
default="draft",
tracking=60,
help="Only valid mandates can be used in a payment line. A cancelled "
"mandate is a mandate that has been cancelled by the customer.",
)
payment_line_ids = fields.One2many(
comodel_name="account.payment.line",
inverse_name="mandate_id",
string="Related Payment Lines",
)
payment_line_ids_count = fields.Integer(compute="_compute_payment_line_ids_count")
_sql_constraints = [
(
"mandate_ref_company_uniq",
"unique(unique_mandate_reference, company_id)",
"A Mandate with the same reference already exists for this company!",
)
]
@api.depends("unique_mandate_reference", "partner_bank_id.acc_number")
def _compute_display_name(self):
for mandate in self:
name = mandate.unique_mandate_reference
acc_number = mandate.partner_bank_id.acc_number
if acc_number:
name = f"{name} [...{acc_number[-4:]}]"
mandate.display_name = name
@api.depends("payment_line_ids")
def _compute_payment_line_ids_count(self):
payment_line_model = self.env["account.payment.line"]
domain = [("mandate_id", "in", self.ids)]
res = payment_line_model.read_group(
domain=domain, fields=["mandate_id"], groupby=["mandate_id"]
)
payment_line_dict = {}
for dic in res:
mandate_id = dic["mandate_id"][0]
payment_line_dict.setdefault(mandate_id, 0)
payment_line_dict[mandate_id] += dic["mandate_id_count"]
for rec in self:
rec.payment_line_ids_count = payment_line_dict.get(rec.id, 0)
def show_payment_lines(self):
self.ensure_one()
return {
"name": _("Payment lines"),
"type": "ir.actions.act_window",
"view_mode": "tree,form",
"res_model": "account.payment.line",
"domain": [("mandate_id", "=", self.id)],
}
@api.constrains("signature_date", "last_debit_date")
def _check_dates(self):
today = fields.Date.context_today(self)
for mandate in self:
if mandate.signature_date and mandate.signature_date > today:
raise ValidationError(
_("The date of signature of mandate '%s' " "is in the future!")
% mandate.unique_mandate_reference
)
if (
mandate.signature_date
and mandate.last_debit_date
and mandate.signature_date > mandate.last_debit_date
):
raise ValidationError(
_(
"The mandate '%s' can't have a date of last debit "
"before the date of signature."
)
% mandate.unique_mandate_reference
)
@api.constrains("state", "partner_bank_id", "signature_date")
def _check_valid_state(self):
for mandate in self:
if mandate.state == "valid":
if not mandate.signature_date:
raise ValidationError(
_(
"Cannot validate the mandate '%s' without a date of "
"signature."
)
% mandate.unique_mandate_reference
)
if not mandate.partner_bank_id:
raise ValidationError(
_(
"Cannot validate the mandate '%s' because it is not "
"attached to a bank account."
)
% mandate.unique_mandate_reference
)
@api.model_create_multi
def create(self, vals_list):
for vals in vals_list:
unique_mandate_reference = vals.get("unique_mandate_reference", "/")
if unique_mandate_reference == "/":
vals["unique_mandate_reference"] = (
self.env["ir.sequence"].next_by_code("account.banking.mandate")
or "New"
)
return super().create(vals_list)
@api.onchange("partner_bank_id")
def mandate_partner_bank_change(self):
for mandate in self:
mandate.partner_id = mandate.partner_bank_id.partner_id
def validate(self):
for mandate in self:
if mandate.state != "draft":
raise UserError(_("Mandate should be in draft state."))
self.write({"state": "valid"})
def cancel(self):
for mandate in self:
if mandate.state not in ("draft", "valid"):
raise UserError(_("Mandate should be in draft or valid state."))
self.write({"state": "cancel"})
def back2draft(self):
"""Allows to set the mandate back to the draft state.
This is for mandates cancelled by mistake.
"""
for mandate in self:
if mandate.state != "cancel":
raise UserError(_("Mandate should be in cancel state."))
self.write({"state": "draft"})