diff --git a/account_banking_pain_base/models/account_payment_line.py b/account_banking_pain_base/models/account_payment_line.py index c430b5cff..a460b9551 100644 --- a/account_banking_pain_base/models/account_payment_line.py +++ b/account_banking_pain_base/models/account_payment_line.py @@ -15,10 +15,47 @@ class AccountPaymentLine(models.Model): string='Priority', default='NORM', help="This field will be used as 'Instruction Priority' in " "the generated PAIN file.") - # local_instrument is used in some countries, for example - # switzerland, cf l10n_ch_sepa that adds some entries in - # the selection field + # local_instrument is used for instant credit transfers which + # will begin on November 2017, cf account_banking_sepa_credit_transfer + # It is also used in some countries such as switzerland, + # cf l10n_ch_pain_base that adds some entries in the selection field local_instrument = fields.Selection([], string='Local Instrument') + category_purpose = fields.Selection([ + # Full category purpose list found on: + # https://www.iso20022.org/external_code_list.page + # Document "External Code Sets spreadsheet" version Feb 8th 2017 + ('BONU', 'Bonus Payment'), + ('CASH', 'Cash Management Transfer'), + ('CBLK', 'Card Bulk Clearing'), + ('CCRD', 'Credit Card Payment'), + ('CORT', 'Trade Settlement Payment'), + ('DCRD', 'Debit Card Payment'), + ('DIVI', 'Dividend'), + ('DVPM', 'Deliver Against Payment'), + ('EPAY', 'ePayment'), + ('FCOL', 'Fee Collection'), + ('GOVT', 'Government Payment'), + ('HEDG', 'Hedging'), + ('ICCP', 'Irrevocable Credit Card Payment'), + ('IDCP', 'Irrevocable Debit Card Payment'), + ('INTC', 'Intra-Company Payment'), + ('INTE', 'Interest'), + ('LOAN', 'Loan'), + ('OTHR', 'Other Payment'), + ('PENS', 'Pension Payment'), + ('RVPM', 'Receive Against Payment'), + ('SALA', 'Salary Payment'), + ('SECU', 'Securities'), + ('SSBE', 'Social Security Benefit'), + ('SUPP', 'Supplier Payment'), + ('TAXS', 'Tax Payment'), + ('TRAD', 'Trade'), + ('TREA', 'Treasury Payment'), + ('VATX', 'VAT Payment'), + ('WHLD', 'WithHolding'), + ], string="Category Purpose", + help="If neither your bank nor your local regulations oblige you to " + "set the category purpose, leave the field empty.") # PAIN allows 140 characters communication = fields.Char(size=140) # The field struct_communication_type has been dropped in v9 diff --git a/account_banking_pain_base/models/account_payment_order.py b/account_banking_pain_base/models/account_payment_order.py index 4e62f6a99..751096e22 100644 --- a/account_banking_pain_base/models/account_payment_order.py +++ b/account_banking_pain_base/models/account_payment_order.py @@ -203,8 +203,8 @@ class AccountPaymentOrder(models.Model): @api.model def generate_start_payment_info_block( self, parent_node, payment_info_ident, - priority, local_instrument, sequence_type, requested_date, - eval_ctx, gen_args): + priority, local_instrument, category_purpose, sequence_type, + requested_date, eval_ctx, gen_args): payment_info = etree.SubElement(parent_node, 'PmtInf') payment_info_identification = etree.SubElement( payment_info, 'PmtInfId') @@ -249,7 +249,12 @@ class AccountPaymentOrder(models.Model): sequence_type_node = etree.SubElement( payment_type_info, 'SeqTp') sequence_type_node.text = sequence_type - + if category_purpose: + category_purpose_node = etree.SubElement( + payment_type_info, 'CtgyPurp') + category_purpose_code = etree.SubElement( + category_purpose_node, 'Cd') + category_purpose_code.text = category_purpose if gen_args['payment_method'] == 'DD': request_date_tag = 'ReqdColltnDt' else: diff --git a/account_banking_pain_base/models/bank_payment_line.py b/account_banking_pain_base/models/bank_payment_line.py index dde080637..c055ac5b4 100644 --- a/account_banking_pain_base/models/bank_payment_line.py +++ b/account_banking_pain_base/models/bank_payment_line.py @@ -13,10 +13,12 @@ class BankPaymentLine(models.Model): local_instrument = fields.Selection( related='payment_line_ids.local_instrument', string='Local Instrument') + category_purpose = fields.Selection( + related='payment_line_ids.category_purpose', string='Category Purpose') @api.model def same_fields_payment_line_and_bank_payment_line(self): res = super(BankPaymentLine, self).\ same_fields_payment_line_and_bank_payment_line() - res += ['priority', 'local_instrument'] + res += ['priority', 'local_instrument', 'category_purpose'] return res diff --git a/account_banking_pain_base/views/account_payment_line.xml b/account_banking_pain_base/views/account_payment_line.xml index e84958e63..925f43e49 100644 --- a/account_banking_pain_base/views/account_payment_line.xml +++ b/account_banking_pain_base/views/account_payment_line.xml @@ -13,7 +13,8 @@ - + + diff --git a/account_banking_pain_base/views/bank_payment_line_view.xml b/account_banking_pain_base/views/bank_payment_line_view.xml index f9496dffd..d6d05a9b3 100644 --- a/account_banking_pain_base/views/bank_payment_line_view.xml +++ b/account_banking_pain_base/views/bank_payment_line_view.xml @@ -13,7 +13,8 @@ - + + diff --git a/account_banking_sepa_credit_transfer/models/__init__.py b/account_banking_sepa_credit_transfer/models/__init__.py index 105896fa3..3475860d2 100644 --- a/account_banking_sepa_credit_transfer/models/__init__.py +++ b/account_banking_sepa_credit_transfer/models/__init__.py @@ -2,3 +2,4 @@ from . import account_payment_method from . import account_payment_order +from . import account_payment_line diff --git a/account_banking_sepa_credit_transfer/models/account_payment_line.py b/account_banking_sepa_credit_transfer/models/account_payment_line.py new file mode 100644 index 000000000..009887250 --- /dev/null +++ b/account_banking_sepa_credit_transfer/models/account_payment_line.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +# © 2017 Akretion - Alexis de Lattre +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import models, fields + + +class AccountPaymentLine(models.Model): + _inherit = 'account.payment.line' + + # local_instrument 'INST' used for instant credit transfers + # which will begin on November 21st 2017, cf + # https://www.europeanpaymentscouncil.eu/document-library/ + # rulebooks/2017-sepa-instant-credit-transfer-rulebook + local_instrument = fields.Selection( + selection_add=[('INST', 'Instant Transfer')]) diff --git a/account_banking_sepa_credit_transfer/models/account_payment_order.py b/account_banking_sepa_credit_transfer/models/account_payment_order.py index 6e629112d..f656a3bb9 100644 --- a/account_banking_sepa_credit_transfer/models/account_payment_order.py +++ b/account_banking_sepa_credit_transfer/models/account_payment_order.py @@ -78,34 +78,37 @@ class AccountPaymentOrder(models.Model): transactions_count_a = 0 amount_control_sum_a = 0.0 lines_per_group = {} - # key = (requested_date, priority, local_instrument) + # key = (requested_date, priority, local_instrument, categ_purpose) # values = list of lines as object for line in self.bank_line_ids: priority = line.priority local_instrument = line.local_instrument + categ_purpose = line.category_purpose # The field line.date is the requested payment date # taking into account the 'date_prefered' setting # cf account_banking_payment_export/models/account_payment.py # in the inherit of action_open() - key = (line.date, priority, local_instrument) + key = (line.date, priority, local_instrument, categ_purpose) if key in lines_per_group: lines_per_group[key].append(line) else: lines_per_group[key] = [line] - for (requested_date, priority, local_instrument), lines in\ - lines_per_group.items(): + for (requested_date, priority, local_instrument, categ_purpose),\ + lines in lines_per_group.items(): # B. Payment info payment_info, nb_of_transactions_b, control_sum_b = \ self.generate_start_payment_info_block( pain_root, "self.name + '-' " "+ requested_date.replace('-', '') + '-' + priority + " - "'-' + local_instrument", - priority, local_instrument, False, requested_date, { + "'-' + local_instrument + '-' + category_purpose", + priority, local_instrument, categ_purpose, + False, requested_date, { 'self': self, 'priority': priority, 'requested_date': requested_date, 'local_instrument': local_instrument or 'NOinstr', + 'category_purpose': categ_purpose or 'NOcateg', }, gen_args) self.generate_party_block( payment_info, 'Dbtr', 'B', diff --git a/account_banking_sepa_direct_debit/models/account_payment_order.py b/account_banking_sepa_direct_debit/models/account_payment_order.py index 116c2e6db..3592437fe 100644 --- a/account_banking_sepa_direct_debit/models/account_payment_order.py +++ b/account_banking_sepa_direct_debit/models/account_payment_order.py @@ -68,6 +68,7 @@ class AccountPaymentOrder(models.Model): for line in self.bank_line_ids: transactions_count_a += 1 priority = line.priority + categ_purpose = line.category_purpose # The field line.date is the requested payment date # taking into account the 'date_prefered' setting # cf account_banking_payment_export/models/account_payment.py @@ -106,25 +107,27 @@ class AccountPaymentOrder(models.Model): line.mandate_id.recurrent_sequence_type assert seq_type_label is not False seq_type = seq_type_map[seq_type_label] - key = (line.date, priority, seq_type, scheme) + key = (line.date, priority, categ_purpose, seq_type, scheme) if key in lines_per_group: lines_per_group[key].append(line) else: lines_per_group[key] = [line] - for (requested_date, priority, sequence_type, scheme), lines in \ - lines_per_group.items(): + for (requested_date, priority, categ_purpose, sequence_type, scheme),\ + lines in lines_per_group.items(): # B. Payment info payment_info, nb_of_transactions_b, control_sum_b = \ self.generate_start_payment_info_block( pain_root, "self.name + '-' + " "sequence_type + '-' + requested_date.replace('-', '') " - "+ '-' + priority", - priority, scheme, sequence_type, requested_date, { + "+ '-' + priority + '-' + category_purpose", + priority, scheme, categ_purpose, + sequence_type, requested_date, { 'self': self, 'sequence_type': sequence_type, 'priority': priority, + 'category_purpose': categ_purpose or 'NOcateg', 'requested_date': requested_date, }, gen_args)