Commit 03ebf87f authored by Jérome Perrin's avatar Jérome Perrin

payment_mean_sepa: new business template

Support generating pain.001.001.02 credit transfer from payment transaction
groups.
parent fc2123ba
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ActionInformation" module="Products.CMFCore.ActionInformation"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/object_jio_action</string>
</tuple>
</value>
</item>
<item>
<key> <string>category</string> </key>
<value> <string>object_jio_action</string> </value>
</item>
<item>
<key> <string>condition</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>generate_sepa_credit_transfer</string> </value>
</item>
<item>
<key> <string>permissions</string> </key>
<value>
<tuple>
<string>Modify portal content</string>
</tuple>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Action Information</string> </value>
</item>
<item>
<key> <string>priority</string> </key>
<value> <float>4.0</float> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Generate SEPA Credit Transfer File</string> </value>
</item>
<item>
<key> <string>visible</string> </key>
<value> <int>1</int> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Expression" module="Products.CMFCore.Expression"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>string:${object_url}/PaymentTransactionGroup_viewGenerateSEPACreditTransferFileDialog?reset:int=1</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="Expression" module="Products.CMFCore.Expression"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>python: context.getValidationState() in ( \'open\', \'closed\', \'delivered\') and context.isMemberOf(\'payment_transaction_group_type/outgoing\')</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Folder" module="OFS.Folder"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>erp5_payment_mean_sepa</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
"""Return a text to use as Unstructured RemittanceInformation for this payment transaction.
This is used in SEPA Credit Transfer export, 2.90 RemittanceInformation
This script is a customization point.
"""
ptg = context.getAggregateValue(portal_type='Payment Transaction Group')
if ptg.getSourcePayment() == context.getSourcePayment():
third_party = context.getDestinationSectionValue()
else:
third_party = context.getSourceSectionValue()
third_party_name = third_party.getCorporateName() or third_party.getTitle()
return "{invoice_reference} {third_party_name}".format(
invoice_reference=context.getParentValue().getCausalityReference() or '',
third_party_name=third_party_name,
).strip()
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>AccountingTransactionLine_getSEPACreditTransferRemittanceInformation</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
from Products.ERP5Type.Message import translateString
assert version == 'pain.001.001.02', 'Unsupported version'
portal = context.getPortalObject()
portal.portal_contributions.newContent(
reference=context.getSourceReference(),
data=getattr(context, 'PaymentTransactionGroup_viewAsSEPACreditTransferPain.001.001.02')().encode('utf-8'),
filename=context.getSourceReference() + '.xml',
# XXX we should probably use a dedicated type based method or preference,
# for now we use the same as for *attached* documents.
publication_section=context.getTypeBasedMethod('getPreferredAttachedDocumentPublicationSection')(),
follow_up=context.getRelativeUrl(),
).release()
return context.Base_redirect(form_id, keep_items={
'portal_status_message': translateString('SEPA Credit Transfer File generated.')
})
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>version, form_id=\'\', **kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>PaymentTransactionGroup_generateSEPACreditTransferFile</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
section = context.getSourceSectionValue()
section_bank_account = context.getSourcePaymentValue()
assert section_bank_account.getValidationState() == 'validated'
currency = context.getPriceCurrencyReference() or context.getPriceCurrencyTitle()
assert currency.upper() == 'EUR', 'Wrong currency %s' % currency
data_dict = {
'GrpHdr': {
'MsgId': context.getSourceReference(),
'CreDtTm': context.getStopDate().toZone('UTC').asdatetime().isoformat(),
'InitgPty': {
'Nm': section.getCorporateName() or section.getTitle(),
}
},
'PmtInf': {
'PmtInfId': context.getReference() or context.getSourceReference(),
'ReqdExctnDt':context.getStopDate().toZone('UTC').asdatetime().strftime('%Y-%m-%d'),
'Dbtr': {
'Nm': section.getCorporateName() or section.getTitle(),
},
'DbtrAcct': {
'Id': {
'IBAN': section_bank_account.getIban().replace(' ', '').replace('\t', ''),
}
},
'DbtrAgt': {
'FinInstnId': {
'BIC': section_bank_account.getBicCode().strip(),
}
}
},
}
# This does not support payment transactions with multiple lines.
# To prevent generating a file where the same end to end id exists twice,
# we just check that EndToEndId are unique in this file.
end_to_end_id_set = set([])
transaction_list = []
total = 0
for brain in context.PaymentTransactionGroup_getAccountingTransactionLineList():
amount = round(-brain.total_quantity, 2)
assert amount > 0
total += amount
transaction_line = brain.getObject()
transaction = transaction_line.getExplanationValue()
if brain.payment_uid == transaction_line.getSourcePaymentUid():
creditor_entity = transaction_line.getDestinationSectionValue()
creditor_bank_account = transaction_line.getDestinationPaymentValue()
else:
assert brain.payment_uid == transaction_line.getDestinationPaymentUid()
creditor_entity = transaction_line.getSourceSectionValue()
creditor_bank_account = transaction_line.getSourcePaymentValue()
assert creditor_bank_account.getValidationState() == 'validated', \
'%s is not validated' % creditor_bank_account.getRelativeUrl()
end_to_end_id = transaction.PaymentTransaction_getOrGenerateReference()
assert end_to_end_id not in end_to_end_id_set
end_to_end_id_set.add(end_to_end_id)
transaction_list.append(
{
'PmtId': {
'EndToEndId': end_to_end_id,
},
'RmtInf': {
'Ustrd': transaction_line.AccountingTransactionLine_getSEPACreditTransferRemittanceInformation(),
},
'Cdtr': {
'Nm': creditor_entity.getCorporateName() or creditor_entity.getTitle(),
'PstlAdr': (creditor_entity.getDefaultAddressText() or '').splitlines(),
'Ctry': creditor_entity.getDefaultAddressRegion() and creditor_entity.getDefaultAddressValue().getRegionReference(),
},
'Amt': {
'InstdAmt': '%0.2f' % amount
},
'CdtrAcct': {
'Id': {
'IBAN': creditor_bank_account.getIban().replace(' ', '').replace('\t', ''),
}
},
'CdtrAgt': {
'FinInstnId': {
'BIC': section_bank_account.getBicCode().strip(),
}
}
}
)
data_dict['GrpHdr']['NbOfTxs'] = len(transaction_list)
data_dict['GrpHdr']['CtrlSum'] = '%0.2f' % total
data_dict['transaction_list'] = transaction_list
return data_dict
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>PaymentTransactionGroup_getSEPACreditTransferDataDict</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ZopePageTemplate" module="Products.PageTemplates.ZopePageTemplate"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/xml</string> </value>
</item>
<item>
<key> <string>expand</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>PaymentTransactionGroup_viewAsSEPACreditTransferPain.001.001.02</string> </value>
</item>
<item>
<key> <string>output_encoding</string> </key>
<value> <string>utf-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <unicode></unicode> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Document
xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.02"
tal:define="data context/PaymentTransactionGroup_getSEPACreditTransferDataDict">
<pain.001.001.02>
<GrpHdr>
<MsgId tal:content="data/GrpHdr/MsgId"></MsgId>
<CreDtTm tal:content="data/GrpHdr/CreDtTm">2001-02-03T04:05:06</CreDtTm>
<BtchBookg>true</BtchBookg>
<NbOfTxs tal:content="data/GrpHdr/NbOfTxs">1</NbOfTxs>
<CtrlSum tal:content="data/GrpHdr/CtrlSum">1000</CtrlSum>
<Grpg>MIXD</Grpg>
<InitgPty>
<Nm tal:content="data/GrpHdr/InitgPty/Nm"></Nm>
</InitgPty>
</GrpHdr>
<PmtInf>
<PmtInfId tal:content="data/PmtInf/PmtInfId"></PmtInfId>
<PmtMtd>TRF</PmtMtd>
<PmtTpInf>
<SvcLvl>
<Cd>SEPA</Cd>
</SvcLvl>
</PmtTpInf>
<ReqdExctnDt tal:content="data/PmtInf/ReqdExctnDt">1970-01-01</ReqdExctnDt>
<Dbtr>
<Nm tal:content="data/PmtInf/Dbtr/Nm"></Nm>
</Dbtr>
<DbtrAcct>
<Id>
<IBAN tal:content="data/PmtInf/DbtrAcct/Id/IBAN"></IBAN>
</Id>
<Ccy>EUR</Ccy>
</DbtrAcct>
<DbtrAgt>
<FinInstnId>
<BIC tal:content="data/PmtInf/DbtrAgt/FinInstnId/BIC"></BIC>
</FinInstnId>
</DbtrAgt>
<CdtTrfTxInf tal:repeat="transaction data/transaction_list">
<PmtId>
<EndToEndId tal:content="transaction/PmtId/EndToEndId"></EndToEndId>
</PmtId>
<Amt>
<InstdAmt Ccy="EUR" tal:content="transaction/Amt/InstdAmt">123.45</InstdAmt>
</Amt>
<CdtrAgt>
<FinInstnId>
<BIC tal:content="transaction/CdtrAgt/FinInstnId/BIC">XXX</BIC>
</FinInstnId>
</CdtrAgt>
<Cdtr>
<Nm tal:content="transaction/Cdtr/Nm"></Nm>
<PstlAdr tal:condition="transaction/Cdtr/Ctry">
<tal:block tal:repeat="line transaction/Cdtr/PstlAdr">
<AdrLine tal:content="line"></AdrLine>
</tal:block>
<Ctry tal:content="transaction/Cdtr/Ctry"></Ctry>
</PstlAdr>
</Cdtr>
<CdtrAcct>
<Id>
<IBAN tal:content="transaction/CdtrAcct/Id/IBAN">FR76...</IBAN>
</Id>
</CdtrAcct>
<RmtInf>
<Ustrd tal:content="transaction/RmtInf/Ustrd"></Ustrd>
</RmtInf>
</CdtTrfTxInf>
</PmtInf>
</pain.001.001.02>
</Document>
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ERP5 Form" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>action</string> </key>
<value> <string>PaymentTransactionGroup_generateSEPACreditTransferFile</string> </value>
</item>
<item>
<key> <string>action_title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>edit_order</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>enctype</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>group_list</string> </key>
<value>
<list>
<string>left</string>
<string>right</string>
<string>center</string>
<string>bottom</string>
<string>hidden</string>
</list>
</value>
</item>
<item>
<key> <string>groups</string> </key>
<value>
<dictionary>
<item>
<key> <string>bottom</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>center</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>hidden</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>left</string> </key>
<value>
<list>
<string>your_version</string>
</list>
</value>
</item>
<item>
<key> <string>right</string> </key>
<value>
<list/>
</value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>PaymentTransactionGroup_viewGenerateSEPACreditTransferFileDialog</string> </value>
</item>
<item>
<key> <string>method</string> </key>
<value> <string>POST</string> </value>
</item>
<item>
<key> <string>name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>pt</string> </key>
<value> <string>form_dialog</string> </value>
</item>
<item>
<key> <string>row_length</string> </key>
<value> <int>4</int> </value>
</item>
<item>
<key> <string>stored_encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Generate SEPA Credit Transfer File</string> </value>
</item>
<item>
<key> <string>unicode_mode</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>update_action</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>update_action_title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
"""Returns an unique reference for this payment transaction. If it does not already have a reference, a new one is generated.
"""
context.getTypeBasedMethod('generateReference')()
return context.getReference()
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>PaymentTransaction_getOrGenerateReference</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>pain.001.001.02.xsd</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/xml</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>pain.001.001.02.xsd</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
##############################################################################
# coding: utf-8
# Copyright (c) 2021 Nexedi SA and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# guarantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
##############################################################################
import urlparse
import lxml.etree
from DateTime import DateTime
from erp5.component.test.testAccounting import AccountingTestCase
class TestPaymentTransactionGroupPaymentSEPA(AccountingTestCase):
def afterSetUp(self):
AccountingTestCase.afterSetUp(self)
self.login()
self.bank_account = self.section.newContent(
portal_type='Bank Account',
iban='FR76 3000 6000 0112 3456 7890 189',
bic_code='TESTXXXX',
price_currency_value=self.portal.currency_module.euro)
self.bank_account.validate()
if 'FR' not in self.portal.portal_categories.region.objectIds():
self.portal.portal_categories.region.newContent(
portal_type='Category',
id='FR',
title='France',
reference='FR',
)
self.tic()
def _createPaymentsAndPTG(self):
ptg = self.portal.payment_transaction_group_module.newContent(
portal_type='Payment Transaction Group',
source_section_value=self.section,
source_payment_value=self.bank_account,
price_currency_value=self.portal.currency_module.euro,
stop_date=DateTime('2021/01/02 03:04:05 Europe/Paris'),
)
ptg.open()
account_module = self.account_module
invoice_1 = self._makeOne(
portal_type='Sale Invoice Transaction',
reference='INVOICE1'
)
supplier1 = self.portal.organisation_module.newContent(
portal_type='Organisation',
title='Supplier1',
default_address_street_address='1 rue des pommes\n3ème étage',
default_address_city='LILLE',
default_address_zip_code='59000',
default_address_region='FR',
)
bank_account_supplier1 = supplier1.newContent(
portal_type='Bank Account',
iban='FI1410093000123458',
bic_code='TESTXXXX'
)
bank_account_supplier1.validate()
payment_1 = self._makeOne(
portal_type='Payment Transaction',
simulation_state='delivered',
title='one',
causality_value=invoice_1,
source_section_value=self.section,
source_payment_value=self.bank_account,
destination_section_value=supplier1,
destination_payment_value=bank_account_supplier1,
start_date=DateTime(2021, 1, 1),
lines=(
dict(
source_value=account_module.payable,
source_debit=100),
dict(
source_value=account_module.bank,
source_credit=100,
aggregate_value=ptg)))
supplier2 = self.portal.organisation_module.newContent(
portal_type='Organisation',
title='Supplier2'
)
bank_account_supplier2 = supplier2.newContent(
portal_type='Bank Account',
iban='CY21002001950000357001234567',
bic_code='TESTXXXX'
)
bank_account_supplier2.validate()
payment_2 = self._makeOne(
portal_type='Payment Transaction',
simulation_state='delivered',
title='two',
destination_section_value=self.section,
destination_payment_value=self.bank_account,
source_section_value=supplier2,
source_payment_value=bank_account_supplier2,
start_date=DateTime(2021, 1, 1),
lines=(
dict(
destination_value=account_module.payable,
destination_debit=200),
dict(
destination_value=account_module.bank,
destination_credit=200,
aggregate_value=ptg)))
self.tic()
return payment_1, payment_2, ptg
def test_PaymentTransactionGroup_viewAsSEPACreditTransferPain_001_001_02(self):
payment_1, payment_2, ptg = self._createPaymentsAndPTG()
pain = lxml.etree.fromstring(
getattr(ptg, 'PaymentTransactionGroup_viewAsSEPACreditTransferPain.001.001.02')().encode('utf-8'))
# this XML validates against the schema
xmlschema = lxml.etree.XMLSchema(
lxml.etree.fromstring(str(getattr(self.portal, 'pain.001.001.02.xsd').data)))
xmlschema.assertValid(pain)
self.assertEqual(
[node.text for node in pain.findall('.//{*}GrpHdr/{*}MsgId')],
[ptg.getSourceReference()],
)
self.assertEqual(
[node.text for node in pain.findall('.//{*}GrpHdr/{*}NbOfTxs')],
['2'],
)
self.assertEqual(
[node.text for node in pain.findall('.//{*}GrpHdr/{*}CtrlSum')],
['300.00'],
)
self.assertEqual(
[node.text for node in pain.findall('.//{*}CreDtTm')],
['2021-01-02T02:04:05+00:00'],
)
self.assertEqual(
[node.text for node in pain.findall('.//{*}InitgPty/{*}Nm')],
['My Organisation Inc.'],
)
self.assertEqual(
[node.text for node in pain.findall('.//{*}DbtrAcct/{*}Id/{*}IBAN')],
['FR7630006000011234567890189'],
)
self.assertEqual(
sorted([node.text for node in pain.findall('.//{*}CdtTrfTxInf/{*}CdtrAcct/{*}Id/{*}IBAN')]),
['CY21002001950000357001234567', 'FI1410093000123458'],
)
self.assertEqual(
sorted([node.text for node in pain.findall('.//{*}CdtTrfTxInf/{*}Amt/{*}InstdAmt')]),
['100.00', '200.00'],
)
self.assertEqual(
sorted([node.text for node in pain.findall('.//{*}CdtTrfTxInf/{*}Cdtr/{*}Nm')]),
['Supplier1', 'Supplier2'],
)
self.assertEqual(
[node.text for node in pain.findall('.//{*}CdtTrfTxInf/{*}Cdtr/{*}PstlAdr/{*}AdrLine')],
[u'1 rue des pommes', u'3ème étage', u'59000 LILLE'],
)
self.assertEqual(
sorted([node.text for node in pain.findall('.//{*}CdtTrfTxInf/{*}RmtInf/{*}Ustrd')]),
['INVOICE1 Supplier1', 'Supplier2'],
)
# generating the XML file set reference on payment transactions
self.assertTrue(payment_1.getReference())
self.assertTrue(payment_2.getReference())
self.assertEqual(
sorted([node.text for node in pain.findall('.//{*}CdtTrfTxInf/{*}PmtId/{*}EndToEndId')]),
sorted([payment_1.getReference(), payment_2.getReference()]),
)
def test_generate_sepa_credit_transfer_action(self):
_, _, ptg = self._createPaymentsAndPTG()
ret = ptg.PaymentTransactionGroup_generateSEPACreditTransferFile(
version='pain.001.001.02')
self.assertEqual(
urlparse.parse_qs(urlparse.urlparse(ret).query)['portal_status_message'],
['SEPA Credit Transfer File generated.'])
self.tic()
f, = ptg.getFollowUpRelatedValueList(
portal_type='File',
)
self.assertEqual(f.getReference(), ptg.getSourceReference())
pain = lxml.etree.fromstring(f.getData())
xmlschema = lxml.etree.XMLSchema(
lxml.etree.fromstring(str(getattr(self.portal, 'pain.001.001.02.xsd').data)))
xmlschema.assertValid(pain)
self.assertEqual(
[node.text for node in pain.findall('.//{*}GrpHdr/{*}CtrlSum')],
['300.00'],
)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Test Component" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_recorded_property_dict</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>default_reference</string> </key>
<value> <string>testPaymentTransactionGroupSEPA</string> </value>
</item>
<item>
<key> <string>default_source_reference</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>test.erp5.testPaymentTransactionGroupSEPA</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Test Component</string> </value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>text_content_error_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>text_content_warning_message</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>version</string> </key>
<value> <string>erp5</string> </value>
</item>
<item>
<key> <string>workflow_history</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary>
<item>
<key> <string>component_validation_workflow</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="WorkflowHistoryList" module="Products.ERP5Type.Workflow"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_log</string> </key>
<value>
<list>
<dictionary>
<item>
<key> <string>action</string> </key>
<value> <string>validate</string> </value>
</item>
<item>
<key> <string>validation_state</string> </key>
<value> <string>validated</string> </value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
erp5_payment_mean
erp5_ingestion
erp5_dms
\ No newline at end of file
Single Euro Payments Area (SEPA) support for payment transactions.
\ No newline at end of file
Payment Transaction Group | generate_sepa_credit_transfer
\ No newline at end of file
erp5_payment_mean_sepa
\ No newline at end of file
test.erp5.testPaymentTransactionGroupSEPA
\ No newline at end of file
erp5_full_text_mroonga_catalog
erp5_accounting_ui_test
\ No newline at end of file
erp5_payment_mean_sepa
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment