[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:
Pedro M. Baeza
2022-11-06 16:08:09 +01:00
parent c89f66a42b
commit 01472a8467
5 changed files with 41 additions and 72 deletions

View File

@@ -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"],

View File

@@ -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

View File

@@ -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"})

View File

@@ -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

View File

@@ -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
) )