[tryton-debian-vcs] tryton-modules-account-payment-sepa branch upstream updated. upstream/3.4.1-1-ged4d9d8

Mathias Behrle tryton-debian-vcs at alioth.debian.org
Thu Apr 23 15:56:51 UTC 2015


The following commit has been merged in the upstream branch:
https://alioth.debian.org/plugins/scmgit/cgi-bin/gitweb.cgi/?p=tryton/tryton-modules-account-payment-sepa.git;a=commitdiff;h=upstream/3.4.1-1-ged4d9d8

commit ed4d9d8dbb787927ba7face5ee01c8ed05163743
Author: Mathias Behrle <mathiasb at m9s.biz>
Date:   Thu Apr 23 16:59:51 2015 +0200

    Adding upstream version 3.6.0.
    
    Signed-off-by: Mathias Behrle <mathiasb at m9s.biz>

diff --git a/CHANGELOG b/CHANGELOG
index 39d44f3..7dff6f2 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,10 @@
-Version 3.4.1 - 2015-03-01
+Version 3.6.0 - 2015-04-20
 * Bug fixes (see mercurial logs for details)
+* Add support for PyPy
+* Use value date of camt.054 as clearing date
+* Allow to re-generate message of a payment group
+* Use right sequence type in case of previous rejected payments
+* Add pain.001.003.03 and pain.008.003.02 flavors
 
 Version 3.4.0 - 2014-10-20
 * Bug fixes (see mercurial logs for details)
diff --git a/INSTALL b/INSTALL
index 1341054..523986f 100644
--- a/INSTALL
+++ b/INSTALL
@@ -6,6 +6,7 @@ Prerequisites
 
  * Python 2.7 or later (http://www.python.org/)
  * Genshi (http://genshi.edgewall.org/)
+ * python-dateutil (https://dateutil.readthedocs.org/)
  * trytond (http://www.tryton.org/)
  * trytond_party (http://www.tryton.org/)
  * trytond_account_payment (http://www.tryton.org/)
diff --git a/PKG-INFO b/PKG-INFO
index 5a270b1..4a40a90 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,12 +1,12 @@
 Metadata-Version: 1.1
 Name: trytond_account_payment_sepa
-Version: 3.4.1
+Version: 3.6.0
 Summary: Tryton module for SEPA payment
 Home-page: http://www.tryton.org/
 Author: Tryton
 Author-email: issue_tracker at tryton.org
 License: GPL-3
-Download-URL: http://downloads.tryton.org/3.4/
+Download-URL: http://downloads.tryton.org/3.6/
 Description: trytond_account_payment_sepa
         ============================
         
@@ -64,5 +64,7 @@ Classifier: Natural Language :: Slovenian
 Classifier: Natural Language :: Spanish
 Classifier: Operating System :: OS Independent
 Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: Implementation :: CPython
+Classifier: Programming Language :: Python :: Implementation :: PyPy
 Classifier: Topic :: Office/Business
 Classifier: Topic :: Office/Business :: Financial :: Accounting
diff --git a/__init__.py b/__init__.py
index 6b0570d..5ac6d23 100644
--- a/__init__.py
+++ b/__init__.py
@@ -1,5 +1,5 @@
-#This file is part of Tryton.  The COPYRIGHT file at the top level of
-#this repository contains the full copyright notices and license terms.
+# This file is part of Tryton.  The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
 from trytond.pool import Pool
 from .payment import *
 from .party import *
diff --git a/account.py b/account.py
index 5e3f57b..da88600 100644
--- a/account.py
+++ b/account.py
@@ -1,7 +1,8 @@
-#This file is part of Tryton.  The COPYRIGHT file at the top level of
-#this repository contains the full copyright notices and license terms.
+# This file is part of Tryton.  The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
 from trytond.pool import PoolMeta
 from trytond.model import fields
+from trytond.pyson import Eval
 
 __all__ = ['Configuration']
 __metaclass__ = PoolMeta
@@ -12,4 +13,6 @@ class Configuration:
     sepa_mandate_sequence = fields.Property(fields.Many2One('ir.sequence',
             'SEPA Mandate Sequence', domain=[
                 ('code', '=', 'account.payment.sepa.mandate'),
+                ('company', 'in', [Eval('context', {}).get('company', -1),
+                        None]),
                 ]))
diff --git a/account.xml b/account.xml
index ec6a1d9..035654e 100644
--- a/account.xml
+++ b/account.xml
@@ -8,7 +8,9 @@ this repository contains the full copyright notices and license terms. -->
             id="act_move_line_form_domain_receivable_mandate">
             <field name="name">Receivable with Mandate</field>
             <field name="sequence" eval="25"/>
-            <field name="domain">['AND', ['OR', ('debit', '>', 0), ('credit', '<', 0)], ('party.sepa_mandates', '!=', None)]</field>
+            <field name="domain"
+                eval="['AND', ['OR', ('debit', '>', 0), ('credit', '<', 0)], ('party.sepa_mandates', '!=', None)]"
+                pyson="1"/>
             <field name="act_window" ref="account_payment.act_move_line_form"/>
         </record>
 
diff --git a/locale/ca_ES.po b/locale/ca_ES.po
index 7964207..d3cf77a 100644
--- a/locale/ca_ES.po
+++ b/locale/ca_ES.po
@@ -233,7 +233,7 @@ msgstr "Cancel·lat"
 
 msgctxt "model:ir.action.act_window.domain,name:act_message_form_domain_done"
 msgid "Done"
-msgstr "Realitzat"
+msgstr "Finalitzat"
 
 msgctxt "model:ir.action.act_window.domain,name:act_message_form_domain_draft"
 msgid "Draft"
@@ -451,7 +451,7 @@ msgstr "Cancel·lat"
 
 msgctxt "selection:account.payment.sepa.message,state:"
 msgid "Done"
-msgstr "Realitzat"
+msgstr "Finalitzat"
 
 msgctxt "selection:account.payment.sepa.message,state:"
 msgid "Draft"
@@ -469,6 +469,10 @@ msgctxt "selection:account.payment.sepa.message,type:"
 msgid "OUT"
 msgstr "Sortida"
 
+msgctxt "view:account.payment.group:"
+msgid "Generate Message"
+msgstr "Missatge generat"
+
 msgctxt "view:account.payment.journal:"
 msgid "SEPA"
 msgstr "SEPA"
diff --git a/locale/de_DE.po b/locale/de_DE.po
index e3580a5..0688785 100644
--- a/locale/de_DE.po
+++ b/locale/de_DE.po
@@ -466,6 +466,10 @@ msgctxt "selection:account.payment.sepa.message,type:"
 msgid "OUT"
 msgstr "OUT"
 
+msgctxt "view:account.payment.group:"
+msgid "Generate Message"
+msgstr "Nachricht erzeugen"
+
 msgctxt "view:account.payment.journal:"
 msgid "SEPA"
 msgstr "SEPA"
@@ -500,7 +504,7 @@ msgstr "Prüfen"
 
 msgctxt "view:account.payment.sepa.message:"
 msgid "Cancel"
-msgstr "Annulliert"
+msgstr "Annullieren"
 
 msgctxt "view:account.payment.sepa.message:"
 msgid "Do"
diff --git a/locale/es_AR.po b/locale/es_AR.po
index 45c6fd2..28909a8 100644
--- a/locale/es_AR.po
+++ b/locale/es_AR.po
@@ -465,6 +465,10 @@ msgctxt "selection:account.payment.sepa.message,type:"
 msgid "OUT"
 msgstr "SALIDA"
 
+msgctxt "view:account.payment.group:"
+msgid "Generate Message"
+msgstr "Generar mensaje"
+
 msgctxt "view:account.payment.journal:"
 msgid "SEPA"
 msgstr "Área Única de Pagos en Euros (SEPA)"
diff --git a/locale/es_CO.po b/locale/es_CO.po
index 20fe05c..e9d49f4 100644
--- a/locale/es_CO.po
+++ b/locale/es_CO.po
@@ -102,7 +102,7 @@ msgstr "Identificación de Solo Lectura"
 
 msgctxt "field:account.payment.sepa.mandate,party:"
 msgid "Party"
-msgstr "Terceros"
+msgstr "Tercero"
 
 msgctxt "field:account.payment.sepa.mandate,payments:"
 msgid "Payments"
@@ -178,7 +178,7 @@ msgstr "Tipo"
 
 msgctxt "field:account.payment.sepa.message,write_date:"
 msgid "Write Date"
-msgstr "Modificado por Usuario"
+msgstr "Fecha de Modificación"
 
 msgctxt "field:account.payment.sepa.message,write_uid:"
 msgid "Write User"
@@ -463,6 +463,10 @@ msgctxt "selection:account.payment.sepa.message,type:"
 msgid "OUT"
 msgstr "SALIDA"
 
+msgctxt "view:account.payment.group:"
+msgid "Generate Message"
+msgstr "Generar Mensaje"
+
 msgctxt "view:account.payment.journal:"
 msgid "SEPA"
 msgstr "SEPA"
diff --git a/locale/es_EC.po b/locale/es_EC.po
index 0d938ef..d7793e7 100644
--- a/locale/es_EC.po
+++ b/locale/es_EC.po
@@ -465,6 +465,10 @@ msgctxt "selection:account.payment.sepa.message,type:"
 msgid "OUT"
 msgstr "Salida"
 
+msgctxt "view:account.payment.group:"
+msgid "Generate Message"
+msgstr "Generar mensaje"
+
 msgctxt "view:account.payment.journal:"
 msgid "SEPA"
 msgstr "SEPA"
diff --git a/locale/es_ES.po b/locale/es_ES.po
index 9313192..ac4e247 100644
--- a/locale/es_ES.po
+++ b/locale/es_ES.po
@@ -233,7 +233,7 @@ msgstr "Cancelado"
 
 msgctxt "model:ir.action.act_window.domain,name:act_message_form_domain_done"
 msgid "Done"
-msgstr "Realizado"
+msgstr "Finalizado"
 
 msgctxt "model:ir.action.act_window.domain,name:act_message_form_domain_draft"
 msgid "Draft"
@@ -449,7 +449,7 @@ msgstr "Cancelado"
 
 msgctxt "selection:account.payment.sepa.message,state:"
 msgid "Done"
-msgstr "Realizado"
+msgstr "Finalizado"
 
 msgctxt "selection:account.payment.sepa.message,state:"
 msgid "Draft"
@@ -467,6 +467,10 @@ msgctxt "selection:account.payment.sepa.message,type:"
 msgid "OUT"
 msgstr "Salida"
 
+msgctxt "view:account.payment.group:"
+msgid "Generate Message"
+msgstr "Generar mensaje"
+
 msgctxt "view:account.payment.journal:"
 msgid "SEPA"
 msgstr "SEPA"
diff --git a/locale/fr_FR.po b/locale/fr_FR.po
index 6e21205..5499bb9 100644
--- a/locale/fr_FR.po
+++ b/locale/fr_FR.po
@@ -465,6 +465,10 @@ msgctxt "selection:account.payment.sepa.message,type:"
 msgid "OUT"
 msgstr "Sortant"
 
+msgctxt "view:account.payment.group:"
+msgid "Generate Message"
+msgstr "Générer le message"
+
 msgctxt "view:account.payment.journal:"
 msgid "SEPA"
 msgstr "SEPA"
diff --git a/locale/sl_SI.po b/locale/sl_SI.po
index 5db1d7f..34c380e 100644
--- a/locale/sl_SI.po
+++ b/locale/sl_SI.po
@@ -18,7 +18,7 @@ msgstr "Soglasja \"%s\" ni možno zbrisati, ker ni v pripravi ali preklicano."
 
 msgctxt "field:account.configuration,sepa_mandate_sequence:"
 msgid "SEPA Mandate Sequence"
-msgstr "Štetje soglasij SEPA"
+msgstr "Štetje SEPA soglasij"
 
 msgctxt "field:account.payment,sepa_end_to_end_id:"
 msgid "SEPA End To End ID"
@@ -26,7 +26,7 @@ msgstr "ID SEPA End-to-End "
 
 msgctxt "field:account.payment,sepa_instruction_id:"
 msgid "SEPA Instruction ID"
-msgstr "ID navodila SEPA"
+msgstr "ID SEPA navodila"
 
 msgctxt "field:account.payment,sepa_mandate:"
 msgid "Mandate"
@@ -46,7 +46,7 @@ msgstr "Podrobnosti razloga zavrnitve"
 
 msgctxt "field:account.payment.group,sepa_messages:"
 msgid "SEPA Messages"
-msgstr "Sporočila SEPA"
+msgstr "SEPA sporočilo"
 
 msgctxt "field:account.payment.journal,company_party:"
 msgid "Company Party"
@@ -126,7 +126,7 @@ msgstr "Stanje"
 
 msgctxt "field:account.payment.sepa.mandate,type:"
 msgid "Type"
-msgstr "Vrsta"
+msgstr "Tip"
 
 msgctxt "field:account.payment.sepa.mandate,write_date:"
 msgid "Write Date"
@@ -174,7 +174,7 @@ msgstr "Stanje"
 
 msgctxt "field:account.payment.sepa.message,type:"
 msgid "Type"
-msgstr "Vrsta"
+msgstr "Tip"
 
 msgctxt "field:account.payment.sepa.message,write_date:"
 msgid "Write Date"
@@ -186,27 +186,27 @@ msgstr "Zapisal"
 
 msgctxt "field:party.party,sepa_creditor_identifier:"
 msgid "SEPA Creditor Identifier"
-msgstr "Identifikacija upnika SEPA"
+msgstr "Identifikacija  SEPA upnika"
 
 msgctxt "field:party.party,sepa_creditor_identifier_used:"
 msgid "SEPA Creditor Identifier Used"
-msgstr "Uporabljena Identifikacija upnika SEPA"
+msgstr "Uporabljena Identifikacija SEPA upnika"
 
 msgctxt "field:party.party,sepa_mandates:"
 msgid "SEPA Mandates"
-msgstr "Soglasja SEPA"
+msgstr "SEPA soglasja"
 
 msgctxt "model:account.payment.sepa.mandate,name:"
 msgid "SEPA Mandate"
-msgstr "Soglasje SEPA"
+msgstr "SEPA soglasje"
 
 msgctxt "model:account.payment.sepa.message,name:"
 msgid "SEPA Message"
-msgstr "Sporočilo SEPA"
+msgstr "SEPA sporočilo"
 
 msgctxt "model:ir.action,name:act_mandate_form"
 msgid "SEPA Mandates"
-msgstr "Soglasja SEPA"
+msgstr "SEPA soglasja"
 
 msgctxt "model:ir.action,name:act_mandate_form2"
 msgid "Mandates"
@@ -214,7 +214,7 @@ msgstr "Soglasja"
 
 msgctxt "model:ir.action,name:act_message_form"
 msgid "SEPA Messages"
-msgstr "Sporočila SEPA"
+msgstr "SEPA sporočilo"
 
 msgctxt "model:ir.action,name:report_mandate"
 msgid "Mandate"
@@ -235,7 +235,7 @@ msgstr "Zaključeno"
 
 msgctxt "model:ir.action.act_window.domain,name:act_message_form_domain_draft"
 msgid "Draft"
-msgstr "V pripravi"
+msgstr "Priprava"
 
 msgctxt ""
 "model:ir.action.act_window.domain,name:act_message_form_domain_waiting"
@@ -249,15 +249,15 @@ msgstr "Terjatve s soglasjem"
 
 msgctxt "model:ir.sequence.type,name:sequence_type_mandate"
 msgid "SEPA Mandate"
-msgstr "Soglasje SEPA"
+msgstr "SEPA soglasje"
 
 msgctxt "model:ir.ui.menu,name:menu_mandate_form"
 msgid "SEPA Mandates"
-msgstr "Soglasja SEPA"
+msgstr "SEPA soglasja"
 
 msgctxt "model:ir.ui.menu,name:menu_message_form"
 msgid "SEPA Messages"
-msgstr "Sporočila SEPA"
+msgstr "SEPA sporočilo"
 
 msgctxt "odt:account.payment.sepa.mandate:"
 msgid "."
@@ -312,7 +312,7 @@ msgstr "Datum"
 
 msgctxt "odt:account.payment.sepa.mandate:"
 msgid "Direct Debit MANDATE"
-msgstr "Soglasje direktne obremenitve"
+msgstr "Soglasje direktne bremenitve"
 
 msgctxt "odt:account.payment.sepa.mandate:"
 msgid "E-Mail:"
@@ -462,6 +462,10 @@ msgctxt "selection:account.payment.sepa.message,type:"
 msgid "OUT"
 msgstr "Izhod"
 
+msgctxt "view:account.payment.group:"
+msgid "Generate Message"
+msgstr "Izdelava sporočila"
+
 msgctxt "view:account.payment.journal:"
 msgid "SEPA"
 msgstr "SEPA"
@@ -504,15 +508,15 @@ msgstr "Izvedi"
 
 msgctxt "view:account.payment.sepa.message:"
 msgid "Draft"
-msgstr "V pripravi"
+msgstr "Priprava"
 
 msgctxt "view:account.payment.sepa.message:"
 msgid "SEPA Message"
-msgstr "Sporočilo SEPA"
+msgstr "SEPA sporočilo"
 
 msgctxt "view:account.payment.sepa.message:"
 msgid "SEPA Messages"
-msgstr "Sporočila SEPA"
+msgstr "SEPA sporočilo"
 
 msgctxt "view:account.payment.sepa.message:"
 msgid "Wait"
diff --git a/mandate.odt b/mandate.odt
index ac7e364..44937ce 100644
Binary files a/mandate.odt and b/mandate.odt differ
diff --git a/party.py b/party.py
index 5154440..944635e 100644
--- a/party.py
+++ b/party.py
@@ -1,5 +1,5 @@
-#This file is part of Tryton.  The COPYRIGHT file at the top level of
-#this repository contains the full copyright notices and license terms.
+# This file is part of Tryton.  The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
 from trytond.pool import PoolMeta
 from trytond.model import fields
 
diff --git a/party.xml b/party.xml
index 8783a35..688d00c 100644
--- a/party.xml
+++ b/party.xml
@@ -11,7 +11,8 @@ this repository contains the full copyright notices and license terms. -->
         <record model="ir.action.act_window" id="act_mandate_form2">
             <field name="name">Mandates</field>
             <field name="res_model">account.payment.sepa.mandate</field>
-            <field name="domain">[("party", "=", Eval('active_id'))]</field>
+            <field name="domain"
+                eval="[('party', '=', Eval('active_id'))]" pyson="1"/>
         </record>
         <record model="ir.action.act_window.view" id="act_mandate_form2_view1">
             <field name="sequence" eval="10"/>
diff --git a/payment.py b/payment.py
index 6ce3d7c..4d6da05 100644
--- a/payment.py
+++ b/payment.py
@@ -1,7 +1,8 @@
-#This file is part of Tryton.  The COPYRIGHT file at the top level of
-#this repository contains the full copyright notices and license terms.
+# This file is part of Tryton.  The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
 import datetime
 import os
+import unicodedata
 from itertools import groupby
 from io import BytesIO
 
@@ -11,7 +12,7 @@ from lxml import etree
 from sql import Literal
 
 from trytond.pool import PoolMeta, Pool
-from trytond.model import ModelSQL, ModelView, Workflow, fields
+from trytond.model import ModelSQL, ModelView, Workflow, fields, dualmethod
 from trytond.pyson import Eval, If
 from trytond.transaction import Transaction
 from trytond.tools import reduce_ids, grouped_slice
@@ -43,6 +44,7 @@ class Journal:
             (None, ''),
             ('pain.001.001.03', 'pain.001.001.03'),
             ('pain.001.001.05', 'pain.001.001.05'),
+            ('pain.001.003.03', 'pain.001.003.03'),
             ], 'Payable Flavor', states={
             'required': Eval('process_method') == 'sepa',
             'invisible': Eval('process_method') != 'sepa',
@@ -53,6 +55,7 @@ class Journal:
             (None, ''),
             ('pain.008.001.02', 'pain.008.001.02'),
             ('pain.008.001.04', 'pain.008.001.04'),
+            ('pain.008.003.02', 'pain.008.003.02'),
             ], 'Receivable Flavor', states={
             'required': Eval('process_method') == 'sepa',
             'invisible': Eval('process_method') != 'sepa',
@@ -127,6 +130,9 @@ class Group:
         cls._error_messages.update({
                 'no_mandate': 'No valid mandate for payment "%s"',
                 })
+        cls._buttons.update({
+                'generate_message': {},
+                })
 
     def get_sepa_template(self):
         if self.kind == 'payable':
@@ -137,11 +143,9 @@ class Group:
     def process_sepa(self):
         pool = Pool()
         Payment = pool.get('account.payment')
-        Message = pool.get('account.payment.sepa.message')
         if self.kind == 'receivable':
-            payments = [p for p in self.payments if not p.sepa_mandate]
-            mandates = Payment.get_sepa_mandates(payments)
-            for payment, mandate in zip(payments, mandates):
+            mandates = Payment.get_sepa_mandates(self.payments)
+            for payment, mandate in zip(self.payments, mandates):
                 if not mandate:
                     self.raise_user_error('no_mandate', payment.rec_name)
                 # Write one by one becasue mandate.sequence_type must be
@@ -150,15 +154,27 @@ class Group:
                         'sepa_mandate': mandate,
                         'sepa_mandate_sequence_type': mandate.sequence_type,
                         })
-        tmpl = self.get_sepa_template()
-        if not tmpl:
-            raise NotImplementedError
-        if not self.sepa_messages:
-            self.sepa_messages = ()
-        message = tmpl.generate(group=self,
-            datetime=datetime).filter(remove_comment).render()
-        message = Message(message=message, type='out', state='waiting')
-        self.sepa_messages += (message,)
+        self.generate_message(_save=False)
+
+    @dualmethod
+    @ModelView.button
+    def generate_message(cls, groups, _save=True):
+        pool = Pool()
+        Message = pool.get('account.payment.sepa.message')
+        for group in groups:
+            tmpl = group.get_sepa_template()
+            if not tmpl:
+                raise NotImplementedError
+            if not group.sepa_messages:
+                group.sepa_messages = ()
+            message = tmpl.generate(group=group,
+                datetime=datetime, normalize=unicodedata.normalize,
+                ).filter(remove_comment).render()
+            message = Message(message=message, type='out', state='waiting',
+                company=group.company)
+            group.sepa_messages += (message,)
+        if _save:
+            cls.save(groups)
 
     @property
     def sepa_initiating_party(self):
@@ -192,8 +208,9 @@ class Payment:
         ondelete='RESTRICT',
         domain=[
             ('party', '=', Eval('party', -1)),
+            ('company', '=', Eval('company', -1)),
             ],
-        depends=['party'])
+        depends=['party', 'company'])
     sepa_mandate_sequence_type = fields.Char('Mandate Sequence Type',
         readonly=True)
     sepa_return_reason_code = fields.Char('Return Reason Code', readonly=True,
@@ -215,14 +232,27 @@ class Payment:
         'get_sepa_instruction_id', searcher='search_sepa_instruction_id')
 
     @classmethod
+    def copy(cls, payments, default=None):
+        if default is None:
+            default = {}
+        default.setdefault('sepa_mandate_sequence_type', None)
+        return super(Payment, cls).copy(payments, default=default)
+
+    @classmethod
     def get_sepa_mandates(cls, payments):
         mandates = []
         for payment in payments:
-            for mandate in payment.party.sepa_mandates:
-                if mandate.is_valid:
-                    break
+            if payment.sepa_mandate:
+                if payment.sepa_mandate.is_valid:
+                    mandate = payment.sepa_mandate
+                else:
+                    mandate = None
             else:
-                mandate = None
+                for mandate in payment.party.sepa_mandates:
+                    if mandate.is_valid:
+                        break
+                else:
+                    mandate = None
             mandates.append(mandate)
         return mandates
 
@@ -233,7 +263,7 @@ class Payment:
     def search_end_to_end_id(cls, name, domain):
         table = cls.__table__()
         _, operator, value = domain
-        cast = cls.sepa_end_to_end_id._field.sql_type().base
+        cast = cls.sepa_end_to_end_id.sql_type().base
         Operator = fields.SQL_OPERATORS[operator]
         query = table.select(table.id,
             where=Operator(table.id.cast(cast), value))
@@ -260,6 +290,17 @@ class Payment:
                     if number.type == 'iban':
                         return number
 
+    @property
+    def rejected(self):
+        return (self.state == 'failed'
+            and self.sepa_return_reason_code
+            and self.sepa_return_reason_information == '/RTYP/RJCT')
+
+    def create_clearing_move(self, date=None):
+        if not date:
+            date = Transaction().context.get('date_value')
+        return super(Payment, self).create_clearing_move(date=date)
+
 
 class Mandate(Workflow, ModelSQL, ModelView):
     'SEPA Mandate'
@@ -271,6 +312,7 @@ class Mandate(Workflow, ModelSQL, ModelView):
             },
         depends=['state'])
     account_number = fields.Many2One('bank.account.number', 'Account Number',
+        ondelete='RESTRICT',
         states={
             'readonly': Eval('state').in_(['validated', 'canceled']),
             'required': Eval('state') == 'validated',
@@ -443,7 +485,9 @@ class Mandate(Workflow, ModelSQL, ModelView):
     def sequence_type(self):
         if self.type == 'one-off':
             return 'OOFF'
-        elif not self.payments:
+        elif (not self.payments
+                or all(not p.sepa_mandate_sequence_type for p in self.payments)
+                or all(p.rejected for p in self.payments)):
             return 'FRST'
         # TODO manage FNAL
         else:
diff --git a/payment.xml b/payment.xml
index 751007e..87b796c 100644
--- a/payment.xml
+++ b/payment.xml
@@ -55,10 +55,19 @@ this repository contains the full copyright notices and license terms. -->
             <field name="global_p" eval="True"/>
         </record>
         <record model="ir.rule" id="rule_payment1">
-            <field name="domain">[('company', '=', user.company.id if user.company else None)]</field>
+            <field name="domain"
+                eval="[('company', '=', Eval('user', {}).get('company', None))]"
+                pyson="1"/>
             <field name="rule_group" ref="rule_group_mandate"/>
         </record>
 
+        <record model="ir.model.access" id="access_mandate">
+            <field name="model" search="[('model', '=', 'account.payment.sepa.mandate')]"/>
+            <field name="perm_read" eval="False"/>
+            <field name="perm_write" eval="False"/>
+            <field name="perm_create" eval="False"/>
+            <field name="perm_delete" eval="False"/>
+        </record>
         <record model="ir.model.access" id="access_mandate_account_admin">
             <field name="model" search="[('model', '=', 'account.payment.sepa.mandate')]"/>
             <field name="group" ref="account.group_account_admin"/>
@@ -121,25 +130,25 @@ this repository contains the full copyright notices and license terms. -->
         <record model="ir.action.act_window.domain" id="act_message_form_domain_draft">
             <field name="name">Draft</field>
             <field name="sequence" eval="10"/>
-            <field name="domain">[('state', '=', 'draft')]</field>
+            <field name="domain" eval="[('state', '=', 'draft')]" pyson="1"/>
             <field name="act_window" ref="act_message_form"/>
         </record>
         <record model="ir.action.act_window.domain" id="act_message_form_domain_waiting">
             <field name="name">Waiting</field>
             <field name="sequence" eval="20"/>
-            <field name="domain">[('state', '=', 'waiting')]</field>
+            <field name="domain" eval="[('state', '=', 'waiting')]" pyson="1"/>
             <field name="act_window" ref="act_message_form"/>
         </record>
         <record model="ir.action.act_window.domain" id="act_message_form_domain_done">
             <field name="name">Done</field>
             <field name="sequence" eval="30"/>
-            <field name="domain">[('state', '=', 'done')]</field>
+            <field name="domain" eval="[('state', '=', 'done')]" pyson="1"/>
             <field name="act_window" ref="act_message_form"/>
         </record>
         <record model="ir.action.act_window.domain" id="act_message_form_domain_canceled">
             <field name="name">Canceled</field>
             <field name="sequence" eval="40"/>
-            <field name="domain">[('state', '=', 'canceled')]</field>
+            <field name="domain" eval="[('state', '=', 'canceled')]" pyson="1"/>
             <field name="act_window" ref="act_message_form"/>
         </record>
         <record model="ir.action.act_window.domain" id="act_message_form_domain_all">
@@ -157,10 +166,20 @@ this repository contains the full copyright notices and license terms. -->
             <field name="global_p" eval="True"/>
         </record>
         <record model="ir.rule" id="rule_message1">
-            <field name="domain">[('company', '=', user.company.id if user.company else None)]</field>
+            <field name="domain"
+                eval="[('company', '=', Eval('user', {}).get('company', None))]"
+                pyson="1"/>
             <field name="rule_group" ref="rule_group_message"/>
         </record>
 
+        <record model="ir.model.access" id="access_message">
+            <field name="model"
+                search="[('model', '=', 'account.payment.sepa.message')]"/>
+            <field name="perm_read" eval="False"/>
+            <field name="perm_write" eval="False"/>
+            <field name="perm_create" eval="False"/>
+            <field name="perm_delete" eval="False"/>
+        </record>
         <record model="ir.model.access" id="access_message_account_admin">
             <field name="model" search="[('model', '=', 'account.payment.sepa.message')]"/>
             <field name="group" ref="account.group_account_admin"/>
diff --git a/sepa_handler.py b/sepa_handler.py
index 7c4271c..2360b1d 100644
--- a/sepa_handler.py
+++ b/sepa_handler.py
@@ -1,6 +1,9 @@
-#This file is part of Tryton.  The COPYRIGHT file at the top level of
-#this repository contains the full copyright notices and license terms.
+# This file is part of Tryton.  The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
 from lxml import etree
+from dateutil.parser import parse
+
+from trytond.transaction import Transaction
 
 __all__ = ['SEPAHandler', 'CAMT054']
 
@@ -32,13 +35,16 @@ class CAMT054(SEPAHandler):
             element.clear()
 
     def handle_entry(self, element):
-        payment = self.get_payment(element)
+        payments = self.get_payments(element)
         if self.is_returned(element):
-            self.set_return_information(payment, element)
-            payment.save()
-            self.Payment.fail([payment])
+            for payment in payments:
+                self.set_return_information(payment, element)
+            self.Payment.save(payments)
+            self.Payment.fail(payments)
         else:
-            self.Payment.succeed([payment])
+            date_value = self.date_value(element)
+            with Transaction().set_context(date_value=date_value):
+                self.Payment.succeed(payments)
 
     def get_payment_kind(self, element):
         tag = etree.QName(element)
@@ -49,7 +55,7 @@ class CAMT054(SEPAHandler):
         'DBIT': 'receivable',
         }
 
-    def get_payment(self, element):
+    def get_payments(self, element):
         tag = etree.QName(element)
         details = element.find('./{%s}NtryDtls' % tag.namespace)
         if details is None:
@@ -59,18 +65,30 @@ class CAMT054(SEPAHandler):
             return
         instr_id = details.find('.//{%s}InstrId' % tag.namespace)
         if instr_id is not None:
-            payment, = self.Payment.search([
+            payments = self.Payment.search([
                     ('sepa_instuction_id', '=', instr_id.text),
                     ('kind', '=', self.get_payment_kind(element)),
                     ])
-            return payment
+            return payments
         end_to_end_id = details.find('.//{%s}EndToEndId' % tag.namespace)
         if end_to_end_id is not None:
-            payment, = self.Payment.search([
+            payments = self.Payment.search([
                     ('sepa_end_to_end_id', '=', end_to_end_id.text),
                     ('kind', '=', self.get_payment_kind(element)),
                     ])
-            return payment
+            return payments
+
+    def date_value(self, element):
+        tag = etree.QName(element)
+        date = element.find('./{%(ns)s}ValDt/{%(ns)s}Dt'
+            % {'ns': tag.namespace})
+        if date is not None:
+            return parse(date.text)
+        else:
+            datetime = element.find('./{%(ns)s}ValDt/{%(ns)s}DtTm'
+                % {'ns': tag.namespace})
+            if datetime:
+                return parse(datetime.text).date()
 
     def is_returned(self, element):
         tag = etree.QName(element)
diff --git a/setup.py b/setup.py
index 545faeb..854e49b 100644
--- a/setup.py
+++ b/setup.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
-#This file is part of Tryton.  The COPYRIGHT file at the top level of
-#this repository contains the full copyright notices and license terms.
+# This file is part of Tryton.  The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
 
 from setuptools import setup
 import re
@@ -41,7 +41,7 @@ if minor_version % 2:
         'hg+http://hg.tryton.org/modules/%s#egg=%s-%s' % (
             name[8:], name, version))
 
-requires = ['Genshi', 'lxml']
+requires = ['Genshi', 'lxml', 'python-dateutil']
 for dep in info.get('depends', []):
     if not re.match(r'(ir|res|webdav)(\W|$)', dep):
         requires.append(get_require_version('trytond_%s' % dep))
@@ -88,6 +88,8 @@ setup(name=name,
         'Natural Language :: Spanish',
         'Operating System :: OS Independent',
         'Programming Language :: Python :: 2.7',
+        'Programming Language :: Python :: Implementation :: CPython',
+        'Programming Language :: Python :: Implementation :: PyPy',
         'Topic :: Office/Business',
         'Topic :: Office/Business :: Financial :: Accounting',
         ],
diff --git a/template/base.003.xml b/template/base.003.xml
new file mode 100644
index 0000000..39555e0
--- /dev/null
+++ b/template/base.003.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- This file is part of Tryton.  The COPYRIGHT file at the top level of
+this repository contains the full copyright notices and license terms. -->
+<py:strip xmlns:py="http://genshi.edgewall.org/">
+    <!-- only ASCII -->
+    <py:def function="PartyIdentification(party, id=True, with_name=True, with_address=True)">
+        <!-- EPC limits to 70 instead of 140 -->
+        <Nm py:if="with_name">${normalize('NFKD', party.name).encode('ascii', 'replace')[:70]}</Nm>
+        <py:if test="with_address">
+            <py:with vars="address = party.address_get()">
+                <PstlAdr py:if="address">
+                    ${PostalAddress(address)}
+                </PstlAdr>
+            </py:with>
+        </py:if>
+        <Id py:if="id and party.sepa_creditor_identifier_used">
+            <PrvtId>
+                <Othr>
+                    <Id>${party.sepa_creditor_identifier_used}</Id>
+                    <SchmeNm>
+                        <Prtry>SEPA</Prtry>
+                    </SchmeNm>
+                    <!-- Issr -->
+                </Othr>
+            </PrvtId>
+        </Id>
+        <!-- CtryOfRes -->
+        <!-- CtctDtls -->
+    </py:def>
+    <py:def function="PostalAddress(address)">
+        <Ctry py:if="address.country">${normalize('NFKD', address.country.code).encode('ascii', 'replace')}</Ctry>
+        <AdrLine py:if="address.street">${normalize('NFKD', address.street).encode('ascii', 'replace')[:70]}</AdrLine>
+        <AdrLine py:if="address.streetbis">${normalize('NFKD', address.streetbis).encode('ascii', 'replace')[:70]}</AdrLine>
+    </py:def>
+    <py:def function="Account(account_number, with_ccy=True)">
+        <Id>
+            <!-- EPC only IBAN is allowed -->
+            <IBAN>${account_number.compact_iban}</IBAN>
+        </Id>
+        <!-- Tp -->
+        <Ccy py:if="with_ccy and account_number.account.currency">${account_number.account.currency.code}</Ccy>
+        <!-- Nm -->
+    </py:def>
+    <!-- uses BIC instead of BICFI -->
+    <py:def function="FinancialInstitution(bank, only_bic=False)">
+        <FinInstnId>
+            <BIC py:if="bank.bic">${bank.bic}</BIC>
+            <Othr py:if="not bank.bic">
+                <Id>NOTPROVIDED</Id>
+            </Othr>
+        </FinInstnId>
+    </py:def>
+</py:strip>
diff --git a/template/base.xml b/template/base.xml
index c6830af..0441aa4 100644
--- a/template/base.xml
+++ b/template/base.xml
@@ -36,13 +36,13 @@ this repository contains the full copyright notices and license terms. -->
         <Ctry py:if="address.country">${address.country.code}</Ctry>
         <!-- AdrLine -->
     </py:def>
-    <py:def function="Account(account_number)">
+    <py:def function="Account(account_number, currency=True)">
         <Id>
             <!-- EPC only IBAN is allowed -->
             <IBAN>${account_number.compact_iban}</IBAN>
         </Id>
         <!-- Tp -->
-        <Ccy py:if="account_number.account.currency">${account_number.account.currency.code}</Ccy>
+        <Ccy py:if="currency and account_number.account.currency">${account_number.account.currency.code}</Ccy>
         <!-- Nm -->
     </py:def>
     <py:def function="FinancialInstitution(bank, only_bic=False)">
diff --git a/template/pain.001.001.03.xml b/template/pain.001.001.03.xml
index 29ea6d6..25073f6 100644
--- a/template/pain.001.001.03.xml
+++ b/template/pain.001.001.03.xml
@@ -31,7 +31,7 @@ this repository contains the full copyright notices and license terms. -->
             <MsgId>${group.reference[:35]}</MsgId>
             <CreDtTm>${datetime.datetime.now().isoformat()}</CreDtTm>
             <!-- Authstn -->
-            <NbOfTxs>${len(group.payments)}</NbOfTxs>
+            <NbOfTxs>${sum(len(payments) for _, payments in group.sepa_payments)}</NbOfTxs>
             <CtrlSum>${sum(p.amount for p in group.payments)}</CtrlSum>
             <!-- PmtTpInf -->
             <!-- ReqdColltnDt -->
diff --git a/template/pain.001.001.05.xml b/template/pain.001.001.05.xml
index db275a5..319afcb 100644
--- a/template/pain.001.001.05.xml
+++ b/template/pain.001.001.05.xml
@@ -12,7 +12,7 @@ this repository contains the full copyright notices and license terms. -->
             <MsgId>${group.reference[:35]}</MsgId>
             <CreDtTm>${datetime.datetime.now().isoformat()}</CreDtTm>
             <!-- Authstn -->
-            <NbOfTxs>${len(group.payments)}</NbOfTxs>
+            <NbOfTxs>${sum(len(payments) for _, payments in group.sepa_payments)}</NbOfTxs>
             <CtrlSum>${sum(p.amount for p in group.payments)}</CtrlSum>
             <!-- PmtTpInf -->
             <!-- ReqdColltnDt -->
diff --git a/template/pain.001.001.05.xml b/template/pain.001.003.03.xml
similarity index 69%
copy from template/pain.001.001.05.xml
copy to template/pain.001.003.03.xml
index db275a5..9b613b4 100644
--- a/template/pain.001.001.05.xml
+++ b/template/pain.001.003.03.xml
@@ -1,25 +1,24 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!-- This file is part of Tryton.  The COPYRIGHT file at the top level of
 this repository contains the full copyright notices and license terms. -->
-<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.05"
+<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.003.03"
     xmlns:xsd="http://www.w3.org/2001/XMLSchema"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:pain.001.003.03
+    pain.001.003.03.xsd"
     xmlns:xi="http://www.w3.org/2001/XInclude"
     xmlns:py="http://genshi.edgewall.org/">
     <xi:include href="base.xml"/>
+    <xi:include href="base.003.xml"/>
     <CstmrCdtTrfInitn>
         <GrpHdr>
             <MsgId>${group.reference[:35]}</MsgId>
             <CreDtTm>${datetime.datetime.now().isoformat()}</CreDtTm>
-            <!-- Authstn -->
-            <NbOfTxs>${len(group.payments)}</NbOfTxs>
+            <NbOfTxs>${sum(len(payments) for _, payments in group.sepa_payments)}</NbOfTxs>
             <CtrlSum>${sum(p.amount for p in group.payments)}</CtrlSum>
-            <!-- PmtTpInf -->
-            <!-- ReqdColltnDt -->
             <InitgPty>
-                ${PartyIdentification(group.sepa_initiating_party)}
+                ${PartyIdentification(group.sepa_initiating_party, with_address=False)}
             </InitgPty>
-            <!-- FwdgAgt -->
         </GrpHdr>
         <PmtInf py:for="key, payments in group.sepa_payments">
             <PmtInfId>${group.sepa_group_payment_id(key)[:35]}</PmtInfId>
@@ -32,11 +31,9 @@ this repository contains the full copyright notices and license terms. -->
                 <SvcLvl>
                     <Cd>SEPA</Cd>
                 </SvcLvl>
-                <!-- LclInstrm -->
                 <!-- CtgyPurp -->
             </PmtTpInf>
             <ReqdExctnDt>${key['date'].isoformat()}</ReqdExctnDt>
-            <!-- PoolgAdjstmntDt -->
             <Dbtr>
                 ${PartyIdentification(group.company.party)}
             </Dbtr>
@@ -46,12 +43,8 @@ this repository contains the full copyright notices and license terms. -->
             <DbtrAgt>
                 ${FinancialInstitution(group.journal.sepa_bank_account_number.account.bank, only_bic=True)}
             </DbtrAgt>
-            <!-- DbtrAgtAcct -->
-            <!-- InstrForDbtrAgt -->
             <!-- UltmtDbtr -->
-            <ChrgBr>${group.journal.sepa_charge_bearer}</ChrgBr>
-            <!-- ChrgsAcct -->
-            <!-- ChrgsAcctAgt -->
+            <ChrgBr>SLEV</ChrgBr>
             <CdtTrfTxInf py:for="payment in payments">
                 <PmtId>
                     <InstrId>${payment.sepa_instruction_id}</InstrId>
@@ -60,41 +53,24 @@ this repository contains the full copyright notices and license terms. -->
                 <!-- PmtTpInf --> <!-- EPC only at payment information level -->
                 <Amt>
                     <InstdAmt py:attrs="{'Ccy': payment.currency.code}">${payment.amount}</InstdAmt>
-                    <!-- EqvtAmt -->
                 </Amt>
-                <!-- XchgRateInf -->
                 <!-- ChrgBr --> <!-- EPC only at payment information level -->
-                <!-- ChqInstr -->
                 <!-- UltmtDbtr -->
-                <!-- IntrmyAgt1 -->
-                <!-- IntrmyAgt1Acct -->
-                <!-- IntrmyAgt2 -->
-                <!-- IntrmyAgt2Acct -->
-                <!-- IntrmyAgt3 -->
-                <!-- IntrmyAgt3Acct -->
                 <CdtrAgt>
                     ${FinancialInstitution(payment.sepa_bank_account_number.account.bank, only_bic=True)}
                 </CdtrAgt>
-                <!-- CdtrAgtAcct -->
                 <Cdtr>
                     ${PartyIdentification(payment.party)}
                 </Cdtr>
                 <CdtrAcct>
-                    ${Account(payment.sepa_bank_account_number)}
+                    ${Account(payment.sepa_bank_account_number, with_ccy=False)}
                 </CdtrAcct>
                 <!-- UltmtCdtr -->
-                <!-- InstrForCdtrAgt -->
-                <!-- InstrForDbtrAgt -->
                 <!-- Purp -->
-                <!-- RgltryRptg -->
-                <!-- Tax -->
-                <!-- RltdRmtInf -->
                 <RmtInf py:if="payment.sepa_remittance_information">
-                    <Ustrd>${payment.sepa_remittance_information[:140]}</Ustrd>
+                    <Ustrd>${normalize('NFKD', payment.sepa_remittance_information).encode('ascii', 'replace')[:140]}</Ustrd>
                 </RmtInf>
-                <!-- SplmtryData -->
             </CdtTrfTxInf>
         </PmtInf>
-        <!-- SplmtryData -->
     </CstmrCdtTrfInitn>
 </Document>
diff --git a/template/pain.008.001.02.xml b/template/pain.008.001.02.xml
index 002db1a..86a28ef 100644
--- a/template/pain.008.001.02.xml
+++ b/template/pain.008.001.02.xml
@@ -31,7 +31,7 @@ this repository contains the full copyright notices and license terms. -->
             <MsgId>${group.reference[:35]}</MsgId>
             <CreDtTm>${datetime.datetime.now().isoformat()}</CreDtTm>
             <!-- Authstn -->
-            <NbOfTxs>${len(group.payments)}</NbOfTxs>
+            <NbOfTxs>${sum(len(payments) for _, payments in group.sepa_payments)}</NbOfTxs>
             <CtrlSum>${sum(p.amount for p in group.payments)}</CtrlSum>
             <!-- PmtTpInf -->
             <!-- ReqdColltnDt -->
@@ -109,7 +109,7 @@ this repository contains the full copyright notices and license terms. -->
                     ${PartyIdentification(payment.party)}
                 </Dbtr>
                 <DbtrAcct>
-                    ${Account(payment.sepa_bank_account_number)}
+                    ${Account(payment.sepa_bank_account_number, currency=False)}
                 </DbtrAcct>
                 <!-- UltmtDbtr -->
                 <!-- InstrForCdtrAgt -->
diff --git a/template/pain.008.001.04.xml b/template/pain.008.001.04.xml
index 2ec8914..57c680e 100644
--- a/template/pain.008.001.04.xml
+++ b/template/pain.008.001.04.xml
@@ -90,7 +90,7 @@ this repository contains the full copyright notices and license terms. -->
                     ${PartyIdentification(payment.party)}
                 </Dbtr>
                 <DbtrAcct>
-                    ${Account(payment.sepa_bank_account_number)}
+                    ${Account(payment.sepa_bank_account_number, currency=False)}
                 </DbtrAcct>
                 <!-- UltmtDbtr -->
                 <!-- InstrForCdtrAgt -->
diff --git a/template/pain.008.001.04.xml b/template/pain.008.003.02.xml
similarity index 74%
copy from template/pain.008.001.04.xml
copy to template/pain.008.003.02.xml
index 2ec8914..7fdb45d 100644
--- a/template/pain.008.001.04.xml
+++ b/template/pain.008.003.02.xml
@@ -1,25 +1,24 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!-- This file is part of Tryton.  The COPYRIGHT file at the top level of
 this repository contains the full copyright notices and license terms. -->
-<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.008.001.04"
+<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pain.008.003.02"
     xmlns:xsd="http://www.w3.org/2001/XMLSchema"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="urn:iso:std:iso:20022:tech:xsd:pain.008.003.02
+    pain.008.003.02.xsd"
     xmlns:xi="http://www.w3.org/2001/XInclude"
     xmlns:py="http://genshi.edgewall.org/">
     <xi:include href="base.xml"/>
+    <xi:include href="base.003.xml"/>
     <CstmrDrctDbtInitn>
         <GrpHdr>
             <MsgId>${group.reference[:35]}</MsgId>
             <CreDtTm>${datetime.datetime.now().isoformat()}</CreDtTm>
-            <!-- Authstn -->
-            <NbOfTxs>${len(group.payments)}</NbOfTxs>
+            <NbOfTxs>${sum(len(payments) for _, payments in group.sepa_payments)}</NbOfTxs>
             <CtrlSum>${sum(p.amount for p in group.payments)}</CtrlSum>
-            <!-- PmtTpInf -->
-            <!-- ReqdColltnDt -->
             <InitgPty>
-                ${PartyIdentification(group.sepa_initiating_party)}
+                ${PartyIdentification(group.sepa_initiating_party, with_address=False)}
             </InitgPty>
-            <!-- FwdgAgt -->
         </GrpHdr>
         <PmtInf py:for="key, payments in group.sepa_payments">
             <PmtInfId>${group.sepa_group_payment_id(key)[:35]}</PmtInfId>
@@ -28,14 +27,11 @@ this repository contains the full copyright notices and license terms. -->
             <NbOfTxs>${len(payments)}</NbOfTxs>
             <CtrlSum>${sum(p.amount for p in payments)}</CtrlSum>
             <PmtTpInf>
-                <!-- InstrPrty -->
                 <SvcLvl>
                     <Cd>SEPA</Cd>
-                    <!-- Prtry -->
                 </SvcLvl>
                 <LclInstrm>
                     <Cd>${key['scheme']}</Cd>
-                    <!-- Prtry -->
                 </LclInstrm>
                 <SeqTp>${key['sequence_type']}</SeqTp>
                 <!-- CtgyPurp -->
@@ -50,20 +46,16 @@ this repository contains the full copyright notices and license terms. -->
             <CdtrAgt>
                 ${FinancialInstitution(group.journal.sepa_bank_account_number.account.bank, only_bic=True)}
             </CdtrAgt>
-            <!-- CdtrAgtAcct -->
             <!-- UltmtCdtr -->
-            <ChrgBr>${group.journal.sepa_charge_bearer}</ChrgBr>
-            <!-- ChrgsAcct -->
-            <!-- ChrgsAcctAgt -->
+            <ChrgBr>SLEV</ChrgBr>
             <CdtrSchmeId>
-                ${PartyIdentification(group.company.party)}
+                ${PartyIdentification(group.company.party, with_name=False, with_address=False)}
             </CdtrSchmeId>
             <DrctDbtTxInf py:for="payment in payments">
                 <PmtId>
                     <InstrId>${payment.sepa_instruction_id}</InstrId>
                     <EndToEndId>${payment.sepa_end_to_end_id}</EndToEndId>
                 </PmtId>
-                <!-- PmtTpInf -->
                 <InstdAmt py:attrs="{'Ccy': payment.currency.code}">${payment.amount}</InstdAmt>
                 <!-- ChrgBr --> <!-- EPC only at payment information level -->
                 <DrctDbtTx>
@@ -73,37 +65,26 @@ this repository contains the full copyright notices and license terms. -->
                         <!-- AmdmntInd -->
                         <!-- AmdmntInfDtls -->
                         <!-- ElctrncSgntr -->
-                        <!-- FrstColltnDt -->
-                        <!-- FnlColltnDt -->
-                        <!-- Frqcy -->
                     </MndtRltdInf>
                     <!-- CdtrSchmeId -->
-                    <!-- PreNtfctnId -->
-                    <!-- PreNtfctnDt -->
                 </DrctDbtTx>
                 <!-- UltmtCdtr -->
                 <DbtrAgt>
                     ${FinancialInstitution(payment.sepa_bank_account_number.account.bank, only_bic=True)}
                 </DbtrAgt>
-                <!-- DbtrAgtAcct -->
                 <Dbtr>
                     ${PartyIdentification(payment.party)}
                 </Dbtr>
                 <DbtrAcct>
-                    ${Account(payment.sepa_bank_account_number)}
+                    ${Account(payment.sepa_bank_account_number, with_ccy=False)}
                 </DbtrAcct>
                 <!-- UltmtDbtr -->
-                <!-- InstrForCdtrAgt -->
                 <!-- Purp -->
-                <!-- RgltryRptg -->
-                <!-- Tax -->
-                <!-- RltdRmtInf -->
                 <RmtInf py:if="payment.sepa_remittance_information">
-                    <Ustrd>${payment.sepa_remittance_information[:140]}</Ustrd>
+                    <Ustrd>${normalize('NFKD', payment.sepa_remittance_information).encode('ascii', 'replace')[:140]}</Ustrd>
+                    <!-- Strd -->
                 </RmtInf>
-                <!-- SplmtryData -->
             </DrctDbtTxInf>
         </PmtInf>
-        <!-- SplmtryData -->
     </CstmrDrctDbtInitn>
 </Document>
diff --git a/tests/__init__.py b/tests/__init__.py
index 84e2248..9e31e2c 100644
--- a/tests/__init__.py
+++ b/tests/__init__.py
@@ -1,5 +1,5 @@
-#This file is part of Tryton.  The COPYRIGHT file at the top level of
-#this repository contains the full copyright notices and license terms.
+# This file is part of Tryton.  The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
 
 from .test_account_payment_sepa import suite
 
diff --git a/tests/pain.001.003.03.xsd b/tests/pain.001.003.03.xsd
new file mode 100644
index 0000000..a90ed99
--- /dev/null
+++ b/tests/pain.001.003.03.xsd
@@ -0,0 +1,474 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Version gemäß DFÜ-Abkommen Anlage 3, Version 2.7, gültig ab November 2013 mit Umsetzung von IBAN Only gemäß EPC SCT 7.0, zudem Erweiterung Service Level auf Externe Codeliste-->
+<!-- Mit XMLSpy v2008 am 29.11.2012 von der SIZ GmbH bearbeitet -->
+<xs:schema xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.003.03" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:iso:std:iso:20022:tech:xsd:pain.001.003.03" elementFormDefault="qualified">
+	<xs:element name="Document" type="Document"/>
+	<xs:complexType name="AccountIdentificationSEPA">
+		<xs:sequence>
+			<xs:element name="IBAN" type="IBAN2007Identifier"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:simpleType name="ActiveOrHistoricCurrencyAndAmount_SimpleTypeSEPA">
+		<xs:restriction base="xs:decimal">
+			<xs:minInclusive value="0.01"/>
+			<xs:maxInclusive value="999999999.99"/>
+			<xs:fractionDigits value="2"/>
+			<xs:totalDigits value="11"/>
+		</xs:restriction>
+	</xs:simpleType>
+	<xs:simpleType name="ActiveOrHistoricCurrencyCode">
+		<xs:restriction base="xs:string">
+			<xs:pattern value="[A-Z]{3,3}"/>
+		</xs:restriction>
+	</xs:simpleType>
+	<xs:complexType name="ActiveOrHistoricCurrencyAndAmountSEPA">
+		<xs:simpleContent>
+			<xs:extension base="ActiveOrHistoricCurrencyAndAmount_SimpleTypeSEPA">
+				<xs:attribute name="Ccy" type="ActiveOrHistoricCurrencyCodeEUR" use="required"/>
+			</xs:extension>
+		</xs:simpleContent>
+	</xs:complexType>
+	<xs:simpleType name="ActiveOrHistoricCurrencyCodeEUR">
+		<xs:restriction base="xs:string">
+			<xs:enumeration value="EUR"/>
+		</xs:restriction>
+	</xs:simpleType>
+	<xs:complexType name="AmountTypeSEPA">
+		<xs:sequence>
+			<xs:element name="InstdAmt" type="ActiveOrHistoricCurrencyAndAmountSEPA"/>
+		</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: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="BatchBookingIndicator">
+		<xs:restriction base="xs:boolean"/>
+	</xs:simpleType>
+	<xs:complexType name="BranchAndFinancialInstitutionIdentificationSEPA1">
+		<xs:sequence>
+			<xs:element name="FinInstnId" type="FinancialInstitutionIdentificationSEPA1"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="BranchAndFinancialInstitutionIdentificationSEPA3">
+		<xs:sequence>
+			<xs:element name="FinInstnId" type="FinancialInstitutionIdentificationSEPA3"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="CashAccountSEPA1">
+		<xs:sequence>
+			<xs:element name="Id" type="AccountIdentificationSEPA"/>
+			<xs:element name="Ccy" type="ActiveOrHistoricCurrencyCode" minOccurs="0"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="CashAccountSEPA2">
+		<xs:sequence>
+			<xs:element name="Id" type="AccountIdentificationSEPA"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="CategoryPurposeSEPA">
+		<xs:sequence>
+			<xs:element name="Cd" type="ExternalCategoryPurpose1Code"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:simpleType name="ChargeBearerTypeSEPACode">
+		<xs:restriction base="xs:string">
+			<xs:enumeration value="SLEV"/>
+		</xs:restriction>
+	</xs:simpleType>
+	<xs:simpleType name="CountryCode">
+		<xs:restriction base="xs:string">
+			<xs:pattern value="[A-Z]{2,2}"/>
+		</xs:restriction>
+	</xs:simpleType>
+	<xs:complexType name="CreditTransferTransactionInformationSCT">
+		<xs:sequence>
+			<xs:element name="PmtId" type="PaymentIdentificationSEPA"/>
+			<xs:element name="PmtTpInf" type="PaymentTypeInformationSCT2" minOccurs="0">
+				<xs:annotation>
+					<xs:documentation>If used, it is recommended to be used at ‘Payment Information’ level and not at ‘Credit Transfer Transaction Information’ level.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+			<xs:element name="Amt" type="AmountTypeSEPA"/>
+			<xs:element name="ChrgBr" type="ChargeBearerTypeSEPACode" minOccurs="0">
+				<xs:annotation>
+					<xs:documentation>It is recommended that this element be specified at ‘Payment Information’ level.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+			<xs:element name="UltmtDbtr" type="PartyIdentificationSEPA1" minOccurs="0">
+				<xs:annotation>
+					<xs:documentation>This data element may be present either at ‘Payment Information’ or at ‘Credit Transfer Transaction Information’ level.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+			<xs:element name="CdtrAgt" type="BranchAndFinancialInstitutionIdentificationSEPA1" minOccurs="0"/>
+			<xs:element name="Cdtr" type="PartyIdentificationSEPA2"/>
+			<xs:element name="CdtrAcct" type="CashAccountSEPA2"/>
+			<xs:element name="UltmtCdtr" type="PartyIdentificationSEPA1" minOccurs="0"/>
+			<xs:element name="Purp" type="PurposeSEPA" minOccurs="0"/>
+			<xs:element name="RmtInf" type="RemittanceInformationSEPA1Choice" minOccurs="0"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="CreditorReferenceInformationSEPA1">
+		<xs:sequence>
+			<xs:element name="Tp" type="CreditorReferenceTypeSEPA"/>
+			<xs:element name="Ref" type="Max35Text">
+				<xs:annotation>
+					<xs:documentation>If a Creditor Reference contains a check digit, the receiving bank is not required to validate this.
+If the receiving bank validates the check digit and if this validation fails, the bank may continue its processing and send the transaction to the next party in the chain.
+RF Creditor Reference may be used (ISO 11649).</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="CreditorReferenceTypeSEPA">
+		<xs:sequence>
+			<xs:element name="CdOrPrtry" type="CreditorReferenceTypeCodeSEPA"/>
+			<xs:element name="Issr" type="Max35Text" minOccurs="0"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="CreditorReferenceTypeCodeSEPA">
+		<xs:sequence>
+			<xs:element name="Cd" type="DocumentType3CodeSEPA"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="CustomerCreditTransferInitiationV03">
+		<xs:sequence>
+			<xs:element name="GrpHdr" type="GroupHeaderSCT"/>
+			<xs:element name="PmtInf" type="PaymentInstructionInformationSCT" maxOccurs="unbounded"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="DateAndPlaceOfBirth">
+		<xs:sequence>
+			<xs:element name="BirthDt" type="ISODate"/>
+			<xs:element name="PrvcOfBirth" type="Max35Text" minOccurs="0"/>
+			<xs:element name="CityOfBirth" type="Max35Text"/>
+			<xs:element name="CtryOfBirth" type="CountryCode"/>
+		</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:simpleType name="DocumentType3CodeSEPA">
+		<xs:restriction base="xs:string">
+			<xs:enumeration value="SCOR"/>
+		</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="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="FinancialInstitutionIdentificationSEPA1">
+		<xs:sequence>
+			<xs:element name="BIC" type="BICIdentifier"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="FinancialInstitutionIdentificationSEPA3">
+		<xs:sequence>
+			<xs:choice>
+				<xs:element name="BIC" type="BICIdentifier"/>
+				<xs:element name="Othr" type="OthrIdentification"/>
+			</xs:choice>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="OthrIdentification">
+		<xs:sequence>
+			<xs:element name="Id" type="OthrIdentificationCode"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:simpleType name="OthrIdentificationCode">
+		<xs:restriction base="xs:string">
+			<xs:enumeration value="NOTPROVIDED"/>
+		</xs:restriction>
+	</xs:simpleType>
+	<xs:complexType name="GenericOrganisationIdentification1">
+		<xs:sequence>
+			<xs:element name="Id" type="Max35Text"/>
+			<xs:element name="SchmeNm" type="OrganisationIdentificationSchemeName1Choice" minOccurs="0"/>
+			<xs:element name="Issr" type="Max35Text" minOccurs="0"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="GenericPersonIdentification1">
+		<xs:sequence>
+			<xs:element name="Id" type="Max35Text"/>
+			<xs:element name="SchmeNm" type="PersonIdentificationSchemeName1Choice" minOccurs="0"/>
+			<xs:element name="Issr" type="Max35Text" minOccurs="0"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="GroupHeaderSCT">
+		<xs:sequence>
+			<xs:element name="MsgId" type="RestrictedIdentificationSEPA1"/>
+			<xs:element name="CreDtTm" type="ISODateTime"/>
+			<xs:element name="NbOfTxs" type="Max15NumericText"/>
+			<xs:element name="CtrlSum" type="DecimalNumber" minOccurs="0"/>
+			<xs:element name="InitgPty" type="PartyIdentificationSEPA1"/>
+		</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="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="Max35Text">
+		<xs:restriction base="xs:string">
+			<xs:minLength value="1"/>
+			<xs:maxLength value="35"/>
+		</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="OrganisationIdentificationSEPAChoice">
+		<xs:sequence>
+			<xs:choice>
+				<xs:element name="BICOrBEI" type="AnyBICIdentifier"/>
+				<xs:element name="Othr" type="GenericOrganisationIdentification1"/>
+			</xs:choice>
+		</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="PartySEPAChoice">
+		<xs:sequence>
+			<xs:choice>
+				<xs:element name="OrgId" type="OrganisationIdentificationSEPAChoice">
+					<xs:annotation>
+						<xs:documentation>Either ‘BIC or BEI’ or one
+occurrence of ‘Other’ is allowed.</xs:documentation>
+					</xs:annotation>
+				</xs:element>
+				<xs:element name="PrvtId" type="PersonIdentificationSEPA1Choice">
+					<xs:annotation>
+						<xs:documentation>Either ‘Date and Place of Birth’ or one occurrence of ‘Other’ is allowed.</xs:documentation>
+					</xs:annotation>
+				</xs:element>
+			</xs:choice>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="PartyIdentificationSEPA1">
+		<xs:sequence>
+			<xs:element name="Nm" type="Max70Text" minOccurs="0">
+				<xs:annotation>
+					<xs:documentation>‘Name’ is limited to 70 characters
+in length.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+			<xs:element name="Id" type="PartySEPAChoice" minOccurs="0"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="PartyIdentificationSEPA2">
+		<xs:sequence>
+			<xs:element name="Nm" type="Max70Text">
+				<xs:annotation>
+					<xs:documentation>‘Name’ is limited to 70 characters
+in length.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+			<xs:element name="PstlAdr" type="PostalAddressSEPA" minOccurs="0"/>
+			<xs:element name="Id" type="PartySEPAChoice" minOccurs="0"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="PaymentIdentificationSEPA">
+		<xs:sequence>
+			<xs:element name="InstrId" type="RestrictedIdentificationSEPA1" minOccurs="0"/>
+			<xs:element name="EndToEndId" type="RestrictedIdentificationSEPA1"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="PaymentInstructionInformationSCT">
+		<xs:sequence>
+			<xs:element name="PmtInfId" type="RestrictedIdentificationSEPA1"/>
+			<xs:element name="PmtMtd" type="PaymentMethodSCTCode">
+				<xs:annotation>
+					<xs:documentation>Only ‘TRF’ is allowed.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+			<xs:element name="BtchBookg" type="BatchBookingIndicator" minOccurs="0">
+				<xs:annotation>
+					<xs:documentation>If present and contains ‘true’, batch booking is requested. If present and contains ‘false’, booking per transaction is requested. If element is not present, pre-agreed customer-to-bank conditions apply.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+			<xs:element name="NbOfTxs" type="Max15NumericText" minOccurs="0"/>
+			<xs:element name="CtrlSum" type="DecimalNumber" minOccurs="0"/>
+			<xs:element name="PmtTpInf" type="PaymentTypeInformationSCT1" minOccurs="0">
+				<xs:annotation>
+					<xs:documentation>If used, it is recommended to be used only at ‘Payment Information’ level and not at Credit Transfer Transaction Information’ level.
+When Instruction Priority is to be used, ‘Payment Type Information’ must be present at ‘Payment Information’ level. </xs:documentation>
+				</xs:annotation>
+			</xs:element>
+			<xs:element name="ReqdExctnDt" type="ISODate"/>
+			<xs:element name="Dbtr" type="PartyIdentificationSEPA2"/>
+			<xs:element name="DbtrAcct" type="CashAccountSEPA1"/>
+			<xs:element name="DbtrAgt" type="BranchAndFinancialInstitutionIdentificationSEPA3"/>
+			<xs:element name="UltmtDbtr" type="PartyIdentificationSEPA1" minOccurs="0">
+				<xs:annotation>
+					<xs:documentation>This data element may be present either at ‘Payment Information’ or at ‘Credit Transfer Transaction Information’ level.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+			<xs:element name="ChrgBr" type="ChargeBearerTypeSEPACode" minOccurs="0">
+				<xs:annotation>
+					<xs:documentation>It is recommended that this element be specified at ‘Payment Information’ level.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+			<xs:element name="CdtTrfTxInf" type="CreditTransferTransactionInformationSCT" maxOccurs="unbounded"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:simpleType name="PaymentMethodSCTCode">
+		<xs:restriction base="xs:string">
+			<xs:enumeration value="TRF"/>
+		</xs:restriction>
+	</xs:simpleType>
+	<xs:complexType name="PaymentTypeInformationSCT1">
+		<xs:sequence>
+			<xs:element name="InstrPrty" type="Priority2Code" minOccurs="0">
+				<xs:annotation>
+					<xs:documentation>If present, pre-agreed customer-to-bank conditions apply.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+			<xs:element name="SvcLvl" type="ServiceLevelSEPA"/>
+			<xs:element name="CtgyPurp" type="CategoryPurposeSEPA" minOccurs="0">
+				<xs:annotation>
+					<xs:documentation>Depending on the agreement between the Originator and the Originator Bank, ‘Category Purpose’ may be forwarded to the Beneficiary Bank.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="PaymentTypeInformationSCT2">
+		<xs:sequence>
+			<xs:element name="SvcLvl" type="ServiceLevelSEPA"/>
+			<xs:element name="CtgyPurp" type="CategoryPurposeSEPA" minOccurs="0">
+				<xs:annotation>
+					<xs:documentation>Depending on the agreement between the Originator and the Originator Bank, ‘Category Purpose’ may be forwarded to the Beneficiary Bank.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="PersonIdentificationSEPA1Choice">
+		<xs:sequence>
+			<xs:choice>
+				<xs:element name="DtAndPlcOfBirth" type="DateAndPlaceOfBirth"/>
+				<xs:element name="Othr" type="GenericPersonIdentification1"/>
+			</xs:choice>
+		</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:complexType name="PostalAddressSEPA">
+		<xs:sequence>
+			<xs:element name="Ctry" type="CountryCode" minOccurs="0"/>
+			<xs:element name="AdrLine" type="Max70Text" minOccurs="0" maxOccurs="2"/>
+		</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="PurposeSEPA">
+		<xs:sequence>
+			<xs:element name="Cd" type="ExternalPurpose1Code">
+				<xs:annotation>
+					<xs:documentation>Only codes from the ISO 20022 ExternalPurposeCode list are allowed.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="RemittanceInformationSEPA1Choice">
+		<xs:sequence>
+			<xs:choice>
+				<xs:element name="Ustrd" type="Max140Text"/>
+				<xs:element name="Strd" type="StructuredRemittanceInformationSEPA1"/>
+			</xs:choice>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="ServiceLevelSEPA">
+		<xs:sequence>
+			<xs:element name="Cd" type="ExternalServiceLevel1Code"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="StructuredRemittanceInformationSEPA1">
+		<xs:sequence>
+			<xs:element name="CdtrRefInf" type="CreditorReferenceInformationSEPA1" minOccurs="0">
+				<xs:annotation>
+					<xs:documentation>When present, the receiving bank is not obliged to validate the the reference information. </xs:documentation>
+				</xs:annotation>
+			</xs:element>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:simpleType name="RestrictedIdentificationSEPA1">
+		<xs:restriction base="xs:string">
+			<xs:pattern value="([A-Za-z0-9]|[\+|\?|/|\-|:|\(|\)|\.|,|'| ]){1,35}"/>
+		</xs:restriction>
+	</xs:simpleType>
+</xs:schema>
diff --git a/tests/pain.008.003.02.xsd b/tests/pain.008.003.02.xsd
new file mode 100644
index 0000000..99992b5
--- /dev/null
+++ b/tests/pain.008.003.02.xsd
@@ -0,0 +1,614 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Mit XMLSpy v2008 rel. 2 (http://www.altova.com) von Wenzel (SIZ Bonn) bearbeitet -->
+<!-- Version gemäß DFÜ-Abkommen Anlage 3, Version 2.7, gültig ab November 2013 mit Umsetzung von IBAN Only gemäß EPC SDD Core IG 7.0 bzw. SDD B2B IG 5.0 , zudem Einbau der COR1-Option durch Erweiterung Local Instrument und Erweiterung Service Level auf Externe Codeliste-->
+<!-- Mit XMLSpy v2008 rel. 2 sp2 (http://www.altova.com) am 29.11.2012 von der SIZ GmbH bearbeitet -->
+<xs:schema xmlns="urn:iso:std:iso:20022:tech:xsd:pain.008.003.02" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:iso:std:iso:20022:tech:xsd:pain.008.003.02" elementFormDefault="qualified">
+	<xs:element name="Document" type="Document"/>
+	<xs:complexType name="AccountIdentificationSEPA">
+		<xs:sequence>
+			<xs:element name="IBAN" type="IBAN2007Identifier"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:simpleType name="ActiveOrHistoricCurrencyAndAmount_SimpleTypeSEPA">
+		<xs:restriction base="xs:decimal">
+			<xs:minInclusive value="0.01"/>
+			<xs:maxInclusive value="999999999.99"/>
+			<xs:fractionDigits value="2"/>
+			<xs:totalDigits value="11"/>
+		</xs:restriction>
+	</xs:simpleType>
+	<xs:complexType name="ActiveOrHistoricCurrencyAndAmountSEPA">
+		<xs:simpleContent>
+			<xs:extension base="ActiveOrHistoricCurrencyAndAmount_SimpleTypeSEPA">
+				<xs:attribute name="Ccy" type="ActiveOrHistoricCurrencyCodeEUR" use="required"/>
+			</xs:extension>
+		</xs:simpleContent>
+	</xs:complexType>
+	<xs:simpleType name="ActiveOrHistoricCurrencyCodeEUR">
+		<xs:restriction base="xs:string">
+			<xs:enumeration value="EUR"/>
+		</xs:restriction>
+	</xs:simpleType>
+	<xs:simpleType name="ActiveOrHistoricCurrencyCode">
+		<xs:restriction base="xs:string">
+			<xs:pattern value="[A-Z]{3,3}"/>
+		</xs:restriction>
+	</xs:simpleType>
+	<xs:complexType name="AmendmentInformationDetailsSDD">
+		<xs:sequence>
+			<xs:element name="OrgnlMndtId" type="RestrictedIdentificationSEPA2" minOccurs="0">
+				<xs:annotation>
+					<xs:documentation>Mandatory if changes occur in ‘Mandate Identification’, otherwise not to be used.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+			<xs:element name="OrgnlCdtrSchmeId" type="PartyIdentificationSEPA4" minOccurs="0">
+				<xs:annotation>
+					<xs:documentation>Mandatory if changes occur in 'Creditor Scheme Identification', otherwise not to be used.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+			<xs:element name="OrgnlDbtrAcct" type="CashAccountSEPA2" minOccurs="0">
+				<xs:annotation>
+					<xs:documentation>To be used only for changes of accounts within the same bank.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+			<xs:element name="OrgnlDbtrAgt" type="BranchAndFinancialInstitutionIdentificationSEPA2" minOccurs="0">
+				<xs:annotation>
+					<xs:documentation>To use 'Identification’ under 'Other' under 'Financial Institution Identifier with code ‘SMNDA’ to indicate same mandate with new Debtor Agent. To be used with the ‘FRST’ indicator in the ‘Sequence Type’.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+		</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: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="BatchBookingIndicator">
+		<xs:restriction base="xs:boolean"/>
+	</xs:simpleType>
+	<xs:complexType name="BranchAndFinancialInstitutionIdentificationSEPA3">
+		<xs:sequence>
+			<xs:element name="FinInstnId" type="FinancialInstitutionIdentificationSEPA3"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="BranchAndFinancialInstitutionIdentificationSEPA2">
+		<xs:sequence>
+			<xs:element name="FinInstnId" type="FinancialInstitutionIdentificationSEPA2"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="CashAccountSEPA1">
+		<xs:sequence>
+			<xs:element name="Id" type="AccountIdentificationSEPA"/>
+			<xs:element name="Ccy" type="ActiveOrHistoricCurrencyCode" minOccurs="0"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="CashAccountSEPA2">
+		<xs:sequence>
+			<xs:element name="Id" type="AccountIdentificationSEPA"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="CategoryPurposeSEPA">
+		<xs:sequence>
+			<xs:element name="Cd" type="ExternalCategoryPurpose1Code"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:simpleType name="ChargeBearerTypeSEPACode">
+		<xs:restriction base="xs:string">
+			<xs:enumeration value="SLEV"/>
+		</xs:restriction>
+	</xs:simpleType>
+	<xs:simpleType name="CountryCode">
+		<xs:restriction base="xs:string">
+			<xs:pattern value="[A-Z]{2,2}"/>
+		</xs:restriction>
+	</xs:simpleType>
+	<xs:complexType name="CreditorReferenceInformationSEPA1">
+		<xs:sequence>
+			<xs:element name="Tp" type="CreditorReferenceTypeSEPA"/>
+			<xs:element name="Ref" type="Max35Text">
+				<xs:annotation>
+					<xs:documentation>If a Creditor Reference contains a check digit, the receiving bank is not required to validate this.
+If the receiving bank validates the check digit and if this validation fails, the bank may continue its processing and send the transaction to the next party in the chain.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="CreditorReferenceTypeSEPA">
+		<xs:sequence>
+			<xs:element name="CdOrPrtry" type="CreditorReferenceTypeCodeSEPA"/>
+			<xs:element name="Issr" type="Max35Text" minOccurs="0"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="CreditorReferenceTypeCodeSEPA">
+		<xs:sequence>
+			<xs:element name="Cd" type="DocumentType3CodeSEPA"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="CustomerDirectDebitInitiationV02">
+		<xs:sequence>
+			<xs:element name="GrpHdr" type="GroupHeaderSDD"/>
+			<xs:element name="PmtInf" type="PaymentInstructionInformationSDD" maxOccurs="unbounded"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="DateAndPlaceOfBirth">
+		<xs:sequence>
+			<xs:element name="BirthDt" type="ISODate"/>
+			<xs:element name="PrvcOfBirth" type="Max35Text" minOccurs="0"/>
+			<xs:element name="CityOfBirth" type="Max35Text"/>
+			<xs:element name="CtryOfBirth" type="CountryCode"/>
+		</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="DirectDebitTransactionSDD">
+		<xs:sequence>
+			<xs:element name="MndtRltdInf" type="MandateRelatedInformationSDD"/>
+			<xs:element name="CdtrSchmeId" type="PartyIdentificationSEPA3" minOccurs="0">
+				<xs:annotation>
+					<xs:documentation>It is recommended that all transactions within the same ‘Payment Information’ block have the same ‘Creditor Scheme Identification’.
+This data element must be present at either ‘Payment Information’ or ‘Direct Debit
+Transaction’ level.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="DirectDebitTransactionInformationSDD">
+		<xs:sequence>
+			<xs:element name="PmtId" type="PaymentIdentificationSEPA"/>
+			<xs:element name="InstdAmt" type="ActiveOrHistoricCurrencyAndAmountSEPA"/>
+			<xs:element name="ChrgBr" type="ChargeBearerTypeSEPACode" minOccurs="0">
+				<xs:annotation>
+					<xs:documentation>It is recommended that this element be specified at ‘Payment Information’ level.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+			<xs:element name="DrctDbtTx" type="DirectDebitTransactionSDD"/>
+			<xs:element name="UltmtCdtr" type="PartyIdentificationSEPA1" minOccurs="0">
+				<xs:annotation>
+					<xs:documentation>This data element may be present either at ‘Payment Information’ or at ‘Direct Debit Transaction Information’ level.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+			<xs:element name="DbtrAgt" type="BranchAndFinancialInstitutionIdentificationSEPA3"/>
+			<xs:element name="Dbtr" type="PartyIdentificationSEPA2"/>
+			<xs:element name="DbtrAcct" type="CashAccountSEPA2"/>
+			<xs:element name="UltmtDbtr" type="PartyIdentificationSEPA1" minOccurs="0">
+				<xs:annotation>
+					<xs:documentation>Mandatory if provided by the debtor in the mandate.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+			<xs:element name="Purp" type="PurposeSEPA" minOccurs="0"/>
+			<xs:element name="RmtInf" type="RemittanceInformationSEPA1Choice" minOccurs="0"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="Document">
+		<xs:sequence>
+			<xs:element name="CstmrDrctDbtInitn" type="CustomerDirectDebitInitiationV02"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:simpleType name="DocumentType3CodeSEPA">
+		<xs:restriction base="xs:string">
+			<xs:enumeration value="SCOR"/>
+		</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="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="FinancialInstitutionIdentificationSEPA3">
+		<xs:sequence>
+			<xs:choice>
+				<xs:element name="BIC" type="BICIdentifier"/>
+				<xs:element name="Othr" type="OthrIdentification"/>
+			</xs:choice>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="OthrIdentification">
+		<xs:sequence>
+			<xs:element name="Id" type="OthrIdentificationCode"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:simpleType name="OthrIdentificationCode">
+		<xs:restriction base="xs:string">
+			<xs:enumeration value="NOTPROVIDED"/>
+		</xs:restriction>
+	</xs:simpleType>
+	<xs:complexType name="FinancialInstitutionIdentificationSEPA2">
+		<xs:sequence>
+			<xs:element name="Othr" type="RestrictedFinancialIdentificationSEPA"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="RestrictedFinancialIdentificationSEPA">
+		<xs:sequence>
+			<xs:element name="Id" type="RestrictedSMNDACode"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:simpleType name="RestrictedSMNDACode">
+		<xs:restriction base="xs:string">
+			<xs:enumeration value="SMNDA"/>
+		</xs:restriction>
+	</xs:simpleType>
+	<xs:complexType name="GenericOrganisationIdentification1">
+		<xs:sequence>
+			<xs:element name="Id" type="Max35Text"/>
+			<xs:element name="SchmeNm" type="OrganisationIdentificationSchemeName1Choice" minOccurs="0"/>
+			<xs:element name="Issr" type="Max35Text" minOccurs="0"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="GenericPersonIdentification1">
+		<xs:sequence>
+			<xs:element name="Id" type="Max35Text"/>
+			<xs:element name="SchmeNm" type="PersonIdentificationSchemeName1Choice" minOccurs="0"/>
+			<xs:element name="Issr" type="Max35Text" minOccurs="0"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="RestrictedPersonIdentificationSEPA">
+		<xs:sequence>
+			<xs:element name="Id" type="RestrictedPersonIdentifierSEPA"/>
+			<xs:element name="SchmeNm" type="RestrictedPersonIdentificationSchemeNameSEPA"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:simpleType name="RestrictedPersonIdentifierSEPA">
+		<xs:restriction base="xs:string">
+			<xs:pattern value="[a-zA-Z]{2,2}[0-9]{2,2}([A-Za-z0-9]|[\+|\?|/|\-|:|\(|\)|\.|,|']){3,3}([A-Za-z0-9]|[\+|\?|/|\-|:|\(|\)|\.|,|']){1,28}"/>
+		</xs:restriction>
+	</xs:simpleType>
+	<xs:complexType name="GroupHeaderSDD">
+		<xs:sequence>
+			<xs:element name="MsgId" type="RestrictedIdentificationSEPA1"/>
+			<xs:element name="CreDtTm" type="ISODateTime"/>
+			<xs:element name="NbOfTxs" type="Max15NumericText"/>
+			<xs:element name="CtrlSum" type="DecimalNumber" minOccurs="0"/>
+			<xs:element name="InitgPty" type="PartyIdentificationSEPA1"/>
+		</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:complexType name="LocalInstrumentSEPA">
+		<xs:sequence>
+			<xs:element name="Cd" type="ExternalLocalInstrument1Code"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="MandateRelatedInformationSDD">
+		<xs:sequence>
+			<xs:element name="MndtId" type="RestrictedIdentificationSEPA2"/>
+			<xs:element name="DtOfSgntr" type="ISODate"/>
+			<xs:element name="AmdmntInd" type="TrueFalseIndicator" minOccurs="0"/>
+			<xs:element name="AmdmntInfDtls" type="AmendmentInformationDetailsSDD" minOccurs="0">
+				<xs:annotation>
+					<xs:documentation>Mandatory if 'Amendment Indicator' is 'TRUE'
+The reason code from the Rulebook is indicated using one of the following message subelements.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+			<xs:element name="ElctrncSgntr" type="Max1025Text" minOccurs="0"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:simpleType name="Max1025Text">
+		<xs:restriction base="xs:string">
+			<xs:minLength value="1"/>
+			<xs:maxLength value="1025"/>
+		</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="Max35Text">
+		<xs:restriction base="xs:string">
+			<xs:minLength value="1"/>
+			<xs:maxLength value="35"/>
+		</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="OrganisationIdentificationSEPAChoice">
+		<xs:sequence>
+			<xs:choice>
+				<xs:element name="BICOrBEI" type="AnyBICIdentifier"/>
+				<xs:element name="Othr" type="GenericOrganisationIdentification1"/>
+			</xs:choice>
+		</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="PartySEPAChoice">
+		<xs:sequence>
+			<xs:choice>
+				<xs:element name="OrgId" type="OrganisationIdentificationSEPAChoice">
+					<xs:annotation>
+						<xs:documentation>Either ‘BIC or BEI’ or one
+occurrence of ‘Other’ is allowed.</xs:documentation>
+					</xs:annotation>
+				</xs:element>
+				<xs:element name="PrvtId" type="PersonIdentificationSEPA1Choice">
+					<xs:annotation>
+						<xs:documentation>Either ‘Date and Place of Birth’ or one occurrence of ‘Other’ is allowed</xs:documentation>
+					</xs:annotation>
+				</xs:element>
+			</xs:choice>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="PartySEPA2">
+		<xs:sequence>
+			<xs:element name="PrvtId" type="PersonIdentificationSEPA2">
+				<xs:annotation>
+					<xs:documentation>Private Identification is used to identify either an organisation or a private
+person.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="PartyIdentificationSEPA1">
+		<xs:sequence>
+			<xs:element name="Nm" type="Max70Text" minOccurs="0">
+				<xs:annotation>
+					<xs:documentation>‘Name’ is limited to 70 characters in length.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+			<xs:element name="Id" type="PartySEPAChoice" minOccurs="0"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="PartyIdentificationSEPA2">
+		<xs:sequence>
+			<xs:element name="Nm" type="Max70Text">
+				<xs:annotation>
+					<xs:documentation>‘Name’ is limited to 70 characters in length.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+			<xs:element name="PstlAdr" type="PostalAddressSEPA" minOccurs="0"/>
+			<xs:element name="Id" type="PartySEPAChoice" minOccurs="0"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="PartyIdentificationSEPA3">
+		<xs:sequence>
+			<xs:element name="Id" type="PartySEPA2"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="PartyIdentificationSEPA4">
+		<xs:sequence>
+			<xs:element name="Nm" type="Max70Text" minOccurs="0">
+				<xs:annotation>
+					<xs:documentation>If present the new’ Name’ must be specified under ‘Creditor’. ‘Name’ is limited to 70 characters in length.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+			<xs:element name="Id" type="PartySEPA2" minOccurs="0"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="PartyIdentificationSEPA5">
+		<xs:sequence>
+			<xs:element name="Nm" type="Max70Text">
+				<xs:annotation>
+					<xs:documentation>‘Name’ is limited to 70 characters in length.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+			<xs:element name="PstlAdr" type="PostalAddressSEPA" minOccurs="0"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="PaymentIdentificationSEPA">
+		<xs:sequence>
+			<xs:element name="InstrId" type="RestrictedIdentificationSEPA1" minOccurs="0"/>
+			<xs:element name="EndToEndId" type="RestrictedIdentificationSEPA1"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="PaymentInstructionInformationSDD">
+		<xs:sequence>
+			<xs:element name="PmtInfId" type="RestrictedIdentificationSEPA1"/>
+			<xs:element name="PmtMtd" type="PaymentMethod2Code"/>
+			<xs:element name="BtchBookg" type="BatchBookingIndicator" minOccurs="0">
+				<xs:annotation>
+					<xs:documentation>If present and contains ‘true’, batch booking is requested. If present and contains ‘false’, booking per transaction is requested. If element is not present, pre-agreed customer-to-bank conditions apply.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+			<xs:element name="NbOfTxs" type="Max15NumericText" minOccurs="0"/>
+			<xs:element name="CtrlSum" type="DecimalNumber" minOccurs="0"/>
+			<xs:element name="PmtTpInf" type="PaymentTypeInformationSDD"/>
+			<xs:element name="ReqdColltnDt" type="ISODate"/>
+			<xs:element name="Cdtr" type="PartyIdentificationSEPA5"/>
+			<xs:element name="CdtrAcct" type="CashAccountSEPA1"/>
+			<xs:element name="CdtrAgt" type="BranchAndFinancialInstitutionIdentificationSEPA3"/>
+			<xs:element name="UltmtCdtr" type="PartyIdentificationSEPA1" minOccurs="0">
+				<xs:annotation>
+					<xs:documentation>This data element may be present either at ‘Payment Information’ or at ‘Direct Debit Transaction Information’ level.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+			<xs:element name="ChrgBr" type="ChargeBearerTypeSEPACode" minOccurs="0">
+				<xs:annotation>
+					<xs:documentation>It is recommended that this element be specified at ‘Payment Information’ level.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+			<xs:element name="CdtrSchmeId" type="PartyIdentificationSEPA3" minOccurs="0">
+				<xs:annotation>
+					<xs:documentation>It is recommended that all transactions within the same ‘Payment Information’ block have the same ‘Creditor Scheme Identification’.
+This data element must be present at either ‘Payment Information’ or ‘Direct Debit
+Transaction’ level.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+			<xs:element name="DrctDbtTxInf" type="DirectDebitTransactionInformationSDD" maxOccurs="unbounded"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:simpleType name="PaymentMethod2Code">
+		<xs:restriction base="xs:string">
+			<xs:enumeration value="DD"/>
+		</xs:restriction>
+	</xs:simpleType>
+	<xs:complexType name="PaymentTypeInformationSDD">
+		<xs:sequence>
+			<xs:element name="SvcLvl" type="ServiceLevelSEPA"/>
+			<xs:element name="LclInstrm" type="LocalInstrumentSEPA">
+				<xs:annotation>
+					<xs:documentation>Only ‘B2B’, 'CORE' or 'COR1' is allowed. The mixing of different Local Instrument values is not allowed in the same message.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+			<xs:element name="SeqTp" type="SequenceType1Code">
+				<xs:annotation>
+					<xs:documentation>If 'Amendment Indicator' is 'true' and 'Original Debtor Agent' is set to 'SMNDA' this message element must indicate 'FRST'</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+			<xs:element name="CtgyPurp" type="CategoryPurposeSEPA" minOccurs="0">
+				<xs:annotation>
+					<xs:documentation>Depending on the agreement between the Creditor and the Creditor Bank, ‘Category Purpose’ may be forwarded to the Debtor Bank.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="PersonIdentificationSEPA1Choice">
+		<xs:sequence>
+			<xs:choice>
+				<xs:element name="DtAndPlcOfBirth" type="DateAndPlaceOfBirth"/>
+				<xs:element name="Othr" type="GenericPersonIdentification1"/>
+			</xs:choice>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="PersonIdentificationSEPA2">
+		<xs:sequence>
+			<xs:element name="Othr" type="RestrictedPersonIdentificationSEPA">
+				<xs:annotation>
+					<xs:documentation>Only one occurrence of ‘Other’ is allowed, and no other sub-elements are allowed.
+Identification must be used with an identifier described in General Message Element Specifications, Chapter 1.5.2 of the Implementation Guide.
+Scheme Name’ under ‘Other’ must specify ‘SEPA’ under ‘Proprietary</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+		</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:complexType name="RestrictedPersonIdentificationSchemeNameSEPA">
+		<xs:sequence>
+			<xs:element name="Prtry" type="IdentificationSchemeNameSEPA"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:simpleType name="IdentificationSchemeNameSEPA">
+		<xs:restriction base="xs:string">
+			<xs:enumeration value="SEPA"/>
+		</xs:restriction>
+	</xs:simpleType>
+	<xs:complexType name="PostalAddressSEPA">
+		<xs:sequence>
+			<xs:element name="Ctry" type="CountryCode" minOccurs="0"/>
+			<xs:element name="AdrLine" type="Max70Text" minOccurs="0" maxOccurs="2"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="PurposeSEPA">
+		<xs:sequence>
+			<xs:element name="Cd" type="ExternalPurpose1Code">
+				<xs:annotation>
+					<xs:documentation>Only codes from the ISO 20022 ExternalPurposeCode list are allowed.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="RemittanceInformationSEPA1Choice">
+		<xs:sequence>
+			<xs:choice>
+				<xs:element name="Ustrd" type="Max140Text"/>
+				<xs:element name="Strd" type="StructuredRemittanceInformationSEPA1"/>
+			</xs:choice>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:simpleType name="SequenceType1Code">
+		<xs:restriction base="xs:string">
+			<xs:enumeration value="FRST"/>
+			<xs:enumeration value="RCUR"/>
+			<xs:enumeration value="FNAL"/>
+			<xs:enumeration value="OOFF"/>
+		</xs:restriction>
+	</xs:simpleType>
+	<xs:complexType name="ServiceLevelSEPA">
+		<xs:sequence>
+			<xs:element name="Cd" type="ExternalServiceLevel1Code"/>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="StructuredRemittanceInformationSEPA1">
+		<xs:sequence>
+			<xs:element name="CdtrRefInf" type="CreditorReferenceInformationSEPA1" minOccurs="0">
+				<xs:annotation>
+					<xs:documentation>When present, the receiving bank is not obliged to validate the reference information.</xs:documentation>
+				</xs:annotation>
+			</xs:element>
+		</xs:sequence>
+	</xs:complexType>
+	<xs:simpleType name="TrueFalseIndicator">
+		<xs:restriction base="xs:boolean"/>
+	</xs:simpleType>
+	<xs:simpleType name="RestrictedIdentificationSEPA1">
+		<xs:restriction base="xs:string">
+			<xs:pattern value="([A-Za-z0-9]|[\+|\?|/|\-|:|\(|\)|\.|,|'| ]){1,35}"/>
+		</xs:restriction>
+	</xs:simpleType>
+	<xs:simpleType name="RestrictedIdentificationSEPA2">
+		<xs:restriction base="xs:string">
+			<xs:pattern value="([A-Za-z0-9]|[\+|\?|/|\-|:|\(|\)|\.|,|']){1,35}"/>
+		</xs:restriction>
+	</xs:simpleType>
+</xs:schema>
diff --git a/tests/test_account_payment_sepa.py b/tests/test_account_payment_sepa.py
index 9b1658a..f688c65 100644
--- a/tests/test_account_payment_sepa.py
+++ b/tests/test_account_payment_sepa.py
@@ -1,5 +1,5 @@
-#This file is part of Tryton.  The COPYRIGHT file at the top level of
-#this repository contains the full copyright notices and license terms.
+# This file is part of Tryton.  The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
 import os
 import unittest
 import doctest
@@ -11,165 +11,191 @@ from io import BytesIO
 from mock import Mock, patch
 
 import trytond.tests.test_tryton
-from trytond.tests.test_tryton import test_view, test_depends
-from trytond.tests.test_tryton import POOL, DB_NAME, USER, CONTEXT
+from trytond.tests.test_tryton import ModuleTestCase
+from trytond.tests.test_tryton import DB_NAME, USER, CONTEXT
 from trytond.transaction import Transaction
 from trytond.exceptions import UserError
 from trytond.modules.account_payment_sepa.payment import CAMT054
-
-
-class AccountPaymentSepaTestCase(unittest.TestCase):
+from trytond.pool import Pool
+
+
+def setup_environment():
+    pool = Pool()
+    Address = pool.get('party.address')
+    Company = pool.get('company.company')
+    Currency = pool.get('currency.currency')
+    Party = pool.get('party.party')
+    Bank = pool.get('bank')
+
+    company, = Company.search([
+            ('rec_name', '=', 'Dunder Mifflin'),
+            ])
+    euro, = Currency.create([{
+                'name': 'Euro',
+                'symbol': 'EUR',
+                'code': 'EUR',
+                }])
+    company.currency = euro
+    company.party.sepa_creditor_identifier = 'BE68539007547034'
+    company.party.save()
+    company.save()
+    bank_party = Party(name='European Bank')
+    bank_party.save()
+    bank = Bank(party=bank_party, bic='BICODEBBXXX')
+    bank.save()
+    customer = Party(name='Customer')
+    address = Address(street='street', streetbis='street bis',
+        zip='1234', city='City')
+    customer.addresses = [address]
+    customer.save()
+    return {
+        'company': company,
+        'bank': bank,
+        'customer': customer,
+        }
+
+
+def setup_accounts(bank, company, customer):
+    pool = Pool()
+    Account = pool.get('bank.account')
+    return Account.create([{
+                'bank': bank,
+                'owners': [('add', [company.party])],
+                'currency': company.currency.id,
+                'numbers': [('create', [{
+                                'type': 'iban',
+                                'number': 'ES8200000000000000000000',
+                                }])]}, {
+                'bank': bank,
+                'owners': [('add', [customer])],
+                'currency': company.currency.id,
+                'numbers': [('create', [{
+                                'type': 'iban',
+                                'number': 'ES3600000000050000000001',
+                                }])]}])
+
+
+def setup_mandate(company, customer, account):
+    pool = Pool()
+    Mandate = pool.get('account.payment.sepa.mandate')
+    Date = pool.get('ir.date')
+    return Mandate.create([{
+                'company': company,
+                'party': customer,
+                'account_number': account.numbers[0],
+                'identification': 'MANDATE',
+                'type': 'recurrent',
+                'signature_date': Date.today(),
+                'state': 'validated',
+                }])[0]
+
+
+def setup_journal(flavor, kind, company, account):
+    pool = Pool()
+    Journal = pool.get('account.payment.journal')
+    journal = Journal()
+    journal.name = flavor
+    journal.company = company
+    journal.currency = company.currency
+    journal.process_method = 'sepa'
+    journal.sepa_bank_account_number = account.numbers[0]
+    journal.sepa_payable_flavor = 'pain.001.001.03'
+    journal.sepa_receivable_flavor = 'pain.008.001.02'
+    setattr(journal, 'sepa_%s_flavor' % kind, flavor)
+    journal.save()
+    return journal
+
+
+def validate_file(flavor, kind, xsd=None):
+    'Test generated files are valid'
+    pool = Pool()
+    Payment = pool.get('account.payment')
+    PaymentGroup = pool.get('account.payment.group')
+    Date = pool.get('ir.date')
+    ProcessPayment = pool.get('account.payment.process', type='wizard')
+
+    if xsd is None:
+        xsd = flavor
+
+    environment = setup_environment()
+    company = environment['company']
+    bank = environment['bank']
+    customer = environment['customer']
+    company_account, customer_account = setup_accounts(
+        bank, company, customer)
+    setup_mandate(company, customer, customer_account)
+    journal = setup_journal(flavor, kind, company, company_account)
+
+    payment, = Payment.create([{
+                'company': company,
+                'party': customer,
+                'journal': journal,
+                'kind': kind,
+                'amount': Decimal('1000.0'),
+                'state': 'approved',
+                'description': 'PAYMENT',
+                'date': Date.today(),
+                }])
+
+    session_id, _, _ = ProcessPayment.create()
+    process_payment = ProcessPayment(session_id)
+    with Transaction().set_context(active_ids=[payment.id]):
+        _, data = process_payment.do_process(None)
+    group, = PaymentGroup.browse(data['res_id'])
+    message, = group.sepa_messages
+    assert message.type == 'out', message.type
+    assert message.state == 'waiting', message.state
+    sepa_string = message.message.encode('utf-8')
+    sepa_xml = etree.fromstring(sepa_string)
+    schema_file = os.path.join(os.path.dirname(__file__),
+        '%s.xsd' % xsd)
+    schema = etree.XMLSchema(etree.parse(schema_file))
+    schema.assertValid(sepa_xml)
+
+
+class AccountPaymentSepaTestCase(ModuleTestCase):
     'Test Account Payment SEPA module'
-
-    def setUp(self):
-        trytond.tests.test_tryton.install_module('account_payment_sepa')
-        self.bank = POOL.get('bank')
-        self.bank_account = POOL.get('bank.account')
-        self.bank_number = POOL.get('bank.account.number')
-        self.company = POOL.get('company.company')
-        self.currency = POOL.get('currency.currency')
-        self.date = POOL.get('ir.date')
-        self.mandate = POOL.get('account.payment.sepa.mandate')
-        self.party = POOL.get('party.party')
-        self.payment = POOL.get('account.payment')
-        self.payment_group = POOL.get('account.payment.group')
-        self.payment_journal = POOL.get('account.payment.journal')
-        self.process_payment = POOL.get('account.payment.process',
-            type='wizard')
-        self.user = POOL.get('res.user')
-
-    def test0005views(self):
-        'Test views'
-        test_view('account_payment_sepa')
-
-    def test0006depends(self):
-        'Test depends'
-        test_depends()
-
-    def setup_environment(self):
-        company, = self.company.search([
-                ('rec_name', '=', 'Dunder Mifflin'),
-                ])
-        euro, = self.currency.create([{
-                    'name': 'Euro',
-                    'symbol': 'EUR',
-                    'code': 'EUR',
-                    }])
-        company.currency = euro
-        company.party.sepa_creditor_identifier = 'BE68539007547034'
-        company.party.save()
-        company.save()
-        bank_party = self.party(name='European Bank')
-        bank_party.save()
-        bank = self.bank(party=bank_party, bic='BICODEBBXXX')
-        bank.save()
-        customer = self.party(name='Customer')
-        customer.save()
-        return {
-            'company': company,
-            'bank': bank,
-            'customer': customer,
-            }
-
-    def setup_accounts(self, bank, company, customer):
-        return self.bank_account.create([{
-                    'bank': bank,
-                    'owners': [('add', [company.party])],
-                    'numbers': [('create', [{
-                                    'type': 'iban',
-                                    'number': 'ES8200000000000000000000',
-                                    }])]}, {
-                    'bank': bank,
-                    'owners': [('add', [customer])],
-                    'numbers': [('create', [{
-                                    'type': 'iban',
-                                    'number': 'ES3600000000050000000001',
-                                    }])]}])
-
-    def setup_mandate(self, company, customer, account):
-        return self.mandate.create([{
-                    'company': company,
-                    'party': customer,
-                    'account_number': account.numbers[0],
-                    'identification': 'MANDATE',
-                    'type': 'recurrent',
-                    'signature_date': self.date.today(),
-                    'state': 'validated',
-                    }])[0]
-
-    def setup_journal(self, flavor, kind, company, account):
-        journal = self.payment_journal()
-        journal.name = flavor
-        journal.company = company
-        journal.currency = company.currency
-        journal.process_method = 'sepa'
-        journal.sepa_bank_account_number = account.numbers[0]
-        journal.sepa_payable_flavor = 'pain.001.001.03'
-        journal.sepa_receivable_flavor = 'pain.008.001.02'
-        setattr(journal, 'sepa_%s_flavor' % kind, flavor)
-        journal.save()
-        return journal
-
-    def validate_file(self, flavor, kind):
-        'Test generated files are valid'
-        with Transaction().start(DB_NAME, USER, context=CONTEXT):
-            environment = self.setup_environment()
-            company = environment['company']
-            bank = environment['bank']
-            customer = environment['customer']
-            company_account, customer_account = self.setup_accounts(bank,
-                company, customer)
-            self.setup_mandate(company, customer, customer_account)
-            journal = self.setup_journal(flavor, kind, company,
-                company_account)
-
-            payment, = self.payment.create([{
-                        'company': company,
-                        'party': customer,
-                        'journal': journal,
-                        'kind': kind,
-                        'amount': Decimal('1000.0'),
-                        'state': 'approved',
-                        'description': 'PAYMENT',
-                        'date': self.date.today(),
-                        }])
-
-            session_id, _, _ = self.process_payment.create()
-            process_payment = self.process_payment(session_id)
-            with Transaction().set_context(active_ids=[payment.id]):
-                _, data = process_payment.do_process(None)
-            group, = self.payment_group.browse(data['res_id'])
-            message, = group.sepa_messages
-            sepa_string = message.message.encode('utf-8')
-            sepa_xml = etree.fromstring(sepa_string)
-            schema_file = os.path.join(os.path.dirname(__file__),
-                '%s.xsd' % flavor)
-            schema = etree.XMLSchema(etree.parse(schema_file))
-            schema.assertValid(sepa_xml)
+    module = 'account_payment_sepa'
 
     def test_pain001_001_03(self):
         'Test pain001.001.03 xsd validation'
-        self.validate_file('pain.001.001.03', 'payable')
+        with Transaction().start(DB_NAME, USER, context=CONTEXT):
+            validate_file('pain.001.001.03', 'payable')
 
     def test_pain001_001_05(self):
         'Test pain001.001.05 xsd validation'
-        self.validate_file('pain.001.001.05', 'payable')
+        with Transaction().start(DB_NAME, USER, context=CONTEXT):
+            validate_file('pain.001.001.05', 'payable')
+
+    def test_pain001_003_03(self):
+        'Test pain001.003.03 xsd validation'
+        with Transaction().start(DB_NAME, USER, context=CONTEXT):
+            validate_file('pain.001.003.03', 'payable')
 
     def test_pain008_001_02(self):
         'Test pain008.001.02 xsd validation'
-        self.validate_file('pain.008.001.02', 'receivable')
+        with Transaction().start(DB_NAME, USER, context=CONTEXT):
+            validate_file('pain.008.001.02', 'receivable')
 
     def test_pain008_001_04(self):
         'Test pain008.001.04 xsd validation'
-        self.validate_file('pain.008.001.04', 'receivable')
+        with Transaction().start(DB_NAME, USER, context=CONTEXT):
+            validate_file('pain.008.001.04', 'receivable')
+
+    def test_pain008_003_02(self):
+        'Test pain008.003.02 xsd validation'
+        with Transaction().start(DB_NAME, USER, context=CONTEXT):
+            validate_file('pain.008.003.02', 'receivable')
 
     def test_sepa_mandate_sequence(self):
         'Test SEPA mandate sequence'
-        Configuration = POOL.get('account.configuration')
-        Sequence = POOL.get('ir.sequence')
-        Party = POOL.get('party.party')
-        Mandate = POOL.get('account.payment.sepa.mandate')
         with Transaction().start(DB_NAME, USER, context=CONTEXT):
+            pool = Pool()
+            Configuration = pool.get('account.configuration')
+            Sequence = pool.get('ir.sequence')
+            Party = pool.get('party.party')
+            Mandate = pool.get('account.payment.sepa.mandate')
+
             party = Party(name='Test')
             party.save()
             mandate = Mandate(party=party)
@@ -189,10 +215,13 @@ class AccountPaymentSepaTestCase(unittest.TestCase):
 
     def test_identification_unique(self):
         'Test unique identification constraint'
-        Party = POOL.get('party.party')
-        Mandate = POOL.get('account.payment.sepa.mandate')
-        same_id = '1'
         with Transaction().start(DB_NAME, USER, context=CONTEXT):
+            pool = Pool()
+            Party = pool.get('party.party')
+            Mandate = pool.get('account.payment.sepa.mandate')
+
+            same_id = '1'
+
             party = Party(name='Test')
             party.save()
             mandate = Mandate(party=party, identification=same_id)
@@ -219,11 +248,12 @@ class AccountPaymentSepaTestCase(unittest.TestCase):
     def test_payment_sepa_bank_account_number(self):
         'Test Payment.sepa_bank_account_number'
         with Transaction().start(DB_NAME, USER, context=CONTEXT):
-            Payment = POOL.get('account.payment')
-            Mandate = POOL.get('account.payment.sepa.mandate')
-            AccountNumber = POOL.get('bank.account.number')
-            Party = POOL.get('party.party')
-            BankAccount = POOL.get('bank.account')
+            pool = Pool()
+            Payment = pool.get('account.payment')
+            Mandate = pool.get('account.payment.sepa.mandate')
+            AccountNumber = pool.get('bank.account.number')
+            Party = pool.get('party.party')
+            BankAccount = pool.get('bank.account')
 
             account_number = AccountNumber()
             mandate = Mandate(account_number=account_number)
@@ -246,17 +276,22 @@ class AccountPaymentSepaTestCase(unittest.TestCase):
     def test_payment_sequence_type(self):
         'Test payment sequence type'
         with Transaction().start(DB_NAME, USER, context=CONTEXT):
-            environment = self.setup_environment()
+            pool = Pool()
+            Date = pool.get('ir.date')
+            Payment = pool.get('account.payment')
+            ProcessPayment = pool.get('account.payment.process', type='wizard')
+
+            environment = setup_environment()
             company = environment['company']
             bank = environment['bank']
             customer = environment['customer']
-            company_account, customer_account = self.setup_accounts(bank,
-                company, customer)
-            self.setup_mandate(company, customer, customer_account)
-            journal = self.setup_journal('pain.008.001.02', 'receivable',
+            company_account, customer_account = setup_accounts(
+                bank, company, customer)
+            setup_mandate(company, customer, customer_account)
+            journal = setup_journal('pain.008.001.02', 'receivable',
                 company, company_account)
 
-            payment, = self.payment.create([{
+            payment, = Payment.create([{
                         'company': company,
                         'party': customer,
                         'journal': journal,
@@ -264,17 +299,17 @@ class AccountPaymentSepaTestCase(unittest.TestCase):
                         'amount': Decimal('1000.0'),
                         'state': 'approved',
                         'description': 'PAYMENT',
-                        'date': self.date.today(),
+                        'date': Date.today(),
                         }])
 
-            session_id, _, _ = self.process_payment.create()
-            process_payment = self.process_payment(session_id)
+            session_id, _, _ = ProcessPayment.create()
+            process_payment = ProcessPayment(session_id)
             with Transaction().set_context(active_ids=[payment.id]):
                 _, data = process_payment.do_process(None)
 
             self.assertEqual(payment.sepa_mandate_sequence_type, 'FRST')
 
-            payments = self.payment.create([{
+            payments = Payment.create([{
                         'company': company,
                         'party': customer,
                         'journal': journal,
@@ -282,7 +317,7 @@ class AccountPaymentSepaTestCase(unittest.TestCase):
                         'amount': Decimal('2000.0'),
                         'state': 'approved',
                         'description': 'PAYMENT',
-                        'date': self.date.today(),
+                        'date': Date.today(),
                         }, {
                         'company': company,
                         'party': customer,
@@ -291,12 +326,12 @@ class AccountPaymentSepaTestCase(unittest.TestCase):
                         'amount': Decimal('3000.0'),
                         'state': 'approved',
                         'description': 'PAYMENT',
-                        'date': self.date.today(),
+                        'date': Date.today(),
                         },
                     ])
 
-            session_id, _, _ = self.process_payment.create()
-            process_payment = self.process_payment(session_id)
+            session_id, _, _ = ProcessPayment.create()
+            process_payment = ProcessPayment(session_id)
             payment_ids = [p.id for p in payments]
             with Transaction().set_context(active_ids=payment_ids):
                 _, data = process_payment.do_process(None)
@@ -307,7 +342,8 @@ class AccountPaymentSepaTestCase(unittest.TestCase):
     def handle_camt054(self, flavor):
         'Handle camt.054'
         with Transaction().start(DB_NAME, USER, context=CONTEXT):
-            Message = POOL.get('account.payment.sepa.message')
+            pool = Pool()
+            Message = pool.get('account.payment.sepa.message')
 
             message_file = os.path.join(os.path.dirname(__file__),
                 '%s.xml' % flavor)
@@ -335,7 +371,7 @@ class AccountPaymentSepaTestCase(unittest.TestCase):
                 is_returned.return_value = True
                 handler = CAMT054(BytesIO(message), Payment)
 
-                payment.save.assert_called_with()
+                Payment.save.assert_called_with([payment])
                 Payment.fail.assert_called_with([payment])
 
     def test_camt054_001_01(self):
@@ -354,6 +390,24 @@ class AccountPaymentSepaTestCase(unittest.TestCase):
         'Test camt.054.001.04 handling'
         self.handle_camt054('camt.054.001.04')
 
+    def test_sepa_mandate_report(self):
+        'Test sepa mandate report'
+        with Transaction().start(DB_NAME, USER, context=CONTEXT):
+            pool = Pool()
+            Report = pool.get('account.payment.sepa.mandate', type='report')
+
+            environment = setup_environment()
+            company = environment['company']
+            bank = environment['bank']
+            customer = environment['customer']
+            company_account, customer_account = setup_accounts(
+                bank, company, customer)
+            mandate = setup_mandate(company, customer, customer_account)
+
+            oext, content, _, _ = Report.execute([mandate.id], {})
+            self.assertEqual(oext, 'odt')
+            self.assertTrue(content)
+
 
 def suite():
     suite = trytond.tests.test_tryton.suite()
diff --git a/tryton.cfg b/tryton.cfg
index ff9390b..d842ac8 100644
--- a/tryton.cfg
+++ b/tryton.cfg
@@ -1,11 +1,13 @@
 [tryton]
-version=3.4.1
+version=3.6.0
 depends:
     account_payment
     company
     ir
     bank
     party
+extra_depends:
+    account_payment_clearing
 xml:
     payment.xml
     party.xml
diff --git a/trytond_account_payment_sepa.egg-info/PKG-INFO b/trytond_account_payment_sepa.egg-info/PKG-INFO
index b2371b2..0d8e740 100644
--- a/trytond_account_payment_sepa.egg-info/PKG-INFO
+++ b/trytond_account_payment_sepa.egg-info/PKG-INFO
@@ -1,12 +1,12 @@
 Metadata-Version: 1.1
 Name: trytond-account-payment-sepa
-Version: 3.4.1
+Version: 3.6.0
 Summary: Tryton module for SEPA payment
 Home-page: http://www.tryton.org/
 Author: Tryton
 Author-email: issue_tracker at tryton.org
 License: GPL-3
-Download-URL: http://downloads.tryton.org/3.4/
+Download-URL: http://downloads.tryton.org/3.6/
 Description: trytond_account_payment_sepa
         ============================
         
@@ -64,5 +64,7 @@ Classifier: Natural Language :: Slovenian
 Classifier: Natural Language :: Spanish
 Classifier: Operating System :: OS Independent
 Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: Implementation :: CPython
+Classifier: Programming Language :: Python :: Implementation :: PyPy
 Classifier: Topic :: Office/Business
 Classifier: Topic :: Office/Business :: Financial :: Accounting
diff --git a/trytond_account_payment_sepa.egg-info/SOURCES.txt b/trytond_account_payment_sepa.egg-info/SOURCES.txt
index 317be22..bff80a2 100644
--- a/trytond_account_payment_sepa.egg-info/SOURCES.txt
+++ b/trytond_account_payment_sepa.egg-info/SOURCES.txt
@@ -28,11 +28,14 @@ tryton.cfg
 ./locale/es_ES.po
 ./locale/fr_FR.po
 ./locale/sl_SI.po
+./template/base.003.xml
 ./template/base.xml
 ./template/pain.001.001.03.xml
 ./template/pain.001.001.05.xml
+./template/pain.001.003.03.xml
 ./template/pain.008.001.02.xml
 ./template/pain.008.001.04.xml
+./template/pain.008.003.02.xml
 ./tests/__init__.py
 ./tests/camt.054.001.01.xsd
 ./tests/camt.054.001.02.xsd
@@ -40,8 +43,10 @@ tryton.cfg
 ./tests/camt.054.001.04.xsd
 ./tests/pain.001.001.03.xsd
 ./tests/pain.001.001.05.xsd
+./tests/pain.001.003.03.xsd
 ./tests/pain.008.001.02.xsd
 ./tests/pain.008.001.04.xsd
+./tests/pain.008.003.02.xsd
 ./tests/test_account_payment_sepa.py
 ./view/configuration_form.xml
 ./view/mandate_form.xml
@@ -61,19 +66,24 @@ locale/es_EC.po
 locale/es_ES.po
 locale/fr_FR.po
 locale/sl_SI.po
+template/base.003.xml
 template/base.xml
 template/pain.001.001.03.xml
 template/pain.001.001.05.xml
+template/pain.001.003.03.xml
 template/pain.008.001.02.xml
 template/pain.008.001.04.xml
+template/pain.008.003.02.xml
 tests/camt.054.001.01.xsd
 tests/camt.054.001.02.xsd
 tests/camt.054.001.03.xsd
 tests/camt.054.001.04.xsd
 tests/pain.001.001.03.xsd
 tests/pain.001.001.05.xsd
+tests/pain.001.003.03.xsd
 tests/pain.008.001.02.xsd
 tests/pain.008.001.04.xsd
+tests/pain.008.003.02.xsd
 trytond_account_payment_sepa.egg-info/PKG-INFO
 trytond_account_payment_sepa.egg-info/SOURCES.txt
 trytond_account_payment_sepa.egg-info/dependency_links.txt
diff --git a/trytond_account_payment_sepa.egg-info/requires.txt b/trytond_account_payment_sepa.egg-info/requires.txt
index d610120..643da8e 100644
--- a/trytond_account_payment_sepa.egg-info/requires.txt
+++ b/trytond_account_payment_sepa.egg-info/requires.txt
@@ -1,7 +1,8 @@
 Genshi
 lxml
-trytond_account_payment >= 3.4, < 3.5
-trytond_company >= 3.4, < 3.5
-trytond_bank >= 3.4, < 3.5
-trytond_party >= 3.4, < 3.5
-trytond >= 3.4, < 3.5
\ No newline at end of file
+python-dateutil
+trytond_account_payment >= 3.6, < 3.7
+trytond_company >= 3.6, < 3.7
+trytond_bank >= 3.6, < 3.7
+trytond_party >= 3.6, < 3.7
+trytond >= 3.6, < 3.7
\ No newline at end of file
diff --git a/view/payment_group_form.xml b/view/payment_group_form.xml
index 2a2a169..e2409eb 100644
--- a/view/payment_group_form.xml
+++ b/view/payment_group_form.xml
@@ -4,5 +4,6 @@ this repository contains the full copyright notices and license terms. -->
 <data>
     <xpath expr="/form/field[@name='kind']" position="after">
         <field name="sepa_messages" colspan="4"/>
+        <button name="generate_message" string="Generate Message" colspan="4"/>
     </xpath>
 </data>
diff --git a/view/payment_journal_form.xml b/view/payment_journal_form.xml
index 0f2e1b1..c14b08c 100644
--- a/view/payment_journal_form.xml
+++ b/view/payment_journal_form.xml
@@ -3,8 +3,7 @@
 this repository contains the full copyright notices and license terms. -->
 <data>
     <xpath expr="/form/field[@name='process_method']" position="after">
-        <separator id="sepa" string="SEPA" colspan="4"
-            states="{'invisible': Eval('process_method') != 'sepa'}"/>
+        <separator name="sepa_bank_account_number" string="SEPA" colspan="4"/>
         <label name="sepa_bank_account_number"/>
         <field name="sepa_bank_account_number"/>
         <newline/>
-- 
tryton-modules-account-payment-sepa



More information about the tryton-debian-vcs mailing list