mirror of
https://gitlab.com/flectra-community/bank-payment.git
synced 2024-11-22 05:32:05 +00:00
212 lines
7.6 KiB
Python
212 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=True,
|
||
|
check_company=True,
|
||
|
)
|
||
|
partner_id = fields.Many2one(
|
||
|
comodel_name="res.partner",
|
||
|
related="partner_bank_id.partner_id",
|
||
|
string="Partner",
|
||
|
store=True,
|
||
|
index=True,
|
||
|
)
|
||
|
company_id = fields.Many2one(
|
||
|
comodel_name="res.company",
|
||
|
string="Company",
|
||
|
required=True,
|
||
|
default=lambda self: self.env.company,
|
||
|
)
|
||
|
unique_mandate_reference = fields.Char(
|
||
|
string="Unique Mandate Reference", tracking=10, copy=False
|
||
|
)
|
||
|
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!",
|
||
|
)
|
||
|
]
|
||
|
|
||
|
def name_get(self):
|
||
|
result = []
|
||
|
for mandate in self:
|
||
|
name = mandate.unique_mandate_reference
|
||
|
acc_number = mandate.partner_bank_id.acc_number
|
||
|
if acc_number:
|
||
|
name = "{} [...{}]".format(name, acc_number[-4:])
|
||
|
result.append((mandate.id, name))
|
||
|
return result
|
||
|
|
||
|
@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
|
||
|
def create(self, vals=None):
|
||
|
unique_mandate_reference = vals.get("unique_mandate_reference")
|
||
|
if not unique_mandate_reference or unique_mandate_reference == "New":
|
||
|
vals["unique_mandate_reference"] = (
|
||
|
self.env["ir.sequence"].next_by_code("account.banking.mandate") or "New"
|
||
|
)
|
||
|
return super().create(vals)
|
||
|
|
||
|
@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"})
|