openerp-community-reviewer team mailing list archive
-
openerp-community-reviewer team
-
Mailing list archive
-
Message #00719
[Merge] lp:~luc-demeyer/account-financial-tools/7.0-account_pain into lp:account-financial-tools
Luc De Meyer (Noviat) has proposed merging lp:~luc-demeyer/account-financial-tools/7.0-account_pain into lp:account-financial-tools.
Requested reviews:
Account Core Editors (account-core-editors)
For more details, see:
https://code.launchpad.net/~luc-demeyer/account-financial-tools/7.0-account_pain/+merge/192256
add support for SEPA payments (ISO 20022)
--
https://code.launchpad.net/~luc-demeyer/account-financial-tools/7.0-account_pain/+merge/192256
Your team Account Core Editors is requested to review the proposed merge of lp:~luc-demeyer/account-financial-tools/7.0-account_pain into lp:account-financial-tools.
=== added directory 'account_pain'
=== added file 'account_pain/README.txt'
--- account_pain/README.txt 1970-01-01 00:00:00 +0000
+++ account_pain/README.txt 2013-10-22 22:00:27 +0000
@@ -0,0 +1,3 @@
+Installation tips
+=================
+
=== added file 'account_pain/__init__.py'
--- account_pain/__init__.py 1970-01-01 00:00:00 +0000
+++ account_pain/__init__.py 2013-10-22 22:00:27 +0000
@@ -0,0 +1,25 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+#
+# Copyright (c) 2013 Noviat nv/sa (www.noviat.com). All rights reserved.
+#
+# 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/>.
+#
+##############################################################################
+
+import account_payment
+import account_move_line
+import wizard
=== added file 'account_pain/__openerp__.py'
--- account_pain/__openerp__.py 1970-01-01 00:00:00 +0000
+++ account_pain/__openerp__.py 2013-10-22 22:00:27 +0000
@@ -0,0 +1,65 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+#
+# Copyright (c) 2013 Noviat nv/sa (www.noviat.com). All rights reserved.
+#
+# 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/>.
+#
+##############################################################################
+{
+ 'name': 'ISO 20022 XML payment files',
+ 'version': '0.1',
+ 'license': 'AGPL-3',
+ 'author': 'Noviat',
+ 'category': 'Generic Modules/Accounting',
+ 'description': """
+
+ISO 20022 XML payment files
+===========================
+
+Module to generate Customer Credit Transfer Initiation message ISO 20022 XML - pain.001.001.03.
+
+This module implements the following subset of the ISO 20022 specifications:
+
+European Credit Transfers:
+--------------------------
+* debtor and creditor account in SEPA countries
+* debtor account in Company currency
+* creditor account in Company currency
+* creditor account identified by BIC & IBAN
+* support for single payments
+
+The module also prohibits the removal of a confirmed Payment Order.
+Such a removal is still possible via the 'Undo Payment' button available to users of the 'Accounting / Manager' group.
+
+Features targeted for the Belgian market (cf. febelfin guidelines):
+
+* creditor account identified by IBAN (without BIC) for BE IBAN accounts
+* support for belgian structured communication format
+* by default, the right part of the VAT number (KBO/BCE number) is used to identify the Initiating Party
+
+ """,
+ 'depends': ['account','base_iban', 'account_payment'],
+ 'demo_xml': [],
+ 'init_xml': [],
+ 'update_xml' : [
+# 'security/ir.model.access.csv',
+ 'account_pain_wizard.xml',
+ 'account_payment_view.xml',
+ ],
+ 'active': False,
+ 'installable': True,
+}
=== added file 'account_pain/account_move_line.py'
--- account_pain/account_move_line.py 1970-01-01 00:00:00 +0000
+++ account_pain/account_move_line.py 2013-10-22 22:00:27 +0000
@@ -0,0 +1,104 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+#
+# Copyright (c) 2013 Noviat nv/sa (www.noviat.com). All rights reserved.
+#
+# 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.tools.translate import _
+from openerp.osv import fields, osv
+from operator import itemgetter
+import logging
+_logger = logging.getLogger(__name__)
+
+class account_move_line(osv.osv):
+ _inherit = "account.move.line"
+
+ def amount_to_pay(self, cr, uid, ids, name, arg={}, context=None):
+ """ Return the amount still to pay regarding all the payment orders
+ (excepting cancelled orders)"""
+ if not ids:
+ return {}
+ amounts_residual = self.read(cr, uid, ids, ['amount_residual'], context=context)
+ cr.execute("""SELECT ml.id,
+ (SELECT coalesce(sum(amount_currency),0)
+ FROM payment_line pl
+ INNER JOIN payment_order po
+ ON (pl.order_id = po.id)
+ WHERE move_line_id = ml.id
+ AND po.state != 'cancel') AS pl_amount
+ FROM account_move_line ml
+ WHERE id IN %s""", (tuple(ids),))
+ amounts_paylines = dict(cr.fetchall())
+ amounts_to_pay = {}
+ for entry in amounts_residual:
+ k = entry['id']
+ v = entry['amount_residual'] - amounts_paylines[k]
+ amounts_to_pay[k] = v
+ return amounts_to_pay
+
+ def _to_pay_search(self, cr, uid, obj, name, args, context=None):
+ if not args:
+ return []
+ if not context: context={}
+ context['all_fiscalyear'] = True
+ line_obj = self.pool.get('account.move.line')
+ query = line_obj._query_get(cr, uid, context={})
+ query += 'AND l.blocked = False '
+ where = ' and '.join(map(lambda x: '''(SELECT
+ CASE WHEN l.amount_currency < 0
+ THEN - l.amount_currency
+ ELSE l.credit
+ END - coalesce(sum(pl.amount_currency), 0)
+ FROM payment_line pl
+ INNER JOIN payment_order po ON (pl.order_id = po.id)
+ WHERE move_line_id = l.id
+ AND po.state != 'cancel'
+ ) %(operator)s %%s ''' % {'operator': x[1]}, args))
+ sql_args = tuple(map(itemgetter(2), args))
+
+ cr.execute(('''SELECT id
+ FROM account_move_line l
+ WHERE account_id IN (select id
+ FROM account_account
+ WHERE type in %s AND active)
+ AND reconcile_id IS null
+ AND credit > 0
+ AND ''' + where + ' AND ' + query), (('payable','receivable'),)+sql_args ) # fix Noviat to include sale refunds
+
+ res = cr.fetchall()
+ if not res:
+ return [('id', '=', '0')]
+ return [('id', 'in', map(lambda x:x[0], res))]
+
+ _columns = {
+ 'amount_to_pay': fields.function(amount_to_pay, method=True,
+ type='float', string='Amount to pay', fnct_search=_to_pay_search),
+ }
+
+ def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
+ if view_type == 'tree':
+ mod_obj = self.pool.get('ir.model.data')
+ if context is None:
+ context = {}
+ if context.get('account_payment', False):
+ model_data_ids = mod_obj.search(cr, uid,[('model', '=', 'ir.ui.view'), ('name', '=', 'view_move_line_tree_account_pain')], context=context)
+ view_id = mod_obj.read(cr, uid, model_data_ids, fields=['res_id'], context=context)[0]['res_id']
+ return super(account_move_line, self).fields_view_get(cr, uid, view_id, view_type, context=context, toolbar=toolbar, submenu=submenu)
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
=== added file 'account_pain/account_pain_wizard.xml'
--- account_pain/account_pain_wizard.xml 1970-01-01 00:00:00 +0000
+++ account_pain/account_pain_wizard.xml 2013-10-22 22:00:27 +0000
@@ -0,0 +1,36 @@
+<?xml version="1.0" ?>
+<openerp>
+ <data>
+
+ <record id="account_pain_save_view" model="ir.ui.view">
+ <field name="name">ISO 20022 payment file</field>
+ <field name="model">account.pain.create</field>
+ <field name="priority">1</field>
+ <field name="arch" type="xml">
+ <form string="The ISO 20022 payment file has been created" version="7.0">
+ <p>Click on link below to download the XML File</p>
+ <p>
+ <b>
+ <field name="pain_data" readonly="1" filename="pain_fname"/>
+ <field name="pain_fname" invisible="1"/>
+ </b>
+ </p>
+ <separator colspan="4"/>
+ <field name="note" colspan="4" attrs="{'invisible':[('note','=',False)]}"/>
+ <separator colspan="4"/>
+ </form>
+ </field>
+ </record>
+
+ <record id="action_account_pain_create" model="ir.actions.act_window">
+ <field name="name">The ISO 20022 payment file has been created</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">account.pain.create</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">form</field>
+ <field name="view_id" ref="account_pain_save_view"/>
+ <field name="target">new</field>
+ </record>
+
+ </data>
+</openerp>
=== added file 'account_pain/account_payment.py'
--- account_pain/account_payment.py 1970-01-01 00:00:00 +0000
+++ account_pain/account_payment.py 2013-10-22 22:00:27 +0000
@@ -0,0 +1,232 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+#
+# Copyright (c) 2013 Noviat nv/sa (www.noviat.com). All rights reserved.
+#
+# 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.tools.translate import _
+from openerp.osv import fields, osv
+from openerp import netsvc
+import re
+import logging
+_logger = logging.getLogger(__name__)
+
+def check_bba_comm(val):
+ supported_chars = '0-9+*/ '
+ pattern = re.compile('[^' + supported_chars + ']')
+ if pattern.findall(val or ''):
+ return False
+ bbacomm = re.sub('\D', '', val or '')
+ if len(bbacomm) == 12:
+ base = int(bbacomm[:10])
+ mod = base % 97 or 97
+ if mod == int(bbacomm[-2:]):
+ return True
+ return False
+
+class payment_mode(osv.osv):
+ _inherit= 'payment.mode'
+
+ def _initiatingparty_default(self, cr, uid, field, context={}):
+ #_logger.warn('_initiatingparty_default, field=%s, context=%s', field, context)
+ company = self.pool.get('res.users').browse(cr, uid, uid).company_id
+ vat = company.partner_id.vat
+ # Belgium, febelfin specs
+ if vat and vat[0:2].upper() == 'BE':
+ kbo_nr = vat[2:].replace(' ','')
+ if field == 'id':
+ return kbo_nr
+ else:
+ return 'KBO-BCE'
+ else:
+ # complete for other countries
+ return False
+
+ def _initiatingparty_id_default(self, cr, uid, context={}):
+ return self._initiatingparty_default(cr, uid, 'id', context=context)
+
+ def _initiatingparty_issr_default(self, cr, uid, context={}):
+ return self._initiatingparty_default(cr, uid, 'issr', context=context)
+
+ _columns = {
+ 'type': fields.selection([
+ ('manual', 'Manual'),
+ ('iso20022', 'ISO 20022')],
+ 'Type', select=1,
+ help='Select the Payment Type for the Payment Mode.'),
+ 'bank_id': fields.many2one('res.partner.bank', "Bank account",
+ required=False, help='Bank Account for the Payment Mode'),
+ 'initgpty_id': fields.char('Initiating Party Id', size=35,
+ help="Identifier of the Initiating Party."
+ "\nSpecify KBO-BCE number for Belgium."
+ "\n(Field: InitgPty.Id.OrgId.Othr.Id)"),
+ 'initgpty_issr': fields.char('Initiating Party Id Issuer', size=35,
+ help="Issuer of the Identifier of the Initiating Party."
+ "\nSpecify 'KBO-BCE' for Belgium."
+ "\n(Field: InitgPty.Id.OrgId.Othr.Issr)"),
+ }
+ _defaults = {
+ 'initgpty_id': _initiatingparty_id_default,
+ 'initgpty_issr': _initiatingparty_issr_default,
+ }
+
+ def _check_initiatingparty_id(self, cr, uid, ids, context=None):
+ pm = self.browse(cr, uid, ids[0], context=context)
+ if pm.initgpty_issr and not pm.initgpty_id:
+ return False
+ return True
+
+ _constraints = [
+ (_check_initiatingparty_id, "Configuration Error! Please complete the 'Initiating Party Id' field.", ['initgpty_id'])
+ ]
+
+class payment_order(osv.osv):
+ _inherit = 'payment.order'
+
+ def get_wizard(self, type):
+ if type == 'iso20022':
+ return 'account_pain','action_account_pain_create'
+ else:
+ return super(payment_order, self).get_wizard(type)
+
+ def action_open(self, cr, uid, ids, *args):
+ for payment in self.browse(cr, uid, ids):
+ for line in payment.line_ids:
+ if line.amount_currency <= 0:
+ raise osv.except_osv(_('Payment Instruction Error!'),
+ _("Unsupported Payment Instruction in Payment Line %s.\n" \
+ "The value '%s' is less than the minimum value allowed.")
+ % (line.name, line.amount_currency))
+ return super(payment_order, self).action_open(cr, uid, ids, *args)
+
+ def unlink(self, cr, uid, ids, context=None):
+ for order in self.browse(cr, uid, ids, context=context):
+ if order.state == 'done':
+ raise osv.except_osv(_('Error'),
+ _("You can not remove a Payment Order that has already been processed !" \
+ "\nIf such an action is required, you should first cancel the Order."))
+ return super(payment_order, self).unlink(cr, uid, ids, context=context)
+
+ def button_undo_payment(self, cr, uid, ids, context=None):
+ att_obj = self.pool.get('ir.attachment')
+ for order in self.browse(cr, uid, ids, context=context):
+ att_ids = att_obj.search(cr, uid, [('res_model', '=', 'payment.order'), ('res_id', '=', order.id)])
+ if att_ids:
+ att_obj.unlink(cr, uid, att_ids)
+ self.write(cr, uid, order.id, {'state': 'draft'})
+ wf_service = netsvc.LocalService("workflow")
+ wf_service.trg_delete(uid, 'payment.order', order.id, cr)
+ wf_service.trg_create(uid, 'payment.order', order.id, cr)
+ return True
+
+class payment_line(osv.osv):
+ _inherit = 'payment.line'
+
+ def _get_struct_comm_types(self, cr, uid, context=None):
+ res = self.pool.get('account.invoice').fields_get(cr, uid, ['reference_type'], context)['reference_type']['selection']
+ res.pop([i for i,x in enumerate(res) if x[0] == 'none'][0])
+ bba_list = [i for i,x in enumerate(res) if x[0] == 'bba']
+ if not bba_list:
+ res.append(('bba', 'BBA Structured Communication'))
+ return res
+
+ def _check_communication(self, cr, uid, ids):
+ for line in self.browse(cr, uid, ids):
+ if line.state == 'structured':
+ if line.struct_comm_type == 'bba':
+ return check_bba_comm(line.communication)
+ return True
+
+ def fields_get(self, cr, uid, fields=None, context=None):
+ fields = super(payment_line,self).fields_get(cr, uid, fields, context)
+ if context is None:
+ context = {}
+ if context.get('payment_line_readonly'):
+ for field in fields:
+ fields[field]['readonly'] = True
+ return fields
+
+ def unlink(self, cr, uid, ids, context=None):
+ if context is None:
+ context = {}
+ if context.get('payment_line_readonly'):
+ raise osv.except_osv(_('Warning'), _('Delete operation not allowed !' \
+ '\nPlease go to the associated Payment Order in order to delete this payment line'))
+ return super(payment_line, self).unlink(cr, uid, ids, context=context)
+
+ def create(self, cr, uid, vals, context=None):
+ # copy structured communication of payment line is created by referencing an invoice
+ if vals.has_key('move_line_id') and vals['move_line_id']:
+ move_line = self.pool.get('account.move.line').browse(cr, uid, vals['move_line_id'], context)
+ inv = move_line.invoice
+ if inv and inv.reference_type != 'none':
+ vals['state'] = 'structured'
+ vals['struct_comm_type'] = inv.reference_type
+ vals['communication'] = inv.reference
+ # verify correctness of bba structured communication when created via the payment line form
+ if vals.has_key('state') and (vals['state'] == 'structured'):
+ if vals.has_key('struct_comm_type') and (vals['struct_comm_type'] == 'bba'):
+ if vals.has_key('communication'):
+ bbacomm = vals['communication']
+ if check_bba_comm(bbacomm):
+ bbacomm = re.sub('\D', '', bbacomm)
+ vals['communication'] = '+++' + bbacomm[0:3] + '/' + bbacomm[3:7] + '/' + bbacomm[7:] + '+++'
+ else:
+ raise osv.except_osv(_('Payment Instruction Error!'),
+ _('Invalid BBA Structured Communication in Payment Line %s , please correct !') % vals['name'])
+ return super(payment_line, self).create(cr, uid, vals, context=context)
+
+ def write(self, cr, uid, ids, vals, context={}):
+ if type(ids) is int:
+ ids = [ids]
+ for line in self.browse(cr, uid, ids, context):
+ vals2 = vals.copy()
+ if vals.has_key('state'):
+ line_state = vals['state']
+ else:
+ line_state = line.state
+ if line_state == 'structured':
+ if vals.has_key('struct_comm_type'):
+ struct_comm_type = vals['struct_comm_type']
+ else:
+ struct_comm_type = line.struct_comm_type or ''
+ if struct_comm_type == 'bba':
+ if vals.has_key('communication'):
+ bbacomm = vals['communication']
+ else:
+ bbacomm = line.communication or ''
+ if check_bba_comm(bbacomm):
+ bbacomm = re.sub('\D', '', bbacomm)
+ vals2['communication'] = '+++' + bbacomm[0:3] + '/' + bbacomm[3:7] + '/' + bbacomm[7:] + '+++'
+ else:
+ raise osv.except_osv(_('Payment Instruction Error!'),
+ _('Invalid BBA Structured Communication in Payment Line %s , please correct !') % line.name)
+ super(payment_line, self).write(cr, uid, [line.id], vals2, context)
+ return True
+
+ _columns = {
+ 'name': fields.char('Payment Line Ref.', size=64, required=True),
+ 'state': fields.selection([('normal','Free Communication'), ('structured','Structured Communication')], 'Communication Type', required=True),
+ 'struct_comm_type': fields.selection(_get_struct_comm_types, 'Structured Communication Type'),
+ }
+ _constraints = [
+ (_check_communication, 'Invalid BBA Structured Communication !', ['Communication']),
+ ]
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
=== added file 'account_pain/account_payment_view.xml'
--- account_pain/account_payment_view.xml 1970-01-01 00:00:00 +0000
+++ account_pain/account_payment_view.xml 2013-10-22 22:00:27 +0000
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data>
+
+ <record id="view_payment_line_search" model="ir.ui.view">
+ <field name="name">payment.line.tree.search</field>
+ <field name="model">payment.line</field>
+ <field name="arch" type="xml">
+ <search string="Search Payment Lines">
+ <group>
+ <field name="order_id"/>
+ <field name="ml_inv_ref"/>
+ <field name="ml_maturity_date"/>
+ <field name="partner_id" select="1"/>
+ <field name="communication"/>
+ <field name="amount"/>
+ <field name="bank_id" domain="[('partner_id', '=', partner_id)]"/>
+ <field name="move_line_id" on_change="onchange_move_line(move_line_id,parent.mode)"/>
+ <field name="create_date"/>
+ <field name="name"/>
+ </group>
+ <newline/>
+ <group expand="0" string="Group By...">
+ <filter string="Payment Mode" context="{'group_by': 'bank_id'}" icon="terp-dolar"/>
+ </group>
+ </search>
+ </field>
+ </record>
+
+ <record id="action_payment_line_tree" model="ir.actions.act_window">
+ <field name="name">Payment Lines</field>
+ <field name="res_model">payment.line</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">tree,form</field>
+ <field name="search_view_id" ref="view_payment_line_search"/>
+ <field name="view_id" ref="account_payment.view_payment_line_tree"/>
+ <field name="context">{'payment_line_readonly':1}</field>
+ </record>
+ <menuitem action="action_payment_line_tree" id="menu_action_payment_line" parent="account_payment.menu_main_payment" sequence="4"/>
+
+ <act_window domain="[('move_line_id.move_id.id', '=', move_id)]"
+ id="act_account_invoice_2_payment_line"
+ name="Payment Lines"
+ view_type="form"
+ context="{'payment_line_readonly':1}"
+ res_model="payment.line" src_model="account.invoice"/>
+
+
+ <record id="account_payment.action_create_payment_order" model="ir.actions.act_window">
+ <field name="view_id" ref="account_payment.view_create_payment_order"/>
+ </record>
+
+ <!-- change compared to view in account payment : 'name'-field replaced by 'invoice'-field -->
+ <record model="ir.ui.view" id="view_move_line_tree_account_pain">
+ <field name="name">account.pain.move.line.tree</field>
+ <field name="model">account.move.line</field>
+ <field name="priority" eval="1"/>
+ <field name="arch" type="xml">
+ <tree string="Account Entry Line">
+ <field name="partner_id"/>
+ <field name="ref"/>
+ <field name="invoice"/>
+ <field name="journal_id"/>
+ <field name="account_id"/>
+ <field name="date_maturity"/>
+ <field name="date"/>
+ <field name="debit" sum="Total debit"/>
+ <field name="credit" sum="Total credit"/>
+ <field name="amount_to_pay"/>
+ <field name="amount_currency"/>
+ <field name="currency_id"/>
+ <field name="period_id" invisible="1"/>
+ </tree>
+ </field>
+ </record>
+
+ <record id="view_payment_order_form_inherit" model="ir.ui.view">
+ <field name="name">payment.order.form.inherit</field>
+ <field name="model">payment.order</field>
+ <field name="inherit_id" ref="account_payment.view_payment_order_form"/>
+ <field name="arch" type="xml">
+ <data>
+ <xpath expr="//field[@name='line_ids']//page[@string='Payment']//field[@name='state']" position="after">
+ <group colspan="4" attrs="{'invisible':[('state','=','normal')]}">
+ <field name="struct_comm_type" attrs="{'required':[('state','=','structured')]}"/>
+ </group>
+ </xpath>
+ <button name="cancel" position="after">
+ <button name="button_undo_payment" states="done" string="Undo Payment" type="object" groups="account.group_account_manager" icon="gtk-cancel"/>
+ </button>
+ <button name="set_done" position="replace">
+ <button name="%(account_payment.action_account_payment_make_payment)d" states="open" string="Make Payments" type="action" icon="gtk-execute"/>
+ </button>
+ </data>
+ </field>
+ </record>
+
+ <record id="view_payment_mode_search_inherit" model="ir.ui.view">
+ <field name="name">payment.mode.search.inherit</field>
+ <field name="model">payment.mode</field>
+ <field name="inherit_id" ref="account_payment.view_payment_mode_search"/>
+ <field name="arch" type="xml">
+ <field name="journal" position="after">
+ <field name="type"/>
+ </field>
+ </field>
+ </record>
+
+ <record id="view_payment_mode_tree_inherit" model="ir.ui.view">
+ <field name="name">payment.mode.tree.inherit</field>
+ <field name="model">payment.mode</field>
+ <field name="inherit_id" ref="account_payment.view_payment_mode_tree"/>
+ <field name="arch" type="xml">
+ <field name="journal" position="after">
+ <field name="type"/>
+ </field>
+ </field>
+ </record>
+
+ <record id="view_payment_mode_form_inherit" model="ir.ui.view">
+ <field name="name">payment.mode.form.inherit</field>
+ <field name="model">payment.mode</field>
+ <field name="inherit_id" ref="account_payment.view_payment_mode_form"/>
+ <field name="arch" type="xml">
+ <field name="journal" position="after">
+ <field name="type"/>
+ </field>
+ <field name="bank_id" position="attributes">
+ <attribute name="attrs">{'required':[('type','=','iso20022')]}</attribute>
+ </field>
+ <field name="bank_id" position="after">
+ <field name="initgpty_id" attrs="{'invisible':[('type','!=','iso20022')]}"/>
+ <field name="initgpty_issr" attrs="{'invisible':[('type','!=','iso20022')]}"/>
+ </field>
+ <!--correct partner_id field for GTK client -->
+ <field name="partner_id" position="replace">
+ <field name="partner_id" invisible="1"/>
+ </field>
+ </field>
+ </record>
+
+ </data>
+</openerp>
=== added directory 'account_pain/i18n'
=== added file 'account_pain/i18n/fr.po'
--- account_pain/i18n/fr.po 1970-01-01 00:00:00 +0000
+++ account_pain/i18n/fr.po 2013-10-22 22:00:27 +0000
@@ -0,0 +1,78 @@
+# French translation of openobject-addons.
+# This file contains the translation of the following modules:
+# * account_pain
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openobject-addons\n"
+"Report-Msgid-Bugs-To: support@xxxxxxxxx\n"
+"POT-Creation-Date: 2011-03-24 11:18:30.714000\n"
+"PO-Revision-Date: 2011-03-24 11:18:30.714000\n"
+"Last-Translator: Luc De Meyer (Noviat nv/sa)\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. module: account_pain
+#: view:account.pain.create:0
+msgid "The ISO 20022 payment file has been created"
+msgstr "Le fichier de paiement ISO 20022 est généré"
+
+#. module: account_pain
+#: view:account.pain.create:0
+msgid "Click on 'Save as' to save the file on your local disk."
+msgstr "Sélectionnez 'Enregistrer sous' pour sauvegarder le fichier sur votre disque local."
+
+#. module: account_pain
+#: field:account.pain.create,pain_data:0
+msgid "Payment File"
+msgstr "Fichier de paiement"
+
+#. module: account_pain
+#: field:account.pain.create,pain_fname:0
+msgid "Filename"
+msgstr "Nom du fichier"
+
+#. module: account_pain
+#: field:account.pain.create,note:0
+msgid "Remarks"
+msgstr "Remarques"
+
+#. module: account_pain
+#: code:addons/account_pain/wizard/pain_wizard.py:0
+#, python-format
+msgid "Warning:\n"
+msgstr "Alerte:\n"
+
+#. module: account_pain
+#: code:addons/account_pain/wizard/pain_wizard.py:0
+#, python-format
+msgid "\nThe Payment Date on Payment Line %s has been changed."
+msgstr "\nLa date de paiement du ligne de paiement %s a changé."
+
+#. module: account_pain
+#: field:payment.line,name:0
+msgid "Payment Line Ref."
+msgstr "Ref. ligne de paiement"
+
+#. module: account_pain
+#: field:payment.line,struct_comm_type:0
+msgid "Structured Communication Type"
+msgstr "Type de communication structurée"
+
+#. module: account_pain
+#: selection:payment.line,struct_comm_type:0
+msgid "BBA Structured Communication"
+msgstr "Communication structurée belge (BBA)"
+
+#. module: account_pain
+#: selection:payment.line,state:0
+msgid "Free Communication"
+msgstr "Communication libre"
+
+#. module: account_pain
+#: selection:payment.line,state:0
+msgid "Structured Communication"
+msgstr "Communication structurée"
+
=== added file 'account_pain/i18n/nl.po'
--- account_pain/i18n/nl.po 1970-01-01 00:00:00 +0000
+++ account_pain/i18n/nl.po 2013-10-22 22:00:27 +0000
@@ -0,0 +1,78 @@
+# Dutch translation of openobject-addons.
+# This file contains the translation of the following modules:
+# * account_pain
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: openobject-addons\n"
+"Report-Msgid-Bugs-To: support@xxxxxxxxx\n"
+"POT-Creation-Date: 2011-03-24 11:18:30.654000\n"
+"PO-Revision-Date: 2011-03-24 11:18:30.654000\n"
+"Last-Translator: Luc De Meyer (Noviat nv/sa)\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. module: account_pain
+#: view:account.pain.create:0
+msgid "The ISO 20022 payment file has been created"
+msgstr "Het ISO 20022 betalingsbestand is aangemaakt"
+
+#. module: account_pain
+#: view:account.pain.create:0
+msgid "Click on 'Save as' to save the file on your local disk."
+msgstr "Selecteer 'Opslaan als' om dit bestand te bewaren op je lokale schijf."
+
+#. module: account_pain
+#: field:account.pain.create,pain_data:0
+msgid "Payment File"
+msgstr "Betalingsbestand"
+
+#. module: account_pain
+#: field:account.pain.create,pain_fname:0
+msgid "Filename"
+msgstr "Bestandsnaam"
+
+#. module: account_pain
+#: field:account.pain.create,note:0
+msgid "Remarks"
+msgstr "Opmerkingen"
+
+#. module: account_pain
+#: code:addons/account_pain/wizard/pain_wizard.py:0
+#, python-format
+msgid "Warning:\n"
+msgstr "Waarschuwing:\n"
+
+#. module: account_pain
+#: code:addons/account_pain/wizard/pain_wizard.py:0
+#, python-format
+msgid "\nThe Payment Date on Payment Line %s has been changed."
+msgstr "\nDe betaaldatum van betaalregel %s is aangepast."
+
+#. module: account_pain
+#: field:payment.line,name:0
+msgid "Payment Line Ref."
+msgstr "Ref. Betaalregel"
+
+#. module: account_pain
+#: field:payment.line,struct_comm_type:0
+msgid "Structured Communication Type"
+msgstr "Type gestructureerde mededeling"
+
+#. module: account_pain
+#: selection:payment.line,struct_comm_type:0
+msgid "BBA Structured Communication"
+msgstr "Belgische gestructureerde mededeling (BBA)"
+
+#. module: account_pain
+#: selection:payment.line,state:0
+msgid "Free Communication"
+msgstr "Vrije mededeling"
+
+#. module: account_pain
+#: selection:payment.line,state:0
+msgid "Structured Communication"
+msgstr "Gestructureerde mededeling"
+
=== added directory 'account_pain/static'
=== added directory 'account_pain/static/src'
=== added directory 'account_pain/static/src/img'
=== added file 'account_pain/static/src/img/icon.png'
Binary files account_pain/static/src/img/icon.png 1970-01-01 00:00:00 +0000 and account_pain/static/src/img/icon.png 2013-10-22 22:00:27 +0000 differ
=== added directory 'account_pain/wizard'
=== added file 'account_pain/wizard/__init__.py'
--- account_pain/wizard/__init__.py 1970-01-01 00:00:00 +0000
+++ account_pain/wizard/__init__.py 2013-10-22 22:00:27 +0000
@@ -0,0 +1,24 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+#
+# Copyright (c) 2013 Noviat nv/sa (www.noviat.com). All rights reserved.
+#
+# 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/>.
+#
+##############################################################################
+
+import payment_order_create
+import pain_wizard
\ No newline at end of file
=== added file 'account_pain/wizard/pain_wizard.py'
--- account_pain/wizard/pain_wizard.py 1970-01-01 00:00:00 +0000
+++ account_pain/wizard/pain_wizard.py 2013-10-22 22:00:27 +0000
@@ -0,0 +1,303 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+#
+# Copyright (c) 2013 Noviat nv/sa (www.noviat.com). All rights reserved.
+#
+# 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.tools.translate import _
+from openerp.osv import fields, osv
+import re
+import time
+import base64
+from StringIO import StringIO
+from lxml import etree
+import tools
+import logging
+_logger = logging.getLogger(__name__)
+
+class account_payment_make_payment(osv.osv_memory):
+ _inherit = 'account.payment.make.payment'
+
+ def launch_wizard(self, cr, uid, ids, context=None):
+ """
+ Search for a wizard to launch according to the type.
+ Confirm the order without wizard if type is manual.
+ """
+ if context is None:
+ context = {}
+ obj_payment_order = self.pool.get('payment.order')
+ obj_model = self.pool.get('ir.model.data')
+ obj_act = self.pool.get('ir.actions.act_window')
+ order = obj_payment_order.browse(cr, uid, context['active_id'], context)
+ payment_type = order.mode and order.mode.type or 'manual'
+ gw = obj_payment_order.get_wizard(payment_type)
+ if (not gw) or (payment_type == 'manual'):
+ obj_payment_order.set_done(cr, uid, [context['active_id']], context)
+ return {'type': 'ir.actions.act_window_close'}
+
+ # add support community modules using the payment gateway wizard plugin
+ module, wizard = gw
+ result = obj_model._get_id(cr, uid, module, wizard)
+ wiz_id = obj_model.read(cr, uid, [result], ['res_id'])[0]['res_id']
+ if payment_type != 'iso20022':
+ return_act = obj_act.read(cr, uid, [wiz_id])[0]
+ return_act.update({'context': context})
+ return return_act
+
+ # generate ISO 20022 XML
+ data = self.generate_pain(cr, uid, context)
+ apc_id = self.pool.get('account.pain.create').create(cr, uid, data)
+ obj_model = self.pool.get('ir.model.data')
+ model_data_ids = obj_model.search(cr,uid,[('model','=','ir.ui.view'), ('name','=','account_pain_save_view')])
+ resource_id = obj_model.read(cr, uid, model_data_ids, fields=['res_id'])[0]['res_id']
+ return {
+ 'name': _('The ISO 20022 payment file has been created'),
+ 'view_type': 'form',
+ 'view_mode': 'form',
+ 'res_model': 'account.pain.create',
+ 'res_id': apc_id,
+ 'views': [(resource_id, 'form')],
+ 'type': 'ir.actions.act_window',
+ 'target': 'new',
+ 'context': context,
+ }
+
+ def format_comm(self, comm):
+ bbacomm = re.sub('\D', '', comm)
+ if len(bbacomm) == 12:
+ base = int(bbacomm[:10])
+ mod = base % 97 or 97
+ if mod == int(bbacomm[-2:]):
+ return bbacomm
+ return False
+
+ def generate_pain(self, cr, uid, context):
+ if not context:
+ context = {}
+ active_id = context.get('active_id', [])
+
+ payment_obj = self.pool.get('payment.order')
+ payment_line_obj = self.pool.get('payment.line')
+ attachment_obj = self.pool.get('ir.attachment')
+ payment_line_obj = self.pool.get('payment.line')
+ note = ''
+
+ payment = payment_obj.browse(cr, uid, active_id, context=context)
+ payment_mode = payment.mode
+ pain_fname = re.sub('\W', '_', payment.reference).lower() + '.xml'
+ company = self.pool.get('res.users').browse(cr, uid, uid).company_id
+ if not (payment_mode.bank_id.bank_bic or payment_mode.bank_id.bank.bic):
+ raise osv.except_osv(_('Configuration Error!'),
+ _("Please fill in the BIC code of the Bank Debtor Account for this Payment Order!"))
+ if not payment.line_ids:
+ raise osv.except_osv(_('Data Error!'),
+ _("Your Payment Order does not contain payment instructions!"))
+ if payment_mode.journal.currency and (payment_mode.journal.currency != company.currency_id):
+ raise osv.except_osv(_('Payment Order Error!'),
+ _('Only payments from a bank account in company currency are supported in the current release ' \
+ 'of the ISO 20022 payment module!'))
+
+ # create XML
+ ns_map = {
+ None: 'urn:iso:std:iso:20022:tech:xsd:pain.001.001.03',
+ 'xsi': 'http://www.w3.org/2001/XMLSchema-instance',
+ }
+ pain = etree.Element('Document', nsmap = ns_map)
+ CstmrCdtTrfInitn = etree.SubElement(pain, 'CstmrCdtTrfInitn')
+ # GroupHeader
+ GrpHdr = etree.SubElement(CstmrCdtTrfInitn, 'GrpHdr')
+ MsgId = etree.SubElement(GrpHdr, 'MsgId')
+ MsgId.text = payment.reference
+ CreDtTm = etree.SubElement(GrpHdr, 'CreDtTm')
+ CreDtTm.text = time.strftime('%Y-%m-%dT%H:%M:%S')
+ NbOfTxs = etree.SubElement(GrpHdr, 'NbOfTxs')
+ NbOfTxs.text = str(len(payment.line_ids))
+ CtrlSum = etree.SubElement(GrpHdr, 'CtrlSum')
+ CtrlSum.text = '%.2f' % payment.total
+ InitgPty = etree.SubElement(GrpHdr, 'InitgPty')
+ Nm = etree.SubElement(InitgPty, 'Nm')
+ Nm.text = company.name
+ if payment_mode.initgpty_id:
+ Id = etree.SubElement(InitgPty, 'Id')
+ OrgId = etree.SubElement(Id, 'OrgId')
+ Othr = etree.SubElement(OrgId, 'Othr')
+ Id = etree.SubElement(Othr, 'Id')
+ Id.text = payment_mode.initgpty_id
+ if payment_mode.initgpty_issr:
+ Issr = etree.SubElement(Othr, 'Issr')
+ Issr.text = payment_mode.initgpty_issr
+ # PaymentInformation
+ payment_method = 'TRF'
+ for line in payment.line_ids:
+ if line.currency != company.currency_id:
+ raise osv.except_osv(_('Payment Instruction Error!'),
+ _('Unsupported Payment Instruction in Payment Line %s.\n' \
+ 'Only payments in company currency are supported in the current release ' \
+ 'of the ISO 20022 payment module!') % line.name)
+ if not line.amount:
+ raise osv.except_osv(_('Payment Instruction Error!'),
+ _('Payment Instruction Error in Payment Line %s.\n' \
+ 'Please fill in the transaction amount!') %line.name)
+ if not (line.bank_id and line.bank_id.iban):
+ raise osv.except_osv(_('Payment Instruction Error!'),
+ _('Unsupported Payment Instruction in Payment Line %s.\n' \
+ 'Please fill in the IBAN number of the Bank Creditor Account for this Payment Line!') % line.name)
+
+ if payment.date_prefered == 'now':
+ execution_date = time.strftime('%Y-%m-%d')
+ elif payment.date_prefered == 'fixed':
+ execution_date = payment.date_scheduled
+ elif payment.date_prefered == 'due':
+ if not line.date:
+ if line.ml_maturity_date:
+ excution_date = ml_maturity_date
+ else:
+ execution_date = time.strftime('%Y-%m-%d')
+ else:
+ execution_date = line.date
+ else:
+ raise osv.except_osv(_('Unsupported Payment Order Option!'),
+ _("Please ensure that the 'Preferred date' is equal to 'Due date', 'Directly' or 'Fixed date'!"))
+ if execution_date < time.strftime('%Y-%m-%d'):
+ execution_date = time.strftime('%Y-%m-%d')
+ if line.date != execution_date:
+ note += _('\nThe Payment Date on Payment Line %s has been changed.') % line.name
+ payment_line_obj.write(cr, uid, line.id, {'date': execution_date})
+
+ PmtInf = etree.SubElement(CstmrCdtTrfInitn, 'PmtInf')
+ PmtInfId = etree.SubElement(PmtInf, 'PmtInfId')
+ PmtInfId.text = line.name
+ PmtMtd = etree.SubElement(PmtInf, 'PmtMtd')
+ PmtMtd.text = payment_method
+ BtchBookg = etree.SubElement(PmtInf, 'BtchBookg')
+ BtchBookg.text = 'false'
+ if payment_method == 'TRF':
+ PmtTpInf = etree.SubElement(PmtInf, 'PmtTpInf')
+ InstrPrty = etree.SubElement(PmtTpInf, 'InstrPrty')
+ InstrPrty.text = 'NORM'
+ SvcLvl = etree.SubElement(PmtTpInf, 'SvcLvl')
+ Cd = etree.SubElement(SvcLvl, 'Cd')
+ Cd.text = 'SEPA'
+ ReqdExctnDt = etree.SubElement(PmtInf, 'ReqdExctnDt')
+ ReqdExctnDt.text = execution_date
+ Dbtr = etree.SubElement(PmtInf, 'Dbtr')
+ Nm = etree.SubElement(Dbtr, 'Nm')
+ Nm.text = company.name
+ DbtrAcct = etree.SubElement(PmtInf, 'DbtrAcct')
+ Id = etree.SubElement(DbtrAcct, 'Id')
+ IBAN = etree.SubElement(Id, 'IBAN')
+ IBAN.text = payment_mode.bank_id.iban.upper().replace(' ','')
+ DbtrAgt = etree.SubElement(PmtInf, 'DbtrAgt')
+ FinInstnId = etree.SubElement(DbtrAgt, 'FinInstnId')
+ BIC = etree.SubElement(FinInstnId, 'BIC')
+ BIC.text = re.sub('\s','',payment_mode.bank_id.bank_bic.upper() or payment_mode.bank_id.bank.bic.upper())
+ ChrgBr = etree.SubElement(PmtInf, 'ChrgBr')
+ ChrgBr.text = 'SLEV'
+ CdtTrfTxInf = etree.SubElement(PmtInf, 'CdtTrfTxInf')
+ PmtId = etree.SubElement(CdtTrfTxInf, 'PmtId')
+ EndToEndId = etree.SubElement(PmtId, 'EndToEndId')
+ EndToEndId.text = line.name
+ Amt = etree.SubElement(CdtTrfTxInf, 'Amt')
+ InstdAmt = etree.SubElement(Amt, 'InstdAmt', Ccy=line.currency.name)
+ InstdAmt.text = '%.2f' % line.amount
+ if line.bank_id.iban[0:2].upper() not in ['BE']: # to be completed with other countries allowing payments without BIC
+ if not (line.bank_id.bank_bic or line.bank_id.bank.bic):
+ raise osv.except_osv(_('Configuration Error!'),
+ _('Unsupported Payment Instruction in Payment Line %s.\n' \
+ 'Please fill in the BIC code of the Bank Creditor Account for this Payment Line!') % line.name)
+ if line.bank_id.bank_bic or line.bank_id.bank.bic:
+ CdtrAgt = etree.SubElement(CdtTrfTxInf, 'CdtrAgt')
+ FinInstnId = etree.SubElement(CdtrAgt, 'FinInstnId')
+ BIC = etree.SubElement(FinInstnId, 'BIC')
+ BIC.text = re.sub('\s','',line.bank_id.bank_bic.upper() or line.bank_id.bank.bic.upper())
+ Cdtr = etree.SubElement(CdtTrfTxInf, 'Cdtr')
+ Nm = etree.SubElement(Cdtr, 'Nm')
+ Nm.text = line.partner_id.name
+ CdtrAcct = etree.SubElement(CdtTrfTxInf, 'CdtrAcct')
+ Id = etree.SubElement(CdtrAcct, 'Id')
+ IBAN = etree.SubElement(Id, 'IBAN')
+ IBAN.text = line.bank_id.iban.upper().replace(' ','')
+ if line.communication:
+ comm = line.communication
+ if line.communication2:
+ comm += ' ' + line.communication2
+ RmtInf = etree.SubElement(CdtTrfTxInf, 'RmtInf')
+ if line.state == 'normal':
+ Ustrd = etree.SubElement(RmtInf, 'Ustrd')
+ Ustrd.text = comm
+ elif line.state == 'structured':
+ Strd = etree.SubElement(RmtInf, 'Strd')
+ CdtrRefInf = etree.SubElement(Strd, 'CdtrRefInf')
+ Tp = etree.SubElement(CdtrRefInf, 'Tp')
+ CdOrPrtry = etree.SubElement(Tp, 'CdOrPrtry')
+ Cd = etree.SubElement(CdOrPrtry, 'Cd')
+ Cd.text = 'SCOR'
+ Issr = etree.SubElement(Tp, 'Issr')
+ Issr.text = 'BBA'
+ comm = self.format_comm(line.communication)
+ if not comm:
+ raise osv.except_osv(_('Payment Instruction Error!'),
+ _('Unsupported Structured Communication in Payment Line %s.\n' \
+ 'Only the Belgian Structured Communication format (BBA) is supported in the current release ' \
+ 'of the ISO 20022 payment module!') % line.name)
+ Ref = etree.SubElement(CdtrRefInf, 'Ref')
+ Ref.text = comm
+ else:
+ raise osv.except_osv(_('Configuration Error!'),
+ _('Unsupported Communication Type in Payment Line %s.\n') % line.name)
+ pain_data = etree.tostring(pain, encoding='UTF-8', xml_declaration=True, pretty_print=True)
+ # validate the generated XML schema
+ xsd = tools.file_open('account_pain/xsd/pain.001.001.03.xsd')
+ xmlschema_doc = etree.parse(xsd)
+ xmlschema = etree.XMLSchema(xmlschema_doc)
+ xml_to_validate = StringIO(pain_data)
+ parse_result = etree.parse(xml_to_validate)
+ if xmlschema.validate(parse_result):
+ pain_data = base64.encodestring(pain_data)
+ attachment_obj.create(cr, uid, {
+ 'name': pain_fname,
+ 'datas': pain_data,
+ 'datas_fname': pain_fname,
+ 'res_model': 'payment.order',
+ 'res_id': active_id,
+ }, context=context)
+ payment_obj.set_done(cr, uid, [active_id], context)
+ else:
+ _logger.error('The generated XML file does not fit the required schema !')
+ _logger.error(tools.ustr(xmlschema.error_log.last_error))
+ error = xmlschema.error_log[0]
+ raise osv.except_osv(_('The generated XML file does not fit the required schema !'),
+ error.message)
+
+ if note:
+ note = _('Warning:\n') + note
+
+ return {'pain_data': pain_data, 'pain_fname': pain_fname, 'note': note}
+
+class account_pain_create(osv.osv_memory):
+ _name = 'account.pain.create'
+ _description = 'ISO 20022 payment file'
+
+ _columns = {
+ 'pain_data': fields.binary('Payment File', required=True, readonly=True),
+ 'pain_fname': fields.char('Filename', size=128, required=True),
+ 'note': fields.text('Remarks'),
+ }
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
=== added file 'account_pain/wizard/payment_order_create.py'
--- account_pain/wizard/payment_order_create.py 1970-01-01 00:00:00 +0000
+++ account_pain/wizard/payment_order_create.py 2013-10-22 22:00:27 +0000
@@ -0,0 +1,142 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+#
+# Copyright (c) 2013 Noviat nv/sa (www.noviat.com). All rights reserved.
+#
+# 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 datetime import datetime, date, timedelta
+from lxml import etree
+from osv import osv, fields
+from tools.translate import _
+import logging
+_logger = logging.getLogger(__name__)
+
+class payment_order_create(osv.osv_memory):
+ _inherit = 'payment.order.create'
+
+ _defaults = {
+ 'duedate': lambda *a: (date.today() + timedelta(30)).isoformat(),
+ }
+
+ def journal_domain(self, cr, uid, context=None):
+ """
+ override this method in order to customise the journals to search on
+ """
+ journal_domain = [('journal_id.type', 'in', ['purchase', 'sale_refund', 'general', 'situation'])]
+ return journal_domain
+
+ def search_entries(self, cr, uid, ids, context=None):
+ """
+ Override the search_entries & fields_view_get methods of the account_payment payment.order.create object
+ """
+ line_obj = self.pool.get('account.move.line')
+ mod_obj = self.pool.get('ir.model.data')
+ if context is None:
+ context = {}
+ data = self.read(cr, uid, ids, [], context=context)[0]
+ search_due_date = data['duedate']
+ # Search for move line to pay:
+ domain = [('reconcile_id', '=', False), ('partner_id', '!=', False), ('account_id.type', 'in', ['payable', 'receivable']), ('amount_to_pay', '>', 0)] # update Noviat
+ domain = domain + ['|', ('date_maturity', '<=', search_due_date), ('date_maturity', '=', False)]
+ journal_domain = self.journal_domain(cr, uid)
+ domain = domain + journal_domain
+ line_ids = line_obj.search(cr, uid, domain, context=context)
+ context.update({'line_ids': line_ids})
+ model_data_ids = mod_obj.search(cr, uid,[('model', '=', 'ir.ui.view'), ('name', '=', 'view_create_payment_order_lines')], context=context)
+ resource_id = mod_obj.read(cr, uid, model_data_ids, fields=['res_id'], context=context)[0]['res_id']
+ return {'name': _('Populate Payment'),
+ 'context': context,
+ 'view_type': 'form',
+ 'view_mode': 'form',
+ 'res_model': 'payment.order.create',
+ 'views': [(resource_id,'form')],
+ 'type': 'ir.actions.act_window',
+ 'target': 'new',
+ }
+
+ """
+ add context to 'entries' field for use in account.move.line
+ """
+ def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
+ res = super(payment_order_create, self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar, submenu=False)
+ if context and 'line_ids' in context and view_type == 'form':
+ doc = etree.XML(res['arch'])
+ nodes = doc.xpath("//field[@name='entries']")
+ for node in nodes:
+ # add context for use in account.move.line
+ node.set('context', "{'account_payment':'1', 'view_mode':'tree'}")
+ node.set('colspan', '4')
+ node.set('height', '300')
+ node.set('width', '800')
+ res['arch'] = etree.tostring(doc)
+ return res
+
+ def create_payment(self, cr, uid, ids, context=None):
+ """
+ This method replaces the original one for multi-currency purposes
+ """
+ order_obj = self.pool.get('payment.order')
+ line_obj = self.pool.get('account.move.line')
+ payment_obj = self.pool.get('payment.line')
+ if context is None:
+ context = {}
+ data = self.browse(cr, uid, ids, context=context)[0]
+ line_ids = [entry.id for entry in data.entries]
+ if not line_ids:
+ return {'type': 'ir.actions.act_window_close'}
+
+ payment = order_obj.browse(cr, uid, context['active_id'], context=context)
+ t = payment.mode.type == 'iso20022' and payment.mode.id or None
+ line2bank = line_obj.line2bank(cr, uid, line_ids, t, context)
+
+ company_currency = payment.mode.company_id.currency_id
+ payment_mode_currency = payment.mode.journal.currency or company_currency
+
+ ## Finally populate the current payment with new lines:
+ for line in line_obj.browse(cr, uid, line_ids, context=context):
+ if payment.date_prefered == "now":
+ #no payment date => immediate payment
+ date_to_pay = False
+ elif payment.date_prefered == 'due':
+ date_to_pay = line.date_maturity
+ elif payment.date_prefered == 'fixed':
+ date_to_pay = payment.date_scheduled
+
+ transaction_currency = line.currency_id or company_currency
+ if transaction_currency != payment_mode_currency and payment.mode.type == 'iso20022':
+ raise osv.except_osv(_('Unsupported Operation !'),
+ _("The payment in another currency as the originating transaction is not supported in the" \
+ "current release of the ISO 20022 Payment Gateway"
+ "\nTransaction Currency: %s, Payment Mode Currency: %s)" \
+ "\n\nPlease contact info@xxxxxxxxx if this is a requirement.")
+ %(transaction_currency, payment_mode_currency) )
+
+ payment_obj.create(cr, uid,{
+ 'move_line_id': line.id,
+ 'amount_currency': line.amount_to_pay,
+ 'bank_id': line2bank.get(line.id),
+ 'order_id': payment.id,
+ 'partner_id': line.partner_id and line.partner_id.id or False,
+ 'communication': line.ref or '/',
+ 'date': date_to_pay,
+ 'currency': line.currency_id.id or company_currency.id,
+ }, context=context)
+ return {'type': 'ir.actions.act_window_close'}
+
+payment_order_create()
\ No newline at end of file
=== added directory 'account_pain/xsd'
=== added file 'account_pain/xsd/pain.001.001.03.xsd'
--- account_pain/xsd/pain.001.001.03.xsd 1970-01-01 00:00:00 +0000
+++ account_pain/xsd/pain.001.001.03.xsd 2013-10-22 22:00:27 +0000
@@ -0,0 +1,921 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!--Generated by SWIFTStandards Workstation (build:R6.1.0.2) on 2009 Jan 08 17:30:53-->
+<xs:schema xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03">
+ <xs:element name="Document" type="Document"/>
+ <xs:complexType name="AccountIdentification4Choice">
+ <xs:sequence>
+ <xs:choice>
+ <xs:element name="IBAN" type="IBAN2007Identifier"/>
+ <xs:element name="Othr" type="GenericAccountIdentification1"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="AccountSchemeName1Choice">
+ <xs:sequence>
+ <xs:choice>
+ <xs:element name="Cd" type="ExternalAccountIdentification1Code"/>
+ <xs:element name="Prtry" type="Max35Text"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="ActiveOrHistoricCurrencyAndAmount_SimpleType">
+ <xs:restriction base="xs:decimal">
+ <xs:minInclusive value="0"/>
+ <xs:fractionDigits value="5"/>
+ <xs:totalDigits value="18"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="ActiveOrHistoricCurrencyAndAmount">
+ <xs:simpleContent>
+ <xs:extension base="ActiveOrHistoricCurrencyAndAmount_SimpleType">
+ <xs:attribute name="Ccy" type="ActiveOrHistoricCurrencyCode" use="required"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ <xs:simpleType name="ActiveOrHistoricCurrencyCode">
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[A-Z]{3,3}"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="AddressType2Code">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="ADDR"/>
+ <xs:enumeration value="PBOX"/>
+ <xs:enumeration value="HOME"/>
+ <xs:enumeration value="BIZZ"/>
+ <xs:enumeration value="MLTO"/>
+ <xs:enumeration value="DLVY"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="AmountType3Choice">
+ <xs:sequence>
+ <xs:choice>
+ <xs:element name="InstdAmt" type="ActiveOrHistoricCurrencyAndAmount"/>
+ <xs:element name="EqvtAmt" type="EquivalentAmount2"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="AnyBICIdentifier">
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[A-Z]{6,6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3,3}){0,1}"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="Authorisation1Choice">
+ <xs:sequence>
+ <xs:choice>
+ <xs:element name="Cd" type="Authorisation1Code"/>
+ <xs:element name="Prtry" type="Max128Text"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="Authorisation1Code">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="AUTH"/>
+ <xs:enumeration value="FDET"/>
+ <xs:enumeration value="FSUM"/>
+ <xs:enumeration value="ILEV"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="BICIdentifier">
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[A-Z]{6,6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3,3}){0,1}"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="BaseOneRate">
+ <xs:restriction base="xs:decimal">
+ <xs:fractionDigits value="10"/>
+ <xs:totalDigits value="11"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="BatchBookingIndicator">
+ <xs:restriction base="xs:boolean"/>
+ </xs:simpleType>
+ <xs:complexType name="BranchAndFinancialInstitutionIdentification4">
+ <xs:sequence>
+ <xs:element name="FinInstnId" type="FinancialInstitutionIdentification7"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="BrnchId" type="BranchData2"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="BranchData2">
+ <xs:sequence>
+ <xs:element maxOccurs="1" minOccurs="0" name="Id" type="Max35Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Nm" type="Max140Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="PstlAdr" type="PostalAddress6"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="CashAccount16">
+ <xs:sequence>
+ <xs:element name="Id" type="AccountIdentification4Choice"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Tp" type="CashAccountType2"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Ccy" type="ActiveOrHistoricCurrencyCode"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Nm" type="Max70Text"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="CashAccountType2">
+ <xs:sequence>
+ <xs:choice>
+ <xs:element name="Cd" type="CashAccountType4Code"/>
+ <xs:element name="Prtry" type="Max35Text"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="CashAccountType4Code">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="CASH"/>
+ <xs:enumeration value="CHAR"/>
+ <xs:enumeration value="COMM"/>
+ <xs:enumeration value="TAXE"/>
+ <xs:enumeration value="CISH"/>
+ <xs:enumeration value="TRAS"/>
+ <xs:enumeration value="SACC"/>
+ <xs:enumeration value="CACC"/>
+ <xs:enumeration value="SVGS"/>
+ <xs:enumeration value="ONDP"/>
+ <xs:enumeration value="MGLD"/>
+ <xs:enumeration value="NREX"/>
+ <xs:enumeration value="MOMA"/>
+ <xs:enumeration value="LOAN"/>
+ <xs:enumeration value="SLRY"/>
+ <xs:enumeration value="ODFT"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="CategoryPurpose1Choice">
+ <xs:sequence>
+ <xs:choice>
+ <xs:element name="Cd" type="ExternalCategoryPurpose1Code"/>
+ <xs:element name="Prtry" type="Max35Text"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="ChargeBearerType1Code">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="DEBT"/>
+ <xs:enumeration value="CRED"/>
+ <xs:enumeration value="SHAR"/>
+ <xs:enumeration value="SLEV"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="Cheque6">
+ <xs:sequence>
+ <xs:element maxOccurs="1" minOccurs="0" name="ChqTp" type="ChequeType2Code"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="ChqNb" type="Max35Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="ChqFr" type="NameAndAddress10"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="DlvryMtd" type="ChequeDeliveryMethod1Choice"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="DlvrTo" type="NameAndAddress10"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="InstrPrty" type="Priority2Code"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="ChqMtrtyDt" type="ISODate"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="FrmsCd" type="Max35Text"/>
+ <xs:element maxOccurs="2" minOccurs="0" name="MemoFld" type="Max35Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="RgnlClrZone" type="Max35Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="PrtLctn" type="Max35Text"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="ChequeDelivery1Code">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="MLDB"/>
+ <xs:enumeration value="MLCD"/>
+ <xs:enumeration value="MLFA"/>
+ <xs:enumeration value="CRDB"/>
+ <xs:enumeration value="CRCD"/>
+ <xs:enumeration value="CRFA"/>
+ <xs:enumeration value="PUDB"/>
+ <xs:enumeration value="PUCD"/>
+ <xs:enumeration value="PUFA"/>
+ <xs:enumeration value="RGDB"/>
+ <xs:enumeration value="RGCD"/>
+ <xs:enumeration value="RGFA"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="ChequeDeliveryMethod1Choice">
+ <xs:sequence>
+ <xs:choice>
+ <xs:element name="Cd" type="ChequeDelivery1Code"/>
+ <xs:element name="Prtry" type="Max35Text"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="ChequeType2Code">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="CCHQ"/>
+ <xs:enumeration value="CCCH"/>
+ <xs:enumeration value="BCHQ"/>
+ <xs:enumeration value="DRFT"/>
+ <xs:enumeration value="ELDR"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="ClearingSystemIdentification2Choice">
+ <xs:sequence>
+ <xs:choice>
+ <xs:element name="Cd" type="ExternalClearingSystemIdentification1Code"/>
+ <xs:element name="Prtry" type="Max35Text"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="ClearingSystemMemberIdentification2">
+ <xs:sequence>
+ <xs:element maxOccurs="1" minOccurs="0" name="ClrSysId" type="ClearingSystemIdentification2Choice"/>
+ <xs:element name="MmbId" type="Max35Text"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="ContactDetails2">
+ <xs:sequence>
+ <xs:element maxOccurs="1" minOccurs="0" name="NmPrfx" type="NamePrefix1Code"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Nm" type="Max140Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="PhneNb" type="PhoneNumber"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="MobNb" type="PhoneNumber"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="FaxNb" type="PhoneNumber"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="EmailAdr" type="Max2048Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Othr" type="Max35Text"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="CountryCode">
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[A-Z]{2,2}"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="CreditDebitCode">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="CRDT"/>
+ <xs:enumeration value="DBIT"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="CreditTransferTransactionInformation10">
+ <xs:sequence>
+ <xs:element name="PmtId" type="PaymentIdentification1"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="PmtTpInf" type="PaymentTypeInformation19"/>
+ <xs:element name="Amt" type="AmountType3Choice"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="XchgRateInf" type="ExchangeRateInformation1"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="ChrgBr" type="ChargeBearerType1Code"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="ChqInstr" type="Cheque6"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="UltmtDbtr" type="PartyIdentification32"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="IntrmyAgt1" type="BranchAndFinancialInstitutionIdentification4"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="IntrmyAgt1Acct" type="CashAccount16"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="IntrmyAgt2" type="BranchAndFinancialInstitutionIdentification4"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="IntrmyAgt2Acct" type="CashAccount16"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="IntrmyAgt3" type="BranchAndFinancialInstitutionIdentification4"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="IntrmyAgt3Acct" type="CashAccount16"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="CdtrAgt" type="BranchAndFinancialInstitutionIdentification4"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="CdtrAgtAcct" type="CashAccount16"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Cdtr" type="PartyIdentification32"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="CdtrAcct" type="CashAccount16"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="UltmtCdtr" type="PartyIdentification32"/>
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="InstrForCdtrAgt" type="InstructionForCreditorAgent1"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="InstrForDbtrAgt" type="Max140Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Purp" type="Purpose2Choice"/>
+ <xs:element maxOccurs="10" minOccurs="0" name="RgltryRptg" type="RegulatoryReporting3"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Tax" type="TaxInformation3"/>
+ <xs:element maxOccurs="10" minOccurs="0" name="RltdRmtInf" type="RemittanceLocation2"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="RmtInf" type="RemittanceInformation5"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="CreditorReferenceInformation2">
+ <xs:sequence>
+ <xs:element maxOccurs="1" minOccurs="0" name="Tp" type="CreditorReferenceType2"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Ref" type="Max35Text"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="CreditorReferenceType1Choice">
+ <xs:sequence>
+ <xs:choice>
+ <xs:element name="Cd" type="DocumentType3Code"/>
+ <xs:element name="Prtry" type="Max35Text"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="CreditorReferenceType2">
+ <xs:sequence>
+ <xs:element name="CdOrPrtry" type="CreditorReferenceType1Choice"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Issr" type="Max35Text"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="CustomerCreditTransferInitiationV03">
+ <xs:sequence>
+ <xs:element name="GrpHdr" type="GroupHeader32"/>
+ <xs:element maxOccurs="unbounded" minOccurs="1" name="PmtInf" type="PaymentInstructionInformation3"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="DateAndPlaceOfBirth">
+ <xs:sequence>
+ <xs:element name="BirthDt" type="ISODate"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="PrvcOfBirth" type="Max35Text"/>
+ <xs:element name="CityOfBirth" type="Max35Text"/>
+ <xs:element name="CtryOfBirth" type="CountryCode"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="DatePeriodDetails">
+ <xs:sequence>
+ <xs:element name="FrDt" type="ISODate"/>
+ <xs:element name="ToDt" type="ISODate"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="DecimalNumber">
+ <xs:restriction base="xs:decimal">
+ <xs:fractionDigits value="17"/>
+ <xs:totalDigits value="18"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="Document">
+ <xs:sequence>
+ <xs:element name="CstmrCdtTrfInitn" type="CustomerCreditTransferInitiationV03"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="DocumentAdjustment1">
+ <xs:sequence>
+ <xs:element name="Amt" type="ActiveOrHistoricCurrencyAndAmount"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="CdtDbtInd" type="CreditDebitCode"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Rsn" type="Max4Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="AddtlInf" type="Max140Text"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="DocumentType3Code">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="RADM"/>
+ <xs:enumeration value="RPIN"/>
+ <xs:enumeration value="FXDR"/>
+ <xs:enumeration value="DISP"/>
+ <xs:enumeration value="PUOR"/>
+ <xs:enumeration value="SCOR"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="DocumentType5Code">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="MSIN"/>
+ <xs:enumeration value="CNFA"/>
+ <xs:enumeration value="DNFA"/>
+ <xs:enumeration value="CINV"/>
+ <xs:enumeration value="CREN"/>
+ <xs:enumeration value="DEBN"/>
+ <xs:enumeration value="HIRI"/>
+ <xs:enumeration value="SBIN"/>
+ <xs:enumeration value="CMCN"/>
+ <xs:enumeration value="SOAC"/>
+ <xs:enumeration value="DISP"/>
+ <xs:enumeration value="BOLD"/>
+ <xs:enumeration value="VCHR"/>
+ <xs:enumeration value="AROI"/>
+ <xs:enumeration value="TSUT"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="EquivalentAmount2">
+ <xs:sequence>
+ <xs:element name="Amt" type="ActiveOrHistoricCurrencyAndAmount"/>
+ <xs:element name="CcyOfTrf" type="ActiveOrHistoricCurrencyCode"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="ExchangeRateInformation1">
+ <xs:sequence>
+ <xs:element maxOccurs="1" minOccurs="0" name="XchgRate" type="BaseOneRate"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="RateTp" type="ExchangeRateType1Code"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="CtrctId" type="Max35Text"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="ExchangeRateType1Code">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="SPOT"/>
+ <xs:enumeration value="SALE"/>
+ <xs:enumeration value="AGRD"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="ExternalAccountIdentification1Code">
+ <xs:restriction base="xs:string">
+ <xs:minLength value="1"/>
+ <xs:maxLength value="4"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="ExternalCategoryPurpose1Code">
+ <xs:restriction base="xs:string">
+ <xs:minLength value="1"/>
+ <xs:maxLength value="4"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="ExternalClearingSystemIdentification1Code">
+ <xs:restriction base="xs:string">
+ <xs:minLength value="1"/>
+ <xs:maxLength value="5"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="ExternalFinancialInstitutionIdentification1Code">
+ <xs:restriction base="xs:string">
+ <xs:minLength value="1"/>
+ <xs:maxLength value="4"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="ExternalLocalInstrument1Code">
+ <xs:restriction base="xs:string">
+ <xs:minLength value="1"/>
+ <xs:maxLength value="35"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="ExternalOrganisationIdentification1Code">
+ <xs:restriction base="xs:string">
+ <xs:minLength value="1"/>
+ <xs:maxLength value="4"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="ExternalPersonIdentification1Code">
+ <xs:restriction base="xs:string">
+ <xs:minLength value="1"/>
+ <xs:maxLength value="4"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="ExternalPurpose1Code">
+ <xs:restriction base="xs:string">
+ <xs:minLength value="1"/>
+ <xs:maxLength value="4"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="ExternalServiceLevel1Code">
+ <xs:restriction base="xs:string">
+ <xs:minLength value="1"/>
+ <xs:maxLength value="4"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="FinancialIdentificationSchemeName1Choice">
+ <xs:sequence>
+ <xs:choice>
+ <xs:element name="Cd" type="ExternalFinancialInstitutionIdentification1Code"/>
+ <xs:element name="Prtry" type="Max35Text"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="FinancialInstitutionIdentification7">
+ <xs:sequence>
+ <xs:element maxOccurs="1" minOccurs="0" name="BIC" type="BICIdentifier"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="ClrSysMmbId" type="ClearingSystemMemberIdentification2"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Nm" type="Max140Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="PstlAdr" type="PostalAddress6"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Othr" type="GenericFinancialIdentification1"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="GenericAccountIdentification1">
+ <xs:sequence>
+ <xs:element name="Id" type="Max34Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="SchmeNm" type="AccountSchemeName1Choice"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Issr" type="Max35Text"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="GenericFinancialIdentification1">
+ <xs:sequence>
+ <xs:element name="Id" type="Max35Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="SchmeNm" type="FinancialIdentificationSchemeName1Choice"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Issr" type="Max35Text"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="GenericOrganisationIdentification1">
+ <xs:sequence>
+ <xs:element name="Id" type="Max35Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="SchmeNm" type="OrganisationIdentificationSchemeName1Choice"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Issr" type="Max35Text"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="GenericPersonIdentification1">
+ <xs:sequence>
+ <xs:element name="Id" type="Max35Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="SchmeNm" type="PersonIdentificationSchemeName1Choice"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Issr" type="Max35Text"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="GroupHeader32">
+ <xs:sequence>
+ <xs:element name="MsgId" type="Max35Text"/>
+ <xs:element name="CreDtTm" type="ISODateTime"/>
+ <xs:element maxOccurs="2" minOccurs="0" name="Authstn" type="Authorisation1Choice"/>
+ <xs:element name="NbOfTxs" type="Max15NumericText"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="CtrlSum" type="DecimalNumber"/>
+ <xs:element name="InitgPty" type="PartyIdentification32"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="FwdgAgt" type="BranchAndFinancialInstitutionIdentification4"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="IBAN2007Identifier">
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[A-Z]{2,2}[0-9]{2,2}[a-zA-Z0-9]{1,30}"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="ISODate">
+ <xs:restriction base="xs:date"/>
+ </xs:simpleType>
+ <xs:simpleType name="ISODateTime">
+ <xs:restriction base="xs:dateTime"/>
+ </xs:simpleType>
+ <xs:simpleType name="Instruction3Code">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="CHQB"/>
+ <xs:enumeration value="HOLD"/>
+ <xs:enumeration value="PHOB"/>
+ <xs:enumeration value="TELB"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="InstructionForCreditorAgent1">
+ <xs:sequence>
+ <xs:element maxOccurs="1" minOccurs="0" name="Cd" type="Instruction3Code"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="InstrInf" type="Max140Text"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="LocalInstrument2Choice">
+ <xs:sequence>
+ <xs:choice>
+ <xs:element name="Cd" type="ExternalLocalInstrument1Code"/>
+ <xs:element name="Prtry" type="Max35Text"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="Max10Text">
+ <xs:restriction base="xs:string">
+ <xs:minLength value="1"/>
+ <xs:maxLength value="10"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="Max128Text">
+ <xs:restriction base="xs:string">
+ <xs:minLength value="1"/>
+ <xs:maxLength value="128"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="Max140Text">
+ <xs:restriction base="xs:string">
+ <xs:minLength value="1"/>
+ <xs:maxLength value="140"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="Max15NumericText">
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[0-9]{1,15}"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="Max16Text">
+ <xs:restriction base="xs:string">
+ <xs:minLength value="1"/>
+ <xs:maxLength value="16"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="Max2048Text">
+ <xs:restriction base="xs:string">
+ <xs:minLength value="1"/>
+ <xs:maxLength value="2048"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="Max34Text">
+ <xs:restriction base="xs:string">
+ <xs:minLength value="1"/>
+ <xs:maxLength value="34"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="Max35Text">
+ <xs:restriction base="xs:string">
+ <xs:minLength value="1"/>
+ <xs:maxLength value="35"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="Max4Text">
+ <xs:restriction base="xs:string">
+ <xs:minLength value="1"/>
+ <xs:maxLength value="4"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="Max70Text">
+ <xs:restriction base="xs:string">
+ <xs:minLength value="1"/>
+ <xs:maxLength value="70"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="NameAndAddress10">
+ <xs:sequence>
+ <xs:element name="Nm" type="Max140Text"/>
+ <xs:element name="Adr" type="PostalAddress6"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="NamePrefix1Code">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="DOCT"/>
+ <xs:enumeration value="MIST"/>
+ <xs:enumeration value="MISS"/>
+ <xs:enumeration value="MADM"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="Number">
+ <xs:restriction base="xs:decimal">
+ <xs:fractionDigits value="0"/>
+ <xs:totalDigits value="18"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="OrganisationIdentification4">
+ <xs:sequence>
+ <xs:element maxOccurs="1" minOccurs="0" name="BICOrBEI" type="AnyBICIdentifier"/>
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="Othr" type="GenericOrganisationIdentification1"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="OrganisationIdentificationSchemeName1Choice">
+ <xs:sequence>
+ <xs:choice>
+ <xs:element name="Cd" type="ExternalOrganisationIdentification1Code"/>
+ <xs:element name="Prtry" type="Max35Text"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="Party6Choice">
+ <xs:sequence>
+ <xs:choice>
+ <xs:element name="OrgId" type="OrganisationIdentification4"/>
+ <xs:element name="PrvtId" type="PersonIdentification5"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="PartyIdentification32">
+ <xs:sequence>
+ <xs:element maxOccurs="1" minOccurs="0" name="Nm" type="Max140Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="PstlAdr" type="PostalAddress6"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Id" type="Party6Choice"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="CtryOfRes" type="CountryCode"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="CtctDtls" type="ContactDetails2"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="PaymentIdentification1">
+ <xs:sequence>
+ <xs:element maxOccurs="1" minOccurs="0" name="InstrId" type="Max35Text"/>
+ <xs:element name="EndToEndId" type="Max35Text"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="PaymentInstructionInformation3">
+ <xs:sequence>
+ <xs:element name="PmtInfId" type="Max35Text"/>
+ <xs:element name="PmtMtd" type="PaymentMethod3Code"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="BtchBookg" type="BatchBookingIndicator"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="NbOfTxs" type="Max15NumericText"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="CtrlSum" type="DecimalNumber"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="PmtTpInf" type="PaymentTypeInformation19"/>
+ <xs:element name="ReqdExctnDt" type="ISODate"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="PoolgAdjstmntDt" type="ISODate"/>
+ <xs:element name="Dbtr" type="PartyIdentification32"/>
+ <xs:element name="DbtrAcct" type="CashAccount16"/>
+ <xs:element name="DbtrAgt" type="BranchAndFinancialInstitutionIdentification4"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="DbtrAgtAcct" type="CashAccount16"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="UltmtDbtr" type="PartyIdentification32"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="ChrgBr" type="ChargeBearerType1Code"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="ChrgsAcct" type="CashAccount16"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="ChrgsAcctAgt" type="BranchAndFinancialInstitutionIdentification4"/>
+ <xs:element maxOccurs="unbounded" minOccurs="1" name="CdtTrfTxInf" type="CreditTransferTransactionInformation10"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="PaymentMethod3Code">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="CHK"/>
+ <xs:enumeration value="TRF"/>
+ <xs:enumeration value="TRA"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="PaymentTypeInformation19">
+ <xs:sequence>
+ <xs:element maxOccurs="1" minOccurs="0" name="InstrPrty" type="Priority2Code"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="SvcLvl" type="ServiceLevel8Choice"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="LclInstrm" type="LocalInstrument2Choice"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="CtgyPurp" type="CategoryPurpose1Choice"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="PercentageRate">
+ <xs:restriction base="xs:decimal">
+ <xs:fractionDigits value="10"/>
+ <xs:totalDigits value="11"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="PersonIdentification5">
+ <xs:sequence>
+ <xs:element maxOccurs="1" minOccurs="0" name="DtAndPlcOfBirth" type="DateAndPlaceOfBirth"/>
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="Othr" type="GenericPersonIdentification1"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="PersonIdentificationSchemeName1Choice">
+ <xs:sequence>
+ <xs:choice>
+ <xs:element name="Cd" type="ExternalPersonIdentification1Code"/>
+ <xs:element name="Prtry" type="Max35Text"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="PhoneNumber">
+ <xs:restriction base="xs:string">
+ <xs:pattern value="\+[0-9]{1,3}-[0-9()+\-]{1,30}"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="PostalAddress6">
+ <xs:sequence>
+ <xs:element maxOccurs="1" minOccurs="0" name="AdrTp" type="AddressType2Code"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Dept" type="Max70Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="SubDept" type="Max70Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="StrtNm" type="Max70Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="BldgNb" type="Max16Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="PstCd" type="Max16Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="TwnNm" type="Max35Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="CtrySubDvsn" type="Max35Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Ctry" type="CountryCode"/>
+ <xs:element maxOccurs="7" minOccurs="0" name="AdrLine" type="Max70Text"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="Priority2Code">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="HIGH"/>
+ <xs:enumeration value="NORM"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="Purpose2Choice">
+ <xs:sequence>
+ <xs:choice>
+ <xs:element name="Cd" type="ExternalPurpose1Code"/>
+ <xs:element name="Prtry" type="Max35Text"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="ReferredDocumentInformation3">
+ <xs:sequence>
+ <xs:element maxOccurs="1" minOccurs="0" name="Tp" type="ReferredDocumentType2"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Nb" type="Max35Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="RltdDt" type="ISODate"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="ReferredDocumentType1Choice">
+ <xs:sequence>
+ <xs:choice>
+ <xs:element name="Cd" type="DocumentType5Code"/>
+ <xs:element name="Prtry" type="Max35Text"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="ReferredDocumentType2">
+ <xs:sequence>
+ <xs:element name="CdOrPrtry" type="ReferredDocumentType1Choice"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Issr" type="Max35Text"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="RegulatoryAuthority2">
+ <xs:sequence>
+ <xs:element maxOccurs="1" minOccurs="0" name="Nm" type="Max140Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Ctry" type="CountryCode"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="RegulatoryReporting3">
+ <xs:sequence>
+ <xs:element maxOccurs="1" minOccurs="0" name="DbtCdtRptgInd" type="RegulatoryReportingType1Code"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Authrty" type="RegulatoryAuthority2"/>
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="Dtls" type="StructuredRegulatoryReporting3"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="RegulatoryReportingType1Code">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="CRED"/>
+ <xs:enumeration value="DEBT"/>
+ <xs:enumeration value="BOTH"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="RemittanceAmount1">
+ <xs:sequence>
+ <xs:element maxOccurs="1" minOccurs="0" name="DuePyblAmt" type="ActiveOrHistoricCurrencyAndAmount"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="DscntApldAmt" type="ActiveOrHistoricCurrencyAndAmount"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="CdtNoteAmt" type="ActiveOrHistoricCurrencyAndAmount"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="TaxAmt" type="ActiveOrHistoricCurrencyAndAmount"/>
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="AdjstmntAmtAndRsn" type="DocumentAdjustment1"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="RmtdAmt" type="ActiveOrHistoricCurrencyAndAmount"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="RemittanceInformation5">
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="Ustrd" type="Max140Text"/>
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="Strd" type="StructuredRemittanceInformation7"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="RemittanceLocation2">
+ <xs:sequence>
+ <xs:element maxOccurs="1" minOccurs="0" name="RmtId" type="Max35Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="RmtLctnMtd" type="RemittanceLocationMethod2Code"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="RmtLctnElctrncAdr" type="Max2048Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="RmtLctnPstlAdr" type="NameAndAddress10"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="RemittanceLocationMethod2Code">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="FAXI"/>
+ <xs:enumeration value="EDIC"/>
+ <xs:enumeration value="URID"/>
+ <xs:enumeration value="EMAL"/>
+ <xs:enumeration value="POST"/>
+ <xs:enumeration value="SMSM"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:complexType name="ServiceLevel8Choice">
+ <xs:sequence>
+ <xs:choice>
+ <xs:element name="Cd" type="ExternalServiceLevel1Code"/>
+ <xs:element name="Prtry" type="Max35Text"/>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="StructuredRegulatoryReporting3">
+ <xs:sequence>
+ <xs:element maxOccurs="1" minOccurs="0" name="Tp" type="Max35Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Dt" type="ISODate"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Ctry" type="CountryCode"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Cd" type="Max10Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Amt" type="ActiveOrHistoricCurrencyAndAmount"/>
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="Inf" type="Max35Text"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="StructuredRemittanceInformation7">
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="RfrdDocInf" type="ReferredDocumentInformation3"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="RfrdDocAmt" type="RemittanceAmount1"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="CdtrRefInf" type="CreditorReferenceInformation2"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Invcr" type="PartyIdentification32"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Invcee" type="PartyIdentification32"/>
+ <xs:element maxOccurs="3" minOccurs="0" name="AddtlRmtInf" type="Max140Text"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TaxAmount1">
+ <xs:sequence>
+ <xs:element maxOccurs="1" minOccurs="0" name="Rate" type="PercentageRate"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="TaxblBaseAmt" type="ActiveOrHistoricCurrencyAndAmount"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="TtlAmt" type="ActiveOrHistoricCurrencyAndAmount"/>
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="Dtls" type="TaxRecordDetails1"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TaxAuthorisation1">
+ <xs:sequence>
+ <xs:element maxOccurs="1" minOccurs="0" name="Titl" type="Max35Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Nm" type="Max140Text"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TaxInformation3">
+ <xs:sequence>
+ <xs:element maxOccurs="1" minOccurs="0" name="Cdtr" type="TaxParty1"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Dbtr" type="TaxParty2"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="AdmstnZn" type="Max35Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="RefNb" type="Max140Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Mtd" type="Max35Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="TtlTaxblBaseAmt" type="ActiveOrHistoricCurrencyAndAmount"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="TtlTaxAmt" type="ActiveOrHistoricCurrencyAndAmount"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Dt" type="ISODate"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="SeqNb" type="Number"/>
+ <xs:element maxOccurs="unbounded" minOccurs="0" name="Rcrd" type="TaxRecord1"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TaxParty1">
+ <xs:sequence>
+ <xs:element maxOccurs="1" minOccurs="0" name="TaxId" type="Max35Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="RegnId" type="Max35Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="TaxTp" type="Max35Text"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TaxParty2">
+ <xs:sequence>
+ <xs:element maxOccurs="1" minOccurs="0" name="TaxId" type="Max35Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="RegnId" type="Max35Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="TaxTp" type="Max35Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Authstn" type="TaxAuthorisation1"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TaxPeriod1">
+ <xs:sequence>
+ <xs:element maxOccurs="1" minOccurs="0" name="Yr" type="ISODate"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Tp" type="TaxRecordPeriod1Code"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="FrToDt" type="DatePeriodDetails"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TaxRecord1">
+ <xs:sequence>
+ <xs:element maxOccurs="1" minOccurs="0" name="Tp" type="Max35Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Ctgy" type="Max35Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="CtgyDtls" type="Max35Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="DbtrSts" type="Max35Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="CertId" type="Max35Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="FrmsCd" type="Max35Text"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="Prd" type="TaxPeriod1"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="TaxAmt" type="TaxAmount1"/>
+ <xs:element maxOccurs="1" minOccurs="0" name="AddtlInf" type="Max140Text"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:complexType name="TaxRecordDetails1">
+ <xs:sequence>
+ <xs:element maxOccurs="1" minOccurs="0" name="Prd" type="TaxPeriod1"/>
+ <xs:element name="Amt" type="ActiveOrHistoricCurrencyAndAmount"/>
+ </xs:sequence>
+ </xs:complexType>
+ <xs:simpleType name="TaxRecordPeriod1Code">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="MM01"/>
+ <xs:enumeration value="MM02"/>
+ <xs:enumeration value="MM03"/>
+ <xs:enumeration value="MM04"/>
+ <xs:enumeration value="MM05"/>
+ <xs:enumeration value="MM06"/>
+ <xs:enumeration value="MM07"/>
+ <xs:enumeration value="MM08"/>
+ <xs:enumeration value="MM09"/>
+ <xs:enumeration value="MM10"/>
+ <xs:enumeration value="MM11"/>
+ <xs:enumeration value="MM12"/>
+ <xs:enumeration value="QTR1"/>
+ <xs:enumeration value="QTR2"/>
+ <xs:enumeration value="QTR3"/>
+ <xs:enumeration value="QTR4"/>
+ <xs:enumeration value="HLF1"/>
+ <xs:enumeration value="HLF2"/>
+ </xs:restriction>
+ </xs:simpleType>
+</xs:schema>
Follow ups