Start code factoring between SCT and SDD.

This commit is contained in:
Alexis de Lattre
2013-12-12 14:47:01 +01:00
parent 0340ceff0c
commit f377a391e8
7 changed files with 268 additions and 274 deletions

View File

@@ -23,3 +23,4 @@
from . import payment_line
from . import payment_mode
from . import company
from . import banking_export_pain

View File

@@ -27,6 +27,9 @@
'website': 'http://openerp-community-association.org/',
'category': 'Hidden',
'depends': ['account_banking_payment_export'],
'external_dependencies': {
'python': ['unidecode', 'lxml'],
},
'data': [
'payment_line_view.xml',
'payment_mode_view.xml',

View File

@@ -0,0 +1,186 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# PAIN Base module for OpenERP
# Copyright (C) 2013 Akretion (http://www.akretion.com)
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp.osv import orm
from openerp.tools.translate import _
from openerp.tools.safe_eval import safe_eval
from unidecode import unidecode
from lxml import etree
from openerp import tools
import logging
logger = logging.getLogger(__name__)
class banking_export_pain(orm.AbstractModel):
_name = 'banking.export.pain'
def _validate_iban(self, cr, uid, iban, context=None):
'''if IBAN is valid, returns IBAN
if IBAN is NOT valid, raises an error message'''
partner_bank_obj = self.pool.get('res.partner.bank')
if partner_bank_obj.is_iban_valid(cr, uid, iban, context=context):
return iban.replace(' ', '')
else:
raise orm.except_orm(
_('Error:'), _("This IBAN is not valid : %s") % iban)
def _prepare_field(
self, cr, uid, field_name, field_value, eval_ctx, max_size=0,
convert_to_ascii=False, context=None):
'''This function is designed to be inherited !'''
assert isinstance(eval_ctx, dict), 'eval_ctx must contain a dict'
try:
value = safe_eval(field_value, eval_ctx)
# SEPA uses XML ; XML = UTF-8 ; UTF-8 = support for all characters
# But we are dealing with banks...
# and many banks don't want non-ASCCI characters !
# cf section 1.4 "Character set" of the SEPA Credit Transfer
# Scheme Customer-to-bank guidelines
if convert_to_ascii:
value = unidecode(value)
except:
line = eval_ctx.get('line')
if line:
raise orm.except_orm(
_('Error:'),
_("Cannot compute the '%s' of the Payment Line with Invoice Reference '%s'.")
% (field_name, self.pool['account.invoice'].name_get(
cr, uid, [line.ml_inv_ref.id], context=context)[0][1]))
else:
raise orm.except_orm(
_('Error:'),
_("Cannot compute the '%s'.") % field_name)
if not isinstance(value, (str, unicode)):
raise orm.except_orm(
_('Field type error:'),
_("The type of the field '%s' is %s. It should be a string or unicode.")
% (field_name, type(value)))
if not value:
raise orm.except_orm(
_('Error:'),
_("The '%s' is empty or 0. It should have a non-null value.")
% field_name)
if max_size and len(value) > max_size:
value = value[0:max_size]
return value
def _validate_xml(self, cr, uid, xml_string, pain_xsd_file):
xsd_etree_obj = etree.parse(
tools.file_open(pain_xsd_file))
official_pain_schema = etree.XMLSchema(xsd_etree_obj)
try:
root_to_validate = etree.fromstring(xml_string)
official_pain_schema.assertValid(root_to_validate)
except Exception, e:
logger.warning(
"The XML file is invalid against the XML Schema Definition")
logger.warning(xml_string)
logger.warning(e)
raise orm.except_orm(
_('Error:'),
_('The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s')
% str(e))
return True
def generate_initiating_party_block(
self, cr, uid, parent_node, sepa_export, gen_args,
context=None):
my_company_name = self._prepare_field(
cr, uid, 'Company Name',
'sepa_export.payment_order_ids[0].mode.bank_id.partner_id.name',
{'sepa_export': sepa_export}, gen_args.get('name_maxsize'),
convert_to_ascii=gen_args.get('convert_to_ascii'), context=context)
initiating_party_1_8 = etree.SubElement(parent_node, 'InitgPty')
initiating_party_name = etree.SubElement(initiating_party_1_8, 'Nm')
initiating_party_name.text = my_company_name
initiating_party_identifier = self.pool['res.company'].\
_get_initiating_party_identifier(
cr, uid, sepa_export.payment_order_ids[0].company_id.id,
context=context)
initiating_party_issuer = \
sepa_export.payment_order_ids[0].company_id.initiating_party_issuer
if initiating_party_identifier and initiating_party_issuer:
iniparty_id = etree.SubElement(initiating_party_1_8, 'Id')
iniparty_org_id = etree.SubElement(iniparty_id, 'OrgId')
iniparty_org_other = etree.SubElement(iniparty_org_id, 'Othr')
iniparty_org_other_id = etree.SubElement(iniparty_org_other, 'Id')
iniparty_org_other_id.text = initiating_party_identifier
iniparty_org_other_issuer = etree.SubElement(
iniparty_org_other, 'Issr')
iniparty_org_other_issuer.text = initiating_party_issuer
return True
def generate_party_bic(
self, cr, uid, parent_node, party_type, party_type_label, bic,
eval_ctx, gen_args, context=None):
'''Generate the piece of the XML file corresponding to BIC
This code is mutualized between TRF and DD'''
party_agent = etree.SubElement(parent_node, '%sAgt' % party_type)
party_agent_institution = etree.SubElement(
party_agent, 'FinInstnId')
party_agent_bic = etree.SubElement(
party_agent_institution, gen_args.get('bic_xml_tag'))
party_agent_bic.text = self._prepare_field(
cr, uid, '%s BIC' % party_type_label, bic, eval_ctx,
convert_to_ascii=gen_args.get('convert_to_ascii'), context=context)
return True
def generate_party_block(
self, cr, uid, parent_node, party_type, order, name, iban, bic,
eval_ctx, gen_args, context=None):
'''Generate the piece of the XML file corresponding to Name+IBAN+BIC
This code is mutualized between TRF and DD'''
assert order in ('B', 'C'), "Order can be 'B' or 'C'"
if party_type == 'Cdtr':
party_type_label = 'Creditor'
elif party_type == 'Dbtr':
party_type_label = 'Debtor'
# At C level, the order is : BIC, Name, IBAN
# At B level, the order is : Name, IBAN, BIC
if order == 'C':
self.generate_party_bic(
cr, uid, parent_node, party_type, party_type_label, bic,
eval_ctx, gen_args, context=context)
party = etree.SubElement(parent_node, party_type)
party_name = etree.SubElement(party, 'Nm')
party_name.text = self._prepare_field(
cr, uid, '%s Name' % party_type_label, name, eval_ctx,
gen_args.get('name_maxsize'),
convert_to_ascii=gen_args.get('convert_to_ascii'), context=context)
party_account = etree.SubElement(
parent_node, '%sAcct' % party_type)
party_account_id = etree.SubElement(party_account, 'Id')
party_account_iban = etree.SubElement(
party_account_id, 'IBAN')
piban = self._prepare_field(
cr, uid, '%s IBAN' % party_type_label, iban, eval_ctx,
convert_to_ascii=gen_args.get('convert_to_ascii'),
context=context)
viban = self._validate_iban(cr, uid, piban, context=context)
party_account_iban.text = viban
if order == 'B':
self.generate_party_bic(
cr, uid, parent_node, party_type, party_type_label, bic,
eval_ctx, gen_args, context=context)
return True

View File

@@ -38,7 +38,10 @@ class res_company(orm.Model):
self, cr, uid, company_id, context=None):
'''This function is designed to be inherited by localization modules'''
assert isinstance(company_id, int), 'Only one company ID'
return False
# TODO REMOOOOOOOOOOOOOOOOOOOVE BEFORE COMMIT
return self.browse(cr, uid, company_id).partner_id.vat
#return False
def _initiating_party_issuer_default(self, cr, uid, context=None):
'''This function is designed to be inherited by localization modules'''

View File

@@ -36,6 +36,7 @@ _logger = logging.getLogger(__name__)
class banking_export_sepa_wizard(orm.TransientModel):
_name = 'banking.export.sepa.wizard'
_inherit = ['banking.export.pain']
_description = 'Export SEPA Credit Transfer File'
_columns = {
@@ -76,16 +77,6 @@ class banking_export_sepa_wizard(orm.TransientModel):
'state': 'create',
}
def _validate_iban(self, cr, uid, iban, context=None):
'''if IBAN is valid, returns IBAN
if IBAN is NOT valid, raises an error message'''
partner_bank_obj = self.pool.get('res.partner.bank')
if partner_bank_obj.is_iban_valid(cr, uid, iban, context=context):
return iban.replace(' ', '')
else:
raise orm.except_orm(
_('Error:'), _("This IBAN is not valid : %s") % iban)
def create(self, cr, uid, vals, context=None):
payment_order_ids = context.get('active_ids', [])
vals.update({
@@ -94,46 +85,6 @@ class banking_export_sepa_wizard(orm.TransientModel):
return super(banking_export_sepa_wizard, self).create(
cr, uid, vals, context=context)
def _prepare_field(
self, cr, uid, field_name, field_value, eval_ctx, max_size=0,
convert_to_ascii=False, context=None):
'''This function is designed to be inherited !'''
assert isinstance(eval_ctx, dict), 'eval_ctx must contain a dict'
try:
value = safe_eval(field_value, eval_ctx)
# SEPA uses XML ; XML = UTF-8 ; UTF-8 = support for all characters
# But we are dealing with banks...
# and many banks don't want non-ASCCI characters !
# cf section 1.4 "Character set" of the SEPA Credit Transfer
# Scheme Customer-to-bank guidelines
if convert_to_ascii:
value = unidecode(value)
except:
line = eval_ctx.get('line')
if line:
raise orm.except_orm(
_('Error:'),
_("Cannot compute the '%s' of the Payment Line with Invoice Reference '%s'.")
% (field_name, self.pool['account.invoice'].name_get(
cr, uid, [line.ml_inv_ref.id], context=context)[0][1]))
else:
raise orm.except_orm(
_('Error:'),
_("Cannot compute the '%s'.") % field_name)
if not isinstance(value, (str, unicode)):
raise orm.except_orm(
_('Field type error:'),
_("The type of the field '%s' is %s. It should be a string or unicode.")
% (field_name, type(value)))
if not value:
raise orm.except_orm(
_('Error:'),
_("The '%s' is empty or 0. It should have a non-null value.")
% field_name)
if max_size and len(value) > max_size:
value = value[0:max_size]
return value
def _prepare_export_sepa(
self, cr, uid, sepa_export, total_amount, transactions_count,
xml_string, context=None):
@@ -148,27 +99,6 @@ class banking_export_sepa_wizard(orm.TransientModel):
],
}
def _validate_xml(self, cr, uid, xml_string, pain_flavor):
xsd_etree_obj = etree.parse(
tools.file_open(
'account_banking_sepa_credit_transfer/data/%s.xsd'
% pain_flavor))
official_pain_schema = etree.XMLSchema(xsd_etree_obj)
try:
root_to_validate = etree.fromstring(xml_string)
official_pain_schema.assertValid(root_to_validate)
except Exception, e:
_logger.warning(
"The XML file is invalid against the XML Schema Definition")
_logger.warning(xml_string)
_logger.warning(e)
raise orm.except_orm(
_('Error:'),
_('The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s')
% str(e))
return True
def create_sepa(self, cr, uid, ids, context=None):
'''
Creates the SEPA Credit Transfer file. That's the important code !
@@ -210,6 +140,12 @@ class banking_export_sepa_wizard(orm.TransientModel):
_("Payment Type Code '%s' is not supported. The only Payment Type Codes supported for SEPA Credit Transfers are 'pain.001.001.02', 'pain.001.001.03', 'pain.001.001.04' and 'pain.001.001.05'.")
% pain_flavor)
gen_args = {
'bic_xml_tag': bic_xml_tag,
'name_maxsize': name_maxsize,
'convert_to_ascii': convert_to_ascii,
}
pain_ns = {
'xsi': 'http://www.w3.org/2001/XMLSchema-instance',
None: 'urn:iso:std:iso:20022:tech:xsd:%s' % pain_flavor,
@@ -250,24 +186,9 @@ class banking_export_sepa_wizard(orm.TransientModel):
if pain_flavor == 'pain.001.001.02':
grouping = etree.SubElement(group_header_1_0, 'Grpg')
grouping.text = 'GRPD'
initiating_party_1_8 = etree.SubElement(group_header_1_0, 'InitgPty')
initiating_party_name = etree.SubElement(initiating_party_1_8, 'Nm')
initiating_party_name.text = my_company_name
initiating_party_identifier = self.pool['res.company'].\
_get_initiating_party_identifier(
cr, uid, sepa_export.payment_order_ids[0].company_id.id,
context=context)
initiating_party_issuer = \
sepa_export.payment_order_ids[0].company_id.initiating_party_issuer
if initiating_party_identifier and initiating_party_issuer:
iniparty_id = etree.SubElement(initiating_party_1_8, 'Id')
iniparty_org_id = etree.SubElement(iniparty_id, 'OrgId')
iniparty_org_other = etree.SubElement(iniparty_org_id, 'Othr')
iniparty_org_other_id = etree.SubElement(iniparty_org_other, 'Id')
iniparty_org_other_id.text = initiating_party_identifier
iniparty_org_other_issuer = etree.SubElement(
iniparty_org_other, 'Issr')
iniparty_org_other_issuer.text = initiating_party_issuer
self.generate_initiating_party_block(
cr, uid, group_header_1_0, sepa_export, gen_args,
context=context)
transactions_count_1_6 = 0
total_amount = 0.0
@@ -339,33 +260,14 @@ class banking_export_sepa_wizard(orm.TransientModel):
requested_exec_date_2_17 = etree.SubElement(
payment_info_2_0, 'ReqdExctnDt')
requested_exec_date_2_17.text = requested_exec_date
debtor_2_19 = etree.SubElement(payment_info_2_0, 'Dbtr')
debtor_name = etree.SubElement(debtor_2_19, 'Nm')
debtor_name.text = my_company_name
debtor_account_2_20 = etree.SubElement(
payment_info_2_0, 'DbtrAcct')
debtor_account_id = etree.SubElement(debtor_account_2_20, 'Id')
debtor_account_iban = etree.SubElement(debtor_account_id, 'IBAN')
debtor_account_iban.text = self._validate_iban(
cr, uid, self._prepare_field(
cr, uid, 'Company IBAN',
'sepa_export.payment_order_ids[0].mode.bank_id.acc_number',
{'sepa_export': sepa_export},
convert_to_ascii=convert_to_ascii, context=context),
context=context)
debtor_agent_2_21 = etree.SubElement(payment_info_2_0, 'DbtrAgt')
debtor_agent_institution = etree.SubElement(
debtor_agent_2_21, 'FinInstnId')
debtor_agent_bic = etree.SubElement(
debtor_agent_institution, bic_xml_tag)
# TODO validate BIC with pattern
# [A-Z]{6,6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3,3}){0,1}
# because OpenERP doesn't have a constraint on BIC
debtor_agent_bic.text = self._prepare_field(
cr, uid, 'Company BIC',
self.generate_party_block(
cr, uid, payment_info_2_0, 'Dbtr', 'B',
'sepa_export.payment_order_ids[0].mode.bank_id.partner_id.name',
'sepa_export.payment_order_ids[0].mode.bank_id.acc_number',
'sepa_export.payment_order_ids[0].mode.bank_id.bank.bic',
{'sepa_export': sepa_export},
convert_to_ascii=convert_to_ascii, context=context)
gen_args, context=context)
charge_bearer_2_24 = etree.SubElement(payment_info_2_0, 'ChrgBr')
charge_bearer_2_24.text = sepa_export.charge_bearer
@@ -396,40 +298,19 @@ class banking_export_sepa_wizard(orm.TransientModel):
instructed_amount_2_43.text = '%.2f' % line.amount_currency
amount_control_sum_1_7 += line.amount_currency
amount_control_sum_2_5 += line.amount_currency
creditor_agent_2_77 = etree.SubElement(
credit_transfer_transaction_info_2_27, 'CdtrAgt')
creditor_agent_institution = etree.SubElement(
creditor_agent_2_77, 'FinInstnId')
if not line.bank_id:
raise orm.except_orm(
_('Error:'),
_("Missing Bank Account on invoice '%s' (payment order line reference '%s').")
% (line.ml_inv_ref.number, line.name))
creditor_agent_bic = etree.SubElement(
creditor_agent_institution, bic_xml_tag)
creditor_agent_bic.text = self._prepare_field(
cr, uid, 'Creditor BIC', 'line.bank_id.bank.bic',
{'line': line}, convert_to_ascii=convert_to_ascii,
context=context)
creditor_2_79 = etree.SubElement(
credit_transfer_transaction_info_2_27, 'Cdtr')
creditor_name = etree.SubElement(creditor_2_79, 'Nm')
creditor_name.text = self._prepare_field(
cr, uid, 'Creditor Name', 'line.partner_id.name',
{'line': line}, name_maxsize,
convert_to_ascii=convert_to_ascii, context=context)
creditor_account_2_80 = etree.SubElement(
credit_transfer_transaction_info_2_27, 'CdtrAcct')
creditor_account_id = etree.SubElement(
creditor_account_2_80, 'Id')
creditor_account_iban = etree.SubElement(
creditor_account_id, 'IBAN')
creditor_account_iban.text = self._validate_iban(
cr, uid, self._prepare_field(
cr, uid, 'Creditor IBAN',
'line.bank_id.acc_number', {'line': line},
convert_to_ascii=convert_to_ascii, context=context),
context=context)
self.generate_party_block(
cr, uid, credit_transfer_transaction_info_2_27, 'Cdtr', 'C',
'line.partner_id.name',
'line.bank_id.acc_number',
'line.bank_id.bank.bic',
{'line': line}, gen_args, context=context)
remittance_info_2_91 = etree.SubElement(
credit_transfer_transaction_info_2_27, 'RmtInf')
if line.state == 'normal':
@@ -498,7 +379,9 @@ class banking_export_sepa_wizard(orm.TransientModel):
"Generated SEPA Credit Transfer XML file in format %s below"
% pain_flavor)
_logger.debug(xml_string)
self._validate_xml(cr, uid, xml_string, pain_flavor)
pain_xsd_file = \
'account_banking_sepa_credit_transfer/data/%s.xsd' % pain_flavor
self._validate_xml(cr, uid, xml_string, pain_xsd_file)
# CREATE the banking.export.sepa record
file_id = self.pool.get('banking.export.sepa').create(

View File

@@ -26,7 +26,7 @@
'author': 'Akretion',
'website': 'http://www.akretion.com',
'category': 'Banking addons',
'depends': ['account_direct_debit'],
'depends': ['account_direct_debit', 'account_banking_pain_base'],
'external_dependencies': {
'python': ['unidecode', 'lxml'],
},

View File

@@ -36,6 +36,7 @@ _logger = logging.getLogger(__name__)
class banking_export_sdd_wizard(orm.TransientModel):
_name = 'banking.export.sdd.wizard'
_inherit = ['banking.export.pain']
_description = 'Export SEPA Direct Debit File'
_columns = {
'state': fields.selection([
@@ -78,16 +79,6 @@ class banking_export_sdd_wizard(orm.TransientModel):
'state': 'create',
}
def _validate_iban(self, cr, uid, iban, context=None):
'''if IBAN is valid, returns IBAN
if IBAN is NOT valid, raises an error message'''
partner_bank_obj = self.pool.get('res.partner.bank')
if partner_bank_obj.is_iban_valid(cr, uid, iban, context=context):
return iban.replace(' ', '')
else:
raise orm.except_orm(
_('Error:'), _("This IBAN is not valid : %s") % iban)
def create(self, cr, uid, vals, context=None):
payment_order_ids = context.get('active_ids', [])
vals.update({
@@ -96,44 +87,6 @@ class banking_export_sdd_wizard(orm.TransientModel):
return super(banking_export_sdd_wizard, self).create(
cr, uid, vals, context=context)
def _prepare_field(
self, cr, uid, field_name, field_value, eval_ctx, max_size=0,
context=None):
'''This function is designed to be inherited !'''
assert isinstance(eval_ctx, dict), 'eval_ctx must contain a dict'
try:
# SEPA uses XML ; XML = UTF-8 ; UTF-8 = support for all characters
# But we are dealing with banks...
# and many banks don't want non-ASCCI characters !
# cf section 1.4 "Character set" of the SEPA Core Direct Debit
# Customer-to-bank implementation guidelines
value = unidecode(safe_eval(field_value, eval_ctx))
except:
line = eval_ctx.get('line')
if line:
raise orm.except_orm(
_('Error:'),
_("Cannot compute the '%s' of the Payment Line with Invoice Reference '%s'.")
% (field_name, self.pool['account.invoice'].name_get(
cr, uid, [line.ml_inv_ref.id], context=context)[0][1]))
else:
raise orm.except_orm(
_('Error:'),
_("Cannot compute the '%s'.") % field_name)
if not isinstance(value, (str, unicode)):
raise orm.except_orm(
_('Field type error:'),
_("The type of the field '%s' is %s. It should be a string or unicode.")
% (field_name, type(value)))
if not value:
raise orm.except_orm(
_('Error:'),
_("The '%s' is empty or 0. It should have a non-null value.")
% field_name)
if max_size and len(value) > max_size:
value = value[0:max_size]
return value
def _prepare_export_sepa(
self, cr, uid, sepa_export, total_amount, transactions_count,
xml_string, context=None):
@@ -149,26 +102,6 @@ class banking_export_sdd_wizard(orm.TransientModel):
],
}
def _validate_xml(self, cr, uid, xml_string, pain_flavor):
xsd_etree_obj = etree.parse(
tools.file_open(
'account_banking_sepa_direct_debit/data/%s.xsd'
% pain_flavor))
official_pain_schema = etree.XMLSchema(xsd_etree_obj)
try:
root_to_validate = etree.fromstring(xml_string)
official_pain_schema.assertValid(root_to_validate)
except Exception, e:
_logger.warning(
"The XML file is invalid against the XML Schema Definition")
_logger.warning(xml_string)
_logger.warning(e)
raise orm.except_orm(
_('Error:'),
_('The generated XML file is not valid against the official XML Schema Definition. The generated XML file and the full error have been written in the server logs. Here is the error, which may give you an idea on the cause of the problem : %s')
% str(e))
return True
def _get_previous_bank(self, cr, uid, payline, context=None):
payline_obj = self.pool['payment.line']
@@ -203,6 +136,8 @@ class banking_export_sdd_wizard(orm.TransientModel):
sepa_export = self.browse(cr, uid, ids[0], context=context)
pain_flavor = sepa_export.payment_order_ids[0].mode.type.code
convert_to_ascii = \
sepa_export.payment_order_ids[0].mode.convert_to_ascii
if pain_flavor == 'pain.008.001.02':
bic_xml_tag = 'BIC'
name_maxsize = 70
@@ -217,6 +152,13 @@ class banking_export_sdd_wizard(orm.TransientModel):
root_xml_tag = 'CstmrDrctDbtInitn'
else:
raise orm.except_orm(_('Error:'), _("Payment Type Code '%s' is not supported. The only Payment Type Code supported for SEPA Direct Debit are 'pain.008.001.02', 'pain.008.001.03' and 'pain.008.001.04'.") % pain_flavor)
gen_args = {
'bic_xml_tag': bic_xml_tag,
'name_maxsize': name_maxsize,
'convert_to_ascii': convert_to_ascii,
}
if sepa_export.requested_collec_date:
my_requested_collec_date = sepa_export.requested_collec_date
else:
@@ -243,15 +185,16 @@ class banking_export_sdd_wizard(orm.TransientModel):
message_identification_1_1.text = self._prepare_field(
cr, uid, 'Message Identification',
'sepa_export.payment_order_ids[0].reference',
{'sepa_export': sepa_export}, 35, context=context)
{'sepa_export': sepa_export}, 35,
convert_to_ascii=convert_to_ascii, context=context)
creation_date_time_1_2 = etree.SubElement(group_header_1_0, 'CreDtTm')
creation_date_time_1_2.text = datetime.strftime(
datetime.today(), '%Y-%m-%dT%H:%M:%S')
nb_of_transactions_1_6 = etree.SubElement(group_header_1_0, 'NbOfTxs')
control_sum_1_7 = etree.SubElement(group_header_1_0, 'CtrlSum')
initiating_party_1_8 = etree.SubElement(group_header_1_0, 'InitgPty')
initiating_party_name = etree.SubElement(initiating_party_1_8, 'Nm')
initiating_party_name.text = my_company_name
self.generate_initiating_party_block(
cr, uid, group_header_1_0, sepa_export, gen_args,
context=context)
transactions_count_1_6 = 0
total_amount = 0.0
@@ -312,7 +255,7 @@ class banking_export_sdd_wizard(orm.TransientModel):
cr, uid, 'Payment Information Identification',
"sequence_type + '-' + sepa_export.payment_order_ids[0].reference",
{'sepa_export': sepa_export, 'sequence_type': sequence_type},
35, context=context)
35, convert_to_ascii=convert_to_ascii, context=context)
payment_method_2_2 = etree.SubElement(payment_info_2_0, 'PmtMtd')
payment_method_2_2.text = 'DD'
# batch_booking is in "Payment Info" with pain.008.001.02/03
@@ -347,30 +290,14 @@ class banking_export_sdd_wizard(orm.TransientModel):
requested_collec_date_2_18 = etree.SubElement(
payment_info_2_0, 'ReqdColltnDt')
requested_collec_date_2_18.text = my_requested_collec_date
creditor_2_19 = etree.SubElement(payment_info_2_0, 'Cdtr')
creditor_name = etree.SubElement(creditor_2_19, 'Nm')
creditor_name.text = my_company_name
creditor_account_2_20 = etree.SubElement(
payment_info_2_0, 'CdtrAcct')
creditor_account_id = etree.SubElement(creditor_account_2_20, 'Id')
creditor_account_iban = etree.SubElement(
creditor_account_id, 'IBAN')
creditor_account_iban.text = self._validate_iban(
cr, uid, self._prepare_field(
cr, uid, 'Company IBAN',
'sepa_export.payment_order_ids[0].mode.bank_id.acc_number',
{'sepa_export': sepa_export}, context=context),
context=context)
creditor_agent_2_21 = etree.SubElement(payment_info_2_0, 'CdtrAgt')
creditor_agent_institution = etree.SubElement(
creditor_agent_2_21, 'FinInstnId')
creditor_agent_bic = etree.SubElement(
creditor_agent_institution, bic_xml_tag)
creditor_agent_bic.text = self._prepare_field(
cr, uid, 'Company BIC',
self.generate_party_block(
cr, uid, payment_info_2_0, 'Cdtr', 'B',
'sepa_export.payment_order_ids[0].mode.bank_id.partner_id.name',
'sepa_export.payment_order_ids[0].mode.bank_id.acc_number',
'sepa_export.payment_order_ids[0].mode.bank_id.bank.bic',
{'sepa_export': sepa_export}, context=context)
{'sepa_export': sepa_export},
gen_args, context=context)
charge_bearer_2_24 = etree.SubElement(payment_info_2_0, 'ChrgBr')
charge_bearer_2_24.text = sepa_export.charge_bearer
@@ -385,7 +312,8 @@ class banking_export_sdd_wizard(orm.TransientModel):
csi_other_id.text = self._prepare_field(
cr, uid, 'SEPA Creditor Identifier',
'sepa_export.payment_order_ids[0].company_id.sepa_creditor_identifier',
{'sepa_export': sepa_export}, context=context)
{'sepa_export': sepa_export},
convert_to_ascii=convert_to_ascii, context=context)
csi_scheme_name = etree.SubElement(csi_other, 'SchmeNm')
csi_scheme_name_proprietary = etree.SubElement(
csi_scheme_name, 'Prtry')
@@ -404,10 +332,12 @@ class banking_export_sdd_wizard(orm.TransientModel):
payment_identification_2_29, 'EndToEndId')
end2end_identification_2_31.text = self._prepare_field(
cr, uid, 'End to End Identification', 'line.name',
{'line': line}, 35, context=context)
{'line': line}, 35,
convert_to_ascii=convert_to_ascii, context=context)
currency_name = self._prepare_field(
cr, uid, 'Currency Code', 'line.currency.name',
{'line': line}, 3, context=context)
{'line': line}, 3, convert_to_ascii=convert_to_ascii,
context=context)
instructed_amount_2_44 = etree.SubElement(
dd_transaction_info_2_28, 'InstdAmt', Ccy=currency_name)
instructed_amount_2_44.text = '%.2f' % line.amount_currency
@@ -422,13 +352,15 @@ class banking_export_sdd_wizard(orm.TransientModel):
mandate_identification_2_48.text = self._prepare_field(
cr, uid, 'Unique Mandate Reference',
'line.sdd_mandate_id.unique_mandate_reference',
{'line': line}, 35, context=context)
{'line': line}, 35,
convert_to_ascii=convert_to_ascii, context=context)
mandate_signature_date_2_49 = etree.SubElement(
mandate_related_info_2_47, 'DtOfSgntr')
mandate_signature_date_2_49.text = self._prepare_field(
cr, uid, 'Mandate Signature Date',
'line.sdd_mandate_id.signature_date',
{'line': line}, 10, context=context)
{'line': line}, 10,
convert_to_ascii=convert_to_ascii, context=context)
if (sequence_type == 'FRST'
and line.sdd_mandate_id.last_debit_date):
previous_bank = self._get_previous_bank(
@@ -451,6 +383,7 @@ class banking_export_sdd_wizard(orm.TransientModel):
cr, uid, 'Original Debtor Account',
'previous_bank.acc_number',
{'previous_bank': previous_bank},
convert_to_ascii=convert_to_ascii,
context=context),
context=context)
else:
@@ -464,6 +397,7 @@ class banking_export_sdd_wizard(orm.TransientModel):
cr, uid, 'Original Debtor Agent',
'previous_bank.bank.bic',
{'previous_bank': previous_bank},
convert_to_ascii=convert_to_ascii,
context=context)
ori_debtor_agent_other = etree.SubElement(
ori_debtor_agent_institution, 'Othr')
@@ -472,32 +406,13 @@ class banking_export_sdd_wizard(orm.TransientModel):
ori_debtor_agent_other_id.text = 'SMNDA'
# SMNDA = Same Mandate New Debtor Agent
debtor_agent_2_70 = etree.SubElement(
dd_transaction_info_2_28, 'DbtrAgt')
debtor_agent_institution = etree.SubElement(
debtor_agent_2_70, 'FinInstnId')
debtor_agent_bic = etree.SubElement(
debtor_agent_institution, bic_xml_tag)
debtor_agent_bic.text = self._prepare_field(
cr, uid, 'Customer BIC', 'line.bank_id.bank.bic',
{'line': line}, context=context)
debtor_2_72 = etree.SubElement(
dd_transaction_info_2_28, 'Dbtr')
debtor_name = etree.SubElement(debtor_2_72, 'Nm')
debtor_name.text = self._prepare_field(
cr, uid, 'Customer Name', 'line.partner_id.name',
{'line': line}, name_maxsize, context=context)
debtor_account_2_73 = etree.SubElement(
dd_transaction_info_2_28, 'DbtrAcct')
debtor_account_id = etree.SubElement(debtor_account_2_73, 'Id')
debtor_account_iban = etree.SubElement(
debtor_account_id, 'IBAN')
debtor_account_iban.text = self._validate_iban(
cr, uid, self._prepare_field(
cr, uid, 'Customer IBAN',
'line.bank_id.acc_number', {'line': line},
context=context),
context=context)
self.generate_party_block(
cr, uid, dd_transaction_info_2_28, 'Dbtr', 'C',
'line.partner_id.name',
'line.bank_id.acc_number',
'line.bank_id.bank.bic',
{'line': line}, gen_args, context=context)
remittance_info_2_88 = etree.SubElement(
dd_transaction_info_2_28, 'RmtInf')
# switch to Structured (Strdr) ? If we do it, beware that the format is not the same between pain 02 and pain 03
@@ -505,7 +420,8 @@ class banking_export_sdd_wizard(orm.TransientModel):
remittance_info_2_88, 'Ustrd')
remittance_info_unstructured_2_89.text = self._prepare_field(
cr, uid, 'Remittance Information', 'line.communication',
{'line': line}, 140, context=context)
{'line': line}, 140, convert_to_ascii=convert_to_ascii,
context=context)
nb_of_transactions_2_4.text = str(transactions_count_2_4)
control_sum_2_5.text = '%.2f' % amount_control_sum_2_5
nb_of_transactions_1_6.text = str(transactions_count_1_6)
@@ -516,7 +432,9 @@ class banking_export_sdd_wizard(orm.TransientModel):
_logger.debug(
"Generated SDD XML file in format %s below" % pain_flavor)
_logger.debug(xml_string)
self._validate_xml(cr, uid, xml_string, pain_flavor)
pain_xsd_file = \
'account_banking_sepa_direct_debit/data/%s.xsd' % pain_flavor
self._validate_xml(cr, uid, xml_string, pain_xsd_file)
# CREATE the banking.export.sepa record
file_id = self.pool.get('banking.export.sdd').create(