mirror of
https://github.com/OCA/bank-payment.git
synced 2025-02-02 10:37:31 +02:00
[REF] account_banking_sepa_direct_debit: Adapt module to native payment refactoring
Notable changes: - InstrId and EndToEndId tags are now filled with the journal entry ID, as there's no bank payment line identifier.
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
# Copyright 2013-2020 Akretion (www.akretion.com)
|
# Copyright 2013-2020 Akretion (www.akretion.com)
|
||||||
# Copyright 2014-2020 Tecnativa - Pedro M. Baeza & Antonio Espinosa
|
# Copyright 2016 Tecnativa - Antonio Espinosa
|
||||||
|
# Copyright 2014-2022 Tecnativa - Pedro M. Baeza
|
||||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -7,7 +8,7 @@
|
|||||||
"summary": "Create SEPA files for Direct Debit",
|
"summary": "Create SEPA files for Direct Debit",
|
||||||
"version": "14.0.1.3.3",
|
"version": "14.0.1.3.3",
|
||||||
"license": "AGPL-3",
|
"license": "AGPL-3",
|
||||||
"author": "Akretion, " "Tecnativa, " "Odoo Community Association (OCA)",
|
"author": "Akretion, Tecnativa, Odoo Community Association (OCA)",
|
||||||
"website": "https://github.com/OCA/bank-payment",
|
"website": "https://github.com/OCA/bank-payment",
|
||||||
"category": "Banking addons",
|
"category": "Banking addons",
|
||||||
"depends": ["account_banking_pain_base", "account_banking_mandate"],
|
"depends": ["account_banking_pain_base", "account_banking_mandate"],
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
from . import res_company
|
from . import res_company
|
||||||
from . import account_banking_mandate
|
from . import account_banking_mandate
|
||||||
from . import bank_payment_line
|
|
||||||
from . import account_payment_mode
|
from . import account_payment_mode
|
||||||
from . import account_payment_method
|
from . import account_payment_method
|
||||||
from . import account_payment_order
|
from . import account_payment_order
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Copyright 2020 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
# Copyright 2020 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||||
# Copyright 2018 Tecnativa - Pedro M. Baeza
|
# Copyright 2018-2022 Tecnativa - Pedro M. Baeza
|
||||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
@@ -72,16 +72,17 @@ class AccountPaymentOrder(models.Model):
|
|||||||
lines_per_group = {}
|
lines_per_group = {}
|
||||||
# key = (requested_date, priority, sequence type)
|
# key = (requested_date, priority, sequence type)
|
||||||
# value = list of lines as objects
|
# value = list of lines as objects
|
||||||
for line in self.bank_line_ids:
|
for line in self.payment_ids:
|
||||||
transactions_count_a += 1
|
transactions_count_a += 1
|
||||||
priority = line.priority
|
payment_line = line.payment_line_ids[:1]
|
||||||
categ_purpose = line.category_purpose
|
priority = payment_line.priority
|
||||||
scheme = line.mandate_id.scheme
|
categ_purpose = payment_line.category_purpose
|
||||||
if line.mandate_id.type == "oneoff":
|
scheme = payment_line.mandate_id.scheme
|
||||||
|
if payment_line.mandate_id.type == "oneoff":
|
||||||
seq_type = "OOFF"
|
seq_type = "OOFF"
|
||||||
elif line.mandate_id.type == "recurrent":
|
elif payment_line.mandate_id.type == "recurrent":
|
||||||
seq_type_map = {"recurring": "RCUR", "first": "FRST", "final": "FNAL"}
|
seq_type_map = {"recurring": "RCUR", "first": "FRST", "final": "FNAL"}
|
||||||
seq_type_label = line.mandate_id.recurrent_sequence_type
|
seq_type_label = payment_line.mandate_id.recurrent_sequence_type
|
||||||
assert seq_type_label is not False
|
assert seq_type_label is not False
|
||||||
seq_type = seq_type_map[seq_type_label]
|
seq_type = seq_type_map[seq_type_label]
|
||||||
else:
|
else:
|
||||||
@@ -90,7 +91,7 @@ class AccountPaymentOrder(models.Model):
|
|||||||
"Invalid mandate type in '%s'. Valid ones are 'Recurrent' "
|
"Invalid mandate type in '%s'. Valid ones are 'Recurrent' "
|
||||||
"or 'One-Off'"
|
"or 'One-Off'"
|
||||||
)
|
)
|
||||||
% line.mandate_id.unique_mandate_reference
|
% payment_line.mandate_id.unique_mandate_reference
|
||||||
)
|
)
|
||||||
# The field line.date is the requested payment date
|
# The field line.date is the requested payment date
|
||||||
# taking into account the 'date_preferred' setting
|
# taking into account the 'date_preferred' setting
|
||||||
@@ -165,7 +166,7 @@ class AccountPaymentOrder(models.Model):
|
|||||||
)
|
)
|
||||||
instruction_identification.text = self._prepare_field(
|
instruction_identification.text = self._prepare_field(
|
||||||
"Instruction Identification",
|
"Instruction Identification",
|
||||||
"line.name",
|
"str(line.move_id.id)",
|
||||||
{"line": line},
|
{"line": line},
|
||||||
35,
|
35,
|
||||||
gen_args=gen_args,
|
gen_args=gen_args,
|
||||||
@@ -175,7 +176,7 @@ class AccountPaymentOrder(models.Model):
|
|||||||
)
|
)
|
||||||
end2end_identification.text = self._prepare_field(
|
end2end_identification.text = self._prepare_field(
|
||||||
"End to End Identification",
|
"End to End Identification",
|
||||||
"line.name",
|
"str(line.move_id.id)",
|
||||||
{"line": line},
|
{"line": line},
|
||||||
35,
|
35,
|
||||||
gen_args=gen_args,
|
gen_args=gen_args,
|
||||||
@@ -190,18 +191,19 @@ class AccountPaymentOrder(models.Model):
|
|||||||
instructed_amount = etree.SubElement(
|
instructed_amount = etree.SubElement(
|
||||||
dd_transaction_info, "InstdAmt", Ccy=currency_name
|
dd_transaction_info, "InstdAmt", Ccy=currency_name
|
||||||
)
|
)
|
||||||
instructed_amount.text = "%.2f" % line.amount_currency
|
instructed_amount.text = "%.2f" % line.amount
|
||||||
amount_control_sum_a += line.amount_currency
|
amount_control_sum_a += line.amount
|
||||||
amount_control_sum_b += line.amount_currency
|
amount_control_sum_b += line.amount
|
||||||
dd_transaction = etree.SubElement(dd_transaction_info, "DrctDbtTx")
|
dd_transaction = etree.SubElement(dd_transaction_info, "DrctDbtTx")
|
||||||
mandate_related_info = etree.SubElement(dd_transaction, "MndtRltdInf")
|
mandate_related_info = etree.SubElement(dd_transaction, "MndtRltdInf")
|
||||||
mandate_identification = etree.SubElement(
|
mandate_identification = etree.SubElement(
|
||||||
mandate_related_info, "MndtId"
|
mandate_related_info, "MndtId"
|
||||||
)
|
)
|
||||||
|
mandate = line.payment_line_ids[:1].mandate_id
|
||||||
mandate_identification.text = self._prepare_field(
|
mandate_identification.text = self._prepare_field(
|
||||||
"Unique Mandate Reference",
|
"Unique Mandate Reference",
|
||||||
"line.mandate_id.unique_mandate_reference",
|
"mandate.unique_mandate_reference",
|
||||||
{"line": line},
|
{"mandate": mandate},
|
||||||
35,
|
35,
|
||||||
gen_args=gen_args,
|
gen_args=gen_args,
|
||||||
)
|
)
|
||||||
@@ -211,16 +213,11 @@ class AccountPaymentOrder(models.Model):
|
|||||||
mandate_signature_date.text = self._prepare_field(
|
mandate_signature_date.text = self._prepare_field(
|
||||||
"Mandate Signature Date",
|
"Mandate Signature Date",
|
||||||
"signature_date",
|
"signature_date",
|
||||||
{
|
{"signature_date": fields.Date.to_string(mandate.signature_date)},
|
||||||
"line": line,
|
|
||||||
"signature_date": fields.Date.to_string(
|
|
||||||
line.mandate_id.signature_date
|
|
||||||
),
|
|
||||||
},
|
|
||||||
10,
|
10,
|
||||||
gen_args=gen_args,
|
gen_args=gen_args,
|
||||||
)
|
)
|
||||||
if sequence_type == "FRST" and line.mandate_id.last_debit_date:
|
if sequence_type == "FRST" and mandate.last_debit_date:
|
||||||
amendment_indicator = etree.SubElement(
|
amendment_indicator = etree.SubElement(
|
||||||
mandate_related_info, "AmdmntInd"
|
mandate_related_info, "AmdmntInd"
|
||||||
)
|
)
|
||||||
@@ -252,10 +249,10 @@ class AccountPaymentOrder(models.Model):
|
|||||||
gen_args,
|
gen_args,
|
||||||
line,
|
line,
|
||||||
)
|
)
|
||||||
|
line_purpose = line.payment_line_ids[:1].purpose
|
||||||
if line.purpose:
|
if line_purpose:
|
||||||
purpose = etree.SubElement(dd_transaction_info, "Purp")
|
purpose = etree.SubElement(dd_transaction_info, "Purp")
|
||||||
etree.SubElement(purpose, "Cd").text = line.purpose
|
etree.SubElement(purpose, "Cd").text = line_purpose
|
||||||
|
|
||||||
self.generate_remittance_info_block(dd_transaction_info, line, gen_args)
|
self.generate_remittance_info_block(dd_transaction_info, line, gen_args)
|
||||||
|
|
||||||
@@ -281,18 +278,19 @@ class AccountPaymentOrder(models.Model):
|
|||||||
to_expire_mandates = abmo.browse([])
|
to_expire_mandates = abmo.browse([])
|
||||||
first_mandates = abmo.browse([])
|
first_mandates = abmo.browse([])
|
||||||
all_mandates = abmo.browse([])
|
all_mandates = abmo.browse([])
|
||||||
for bline in order.bank_line_ids:
|
for payment in order.payment_ids:
|
||||||
if bline.mandate_id in all_mandates:
|
mandate = payment.payment_line_ids.mandate_id
|
||||||
|
if mandate in all_mandates:
|
||||||
continue
|
continue
|
||||||
all_mandates += bline.mandate_id
|
all_mandates += mandate
|
||||||
if bline.mandate_id.type == "oneoff":
|
if mandate.type == "oneoff":
|
||||||
to_expire_mandates += bline.mandate_id
|
to_expire_mandates += mandate
|
||||||
elif bline.mandate_id.type == "recurrent":
|
elif mandate.type == "recurrent":
|
||||||
seq_type = bline.mandate_id.recurrent_sequence_type
|
seq_type = mandate.recurrent_sequence_type
|
||||||
if seq_type == "final":
|
if seq_type == "final":
|
||||||
to_expire_mandates += bline.mandate_id
|
to_expire_mandates += mandate
|
||||||
elif seq_type == "first":
|
elif seq_type == "first":
|
||||||
first_mandates += bline.mandate_id
|
first_mandates += mandate
|
||||||
all_mandates.write({"last_debit_date": order.date_generated})
|
all_mandates.write({"last_debit_date": order.date_generated})
|
||||||
to_expire_mandates.write({"state": "expired"})
|
to_expire_mandates.write({"state": "expired"})
|
||||||
first_mandates.write({"recurrent_sequence_type": "recurring"})
|
first_mandates.write({"recurrent_sequence_type": "recurring"})
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
# Copyright 2020 Akretion - Alexis de Lattre
|
|
||||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
|
||||||
|
|
||||||
from odoo import models
|
|
||||||
|
|
||||||
|
|
||||||
class BankPaymentLine(models.Model):
|
|
||||||
_inherit = "bank.payment.line"
|
|
||||||
|
|
||||||
def move_line_offsetting_account_hashcode(self):
|
|
||||||
"""
|
|
||||||
From my experience, even when you ask several direct debits
|
|
||||||
at the same date with enough delay, you will have several credits
|
|
||||||
on your bank statement: one for each mandate types.
|
|
||||||
So we split the transfer move lines by mandate type, so easier
|
|
||||||
reconciliation of the bank statement.
|
|
||||||
"""
|
|
||||||
hashcode = super().move_line_offsetting_account_hashcode()
|
|
||||||
hashcode += "-" + str(self.mandate_id.recurrent_sequence_type)
|
|
||||||
return hashcode
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
# Copyright 2016 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
# Copyright 2016 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||||
# Copyright 2018-2020 Tecnativa - Pedro M. Baeza
|
# Copyright 2018-2022 Tecnativa - Pedro M. Baeza
|
||||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
import base64
|
import base64
|
||||||
@@ -42,7 +42,6 @@ class TestSDDBase(SavepointCase):
|
|||||||
cls.payment_order_model = cls.env["account.payment.order"]
|
cls.payment_order_model = cls.env["account.payment.order"]
|
||||||
cls.payment_line_model = cls.env["account.payment.line"]
|
cls.payment_line_model = cls.env["account.payment.line"]
|
||||||
cls.mandate_model = cls.env["account.banking.mandate"]
|
cls.mandate_model = cls.env["account.banking.mandate"]
|
||||||
cls.bank_line_model = cls.env["bank.payment.line"]
|
|
||||||
cls.partner_bank_model = cls.env["res.partner.bank"]
|
cls.partner_bank_model = cls.env["res.partner.bank"]
|
||||||
cls.attachment_model = cls.env["ir.attachment"]
|
cls.attachment_model = cls.env["ir.attachment"]
|
||||||
cls.invoice_model = cls.env["account.move"]
|
cls.invoice_model = cls.env["account.move"]
|
||||||
@@ -255,22 +254,14 @@ class TestSDDBase(SavepointCase):
|
|||||||
payment_order.draft2open()
|
payment_order.draft2open()
|
||||||
self.assertEqual(payment_order.state, "open")
|
self.assertEqual(payment_order.state, "open")
|
||||||
self.assertEqual(payment_order.sepa, True)
|
self.assertEqual(payment_order.sepa, True)
|
||||||
# Check bank payment line
|
# Check account payment
|
||||||
bank_lines = self.bank_line_model.search(
|
agrolait_bank_line = payment_order.payment_ids[0]
|
||||||
[("partner_id", "=", self.partner_agrolait.id)]
|
|
||||||
)
|
|
||||||
self.assertEqual(len(bank_lines), 1)
|
|
||||||
agrolait_bank_line = bank_lines[0]
|
|
||||||
self.assertEqual(agrolait_bank_line.currency_id, self.eur_currency)
|
self.assertEqual(agrolait_bank_line.currency_id, self.eur_currency)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
float_compare(
|
float_compare(agrolait_bank_line.amount, 42.0, precision_digits=accpre),
|
||||||
agrolait_bank_line.amount_currency, 42.0, precision_digits=accpre
|
|
||||||
),
|
|
||||||
0,
|
0,
|
||||||
)
|
)
|
||||||
self.assertEqual(agrolait_bank_line.communication_type, "normal")
|
self.assertEqual(agrolait_bank_line.payment_reference, invoice1.name)
|
||||||
self.assertEqual(agrolait_bank_line.communication, invoice1.name)
|
|
||||||
self.assertEqual(agrolait_bank_line.mandate_id, invoice1.mandate_id)
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
agrolait_bank_line.partner_bank_id, invoice1.mandate_id.partner_bank_id
|
agrolait_bank_line.partner_bank_id, invoice1.mandate_id.partner_bank_id
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user