[MIG] account_banking_sepa_direct_debit

This commit is contained in:
etobella
2017-10-17 16:12:16 +02:00
committed by Enric Tobella
parent 5d312aa87c
commit c8303f304c
24 changed files with 202 additions and 126 deletions

View File

@@ -35,26 +35,26 @@ Configuration
For setting the SEPA creditor identifier:
#. Go to Accounting > Configuration > Settings.
#. Go to Invoicing/Accounting > Configuration > Settings.
#. On the field "SEPA Creditor Identifier" in the section *SEPA/PAIN*, you can
fill the corresponding identifier.
If your country requires several identifiers (like Spain), you must:
#. Go to *Accounting > Configuration > Settings*.
#. Go to *Invoicing/Accounting > Configuration > Settings*.
#. On the section *SEPA/PAIN*, check the mark "Multiple identifiers".
#. Now go to *Accounting > Configuration > Management > Payment Modes*.
#. Now go to *Invoicing/Accounting > Configuration > Management > Payment Modes*.
#. Create a payment mode for your specific bank.
#. Fill the specific identifier on the field "SEPA Creditor Identifier".
For defining a payment mode that uses SEPA direct debit:
#. Go to *Accounting > Configuration > Management > Payment Modes*.
#. Go to *Invoicing/Accounting > Configuration > Management > Payment Modes*.
#. Create a record.
#. Select the Payment Method *SEPA Direct Debit for customers* (which is
automatically created upon module installation).
#. Check that this payment method uses the proper version of PAIN.
#. If not, go *Accounting > Configuration > Management > Payment Methods*.
#. If not, go *Invoicing/Accounting > Configuration > Management > Payment Methods*.
#. Locate the "SEPA Direct Debit for customers" record and open it.
#. Change the "PAIN version" according your needs.
#. If you need to handle several PAIN versions, just duplicate the payment
@@ -63,13 +63,13 @@ For defining a payment mode that uses SEPA direct debit:
Usage
=====
In the menu *Accounting > Payments > Debit Order*, create a new debit
In the menu *Invoicing/Accounting > Payments > Debit Order*, create a new debit
order and select the Payment Mode dedicated to SEPA Direct Debit that
you created during the configuration step.
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
:target: https://runbot.odoo-community.org/runbot/173/10.0
:target: https://runbot.odoo-community.org/runbot/173/11.0
Known issues / Roadmap
======================
@@ -103,7 +103,7 @@ Contributors
Maintainer
----------
.. image:: http://odoo-community.org/logo.png
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org

View File

@@ -2,12 +2,12 @@
# Copyright 2013-2016 Akretion (www.akretion.com)
# Copyright 2014-2017 Tecnativa - Pedro M. Baeza
# Copyright 2016 Tecnativa - Antonio Espinosa
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
{
'name': 'Account Banking SEPA Direct Debit',
'summary': 'Create SEPA files for Direct Debit',
'version': '10.0.1.1.0',
'version': '11.0.1.0.0',
'license': 'AGPL-3',
'author': "Akretion, "
"Tecnativa, "

View File

@@ -1,17 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record id="sepa_direct_debit" model="account.payment.method">
<field name="name">SEPA Direct Debit for customers</field>
<field name="code">sepa_direct_debit</field>
<field name="payment_type">inbound</field>
<field name="bank_account_required" eval="True"/>
<field name="mandate_required" eval="True"/>
<field name="pain_version">pain.008.001.02</field>
</record>
</data>
<odoo noupdate="1">
<record id="sepa_direct_debit" model="account.payment.method">
<field name="name">SEPA Direct Debit for customers</field>
<field name="code">sepa_direct_debit</field>
<field name="payment_type">inbound</field>
<field name="bank_account_required" eval="True"/>
<field name="mandate_required" eval="True"/>
<field name="pain_version">pain.008.001.02</field>
</record>
</odoo>

View File

@@ -2,22 +2,19 @@
<!--
© 2013-2016 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
-->
<odoo>
<data noupdate="1">
<record id="sdd_mandate_expire_cron" model="ir.cron">
<field name="name">Set SEPA Direct Debit Mandates to Expired</field>
<field name="active" eval="True"/>
<field name="user_id" ref="base.user_root"/>
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field name="doall" eval="False"/>
<field name="model" eval="'account.banking.mandate'"/>
<field name="function" eval="'_sdd_mandate_set_state_to_expired'" />
<field name="args" eval="'()'"/>
</record>
</data>
<odoo noupdate="1">
<record id="sdd_mandate_expire_cron" model="ir.cron">
<field name="name">Set SEPA Direct Debit Mandates to Expired</field>
<field name="active" eval="True"/>
<field name="model_id" ref="model_account_banking_mandate"/>
<field name="state">code</field>
<field name="code">model._sdd_mandate_set_state_to_expired()</field>
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field name="user_id" ref="base.user_root"/>
</record>
</odoo>

View File

@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
# © 2013-2016 Akretion - Alexis de Lattre <alexis.delattre@akretion.com>
# © 2014 Serv. Tecnol. Avanzados - Pedro M. Baeza
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import models, fields, api, exceptions, _
from datetime import datetime
@@ -20,10 +20,11 @@ class AccountBankingMandate(models.Model):
format = fields.Selection(
selection_add=[('sepa', 'Sepa Mandate')], default='sepa')
type = fields.Selection([('recurrent', 'Recurrent'),
('oneoff', 'One-Off')],
string='Type of Mandate',
track_visibility='onchange')
type = fields.Selection(
selection_add=[
('recurrent', 'Recurrent'),
('oneoff', 'One-Off')
])
recurrent_sequence_type = fields.Selection(
[('first', 'First'),
('recurring', 'Recurring'),
@@ -66,10 +67,12 @@ class AccountBankingMandate(models.Model):
for mandate in self:
super(AccountBankingMandate, self).mandate_partner_bank_change()
res = {}
if (mandate.state == 'valid' and
mandate.partner_bank_id and
mandate.type == 'recurrent' and
mandate.recurrent_sequence_type != 'first'):
if (
mandate.state == 'valid' and
mandate.partner_bank_id and
mandate.type == 'recurrent' and
mandate.recurrent_sequence_type != 'first'
):
mandate.recurrent_sequence_type = 'first'
res['warning'] = {
'title': _('Mandate update'),
@@ -82,8 +85,8 @@ class AccountBankingMandate(models.Model):
@api.model
def _sdd_mandate_set_state_to_expired(self):
logger.info('Searching for SDD Mandates that must be set to Expired')
expire_limit_date = datetime.today() + \
relativedelta(months=-NUMBER_OF_UNUSED_MONTHS_BEFORE_EXPIRY)
expire_limit_date = datetime.today() + relativedelta(
months=-NUMBER_OF_UNUSED_MONTHS_BEFORE_EXPIRY)
expire_limit_date_str = expire_limit_date.strftime('%Y-%m-%d')
expired_mandates = self.search(
['|',

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# © 2016 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import models, fields, api

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# © 2016 Antiun Ingenieria S.L. - Antonio Espinosa
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import models, fields, api, _
from .common import is_sepa_creditor_identifier_valid

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# © 2016 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import models, fields, api, _
from odoo.exceptions import UserError
@@ -114,7 +114,7 @@ class AccountPaymentOrder(models.Model):
lines_per_group[key] = [line]
for (requested_date, priority, categ_purpose, sequence_type, scheme),\
lines in lines_per_group.items():
lines in list(lines_per_group.items()):
# B. Payment info
payment_info, nb_of_transactions_b, control_sum_b = \
self.generate_start_payment_info_block(
@@ -218,9 +218,9 @@ class AccountPaymentOrder(models.Model):
self.generate_remittance_info_block(
dd_transaction_info, line, gen_args)
nb_of_transactions_b.text = unicode(transactions_count_b)
nb_of_transactions_b.text = str(transactions_count_b)
control_sum_b.text = '%.2f' % amount_control_sum_b
nb_of_transactions_a.text = unicode(transactions_count_a)
nb_of_transactions_a.text = str(transactions_count_a)
control_sum_a.text = '%.2f' % amount_control_sum_a
return self.finalize_sepa_file_creation(

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# © 2015-2016 Akretion - Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import models, api
@@ -19,5 +19,5 @@ class BankPaymentLine(models.Model):
"""
hashcode = super(BankPaymentLine, self).\
move_line_offsetting_account_hashcode()
hashcode += '-' + unicode(self.mandate_id.recurrent_sequence_type)
hashcode += '-' + str(self.mandate_id.recurrent_sequence_type)
return hashcode

View File

@@ -2,7 +2,7 @@
# © 2013-2016 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
# © 2014 Serv. Tecnol. Avanzados - Pedro M. Baeza
# © 2016 Antiun Ingenieria S.L. - Antonio Espinosa
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
import logging
@@ -15,7 +15,7 @@ def is_sepa_creditor_identifier_valid(sepa_creditor_identifier):
or unicode
@return: True if valid, False otherwise
"""
if not isinstance(sepa_creditor_identifier, (str, unicode)):
if not isinstance(sepa_creditor_identifier, str):
return False
try:
sci = str(sepa_creditor_identifier).lower()

View File

@@ -2,7 +2,7 @@
# © 2013-2016 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
# © 2014 Serv. Tecnol. Avanzados - Pedro M. Baeza
# © 2016 Antiun Ingenieria S.L. - Antonio Espinosa
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import models, fields, api, _
from .common import is_sepa_creditor_identifier_valid

View File

@@ -1,12 +1,12 @@
# -*- coding: utf-8 -*-
# © 2016 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import models, fields
class AccountConfigSettings(models.TransientModel):
_inherit = 'account.config.settings'
class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
sepa_creditor_identifier = fields.Char(
related='company_id.sepa_creditor_identifier')

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# © 2016 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import api, SUPERUSER_ID

View File

@@ -11,7 +11,7 @@
file="account_banking_sepa_direct_debit.sepa_direct_debit_mandate"
/>
<record id="report_sepa_direct_debit_mandate" model="ir.actions.report.xml">
<record id="report_sepa_direct_debit_mandate" model="ir.actions.report">
<field name="paperformat_id"
ref="account_banking_sepa_direct_debit.paperformat_euro_sepa_lowmargin"/>
</record>

View File

@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
from . import test_sdd
from . import test_mandate

View File

@@ -0,0 +1,47 @@
# -*- coding: utf-8 -*-
# © 2016 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo.tests.common import TransactionCase
from odoo.exceptions import ValidationError
from datetime import datetime
from dateutil.relativedelta import relativedelta
class TestMandate(TransactionCase):
def test_contrains(self):
with self.assertRaises(ValidationError):
self.mandate.recurrent_sequence_type = False
self.mandate.type = 'recurrent'
self.mandate._check_recurring_type()
def test_onchange_bank(self):
self.mandate.write({
'type': 'recurrent', 'recurrent_sequence_type': 'recurring'
})
self.mandate.validate()
self.mandate.partner_bank_id = self.env.ref(
'account_payment_mode.res_partner_2_iban'
)
self.mandate.mandate_partner_bank_change()
self.assertEqual(self.mandate.recurrent_sequence_type, 'first')
def test_expire(self):
self.mandate.signature_date = datetime.now() + relativedelta(
months=-50)
self.mandate.validate()
self.assertEqual(self.mandate.state, 'valid')
self.env['account.banking.mandate']._sdd_mandate_set_state_to_expired()
self.assertEqual(self.mandate.state, 'expired')
def setUp(self):
res = super(TestMandate, self).setUp()
self.partner = self.env.ref('base.res_partner_12')
bank_account = self.env.ref('account_payment_mode.res_partner_12_iban')
self.mandate = self.env['account.banking.mandate'].create({
'partner_bank_id': bank_account.id,
'format': 'sepa',
'type': 'oneoff',
'signature_date': '2015-01-01',
})
return res

View File

@@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
# © 2016 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo.addons.account.tests.account_test_classes\
import AccountingTestCase
import base64
from odoo.addons.account.tests.account_test_classes import AccountingTestCase
from odoo.tools import float_compare
import time
from lxml import etree
@@ -60,72 +60,91 @@ class TestSDD(AccountingTestCase):
for bank_acc in self.partner_bank_model.search([]):
bank_acc.acc_number = bank_acc.acc_number
def test_sdd(self):
def test_pain_001_02(self):
self.payment_mode.payment_method_id.pain_version = 'pain.008.001.02'
self.check_sdd()
def test_pain_003_02(self):
self.payment_mode.payment_method_id.pain_version = 'pain.008.003.02'
self.check_sdd()
def test_pain_001_03(self):
self.payment_mode.payment_method_id.pain_version = 'pain.008.001.03'
self.check_sdd()
def test_pain_001_04(self):
self.payment_mode.payment_method_id.pain_version = 'pain.008.001.04'
self.check_sdd()
def check_sdd(self):
self.env.ref(
'account_banking_sepa_direct_debit.res_partner_2_mandate').\
recurrent_sequence_type = 'first'
'account_banking_sepa_direct_debit.res_partner_2_mandate'
).recurrent_sequence_type = 'first'
invoice1 = self.create_invoice(
self.partner_agrolait.id,
'account_banking_sepa_direct_debit.res_partner_2_mandate', 42.0)
self.env.ref(
'account_banking_sepa_direct_debit.res_partner_12_mandate'
).type = 'oneoff'
invoice2 = self.create_invoice(
self.partner_c2c.id,
'account_banking_sepa_direct_debit.res_partner_12_mandate', 11.0)
for inv in [invoice1, invoice2]:
action = inv.create_account_payment_line()
self.assertEquals(action['res_model'], 'account.payment.order')
self.payment_order = self.payment_order_model.browse(action['res_id'])
self.assertEquals(
self.payment_order.payment_type, 'inbound')
self.assertEquals(
self.payment_order.payment_mode_id, self.payment_mode)
self.assertEquals(
self.payment_order.journal_id, self.bank_journal)
self.assertEqual(action['res_model'], 'account.payment.order')
payment_order = self.payment_order_model.browse(action['res_id'])
self.assertEqual(
payment_order.payment_type, 'inbound')
self.assertEqual(
payment_order.payment_mode_id, self.payment_mode)
self.assertEqual(
payment_order.journal_id, self.bank_journal)
# Check payment line
pay_lines = self.payment_line_model.search([
('partner_id', '=', self.partner_agrolait.id),
('order_id', '=', self.payment_order.id)])
self.assertEquals(len(pay_lines), 1)
('order_id', '=', payment_order.id)])
self.assertEqual(len(pay_lines), 1)
agrolait_pay_line1 = pay_lines[0]
accpre = self.env['decimal.precision'].precision_get('Account')
self.assertEquals(
self.assertEqual(
agrolait_pay_line1.currency_id.id, self.eur_currency_id)
self.assertEquals(
self.assertEqual(
agrolait_pay_line1.mandate_id, invoice1.mandate_id)
self.assertEquals(
self.assertEqual(
agrolait_pay_line1.partner_bank_id,
invoice1.mandate_id.partner_bank_id)
self.assertEquals(float_compare(
self.assertEqual(float_compare(
agrolait_pay_line1.amount_currency, 42, precision_digits=accpre),
0)
self.assertEquals(agrolait_pay_line1.communication_type, 'normal')
self.assertEquals(agrolait_pay_line1.communication, invoice1.number)
self.payment_order.draft2open()
self.assertEquals(self.payment_order.state, 'open')
self.assertEquals(self.payment_order.sepa, True)
self.assertEqual(agrolait_pay_line1.communication_type, 'normal')
self.assertEqual(agrolait_pay_line1.communication, invoice1.number)
payment_order.draft2open()
self.assertEqual(payment_order.state, 'open')
self.assertEqual(payment_order.sepa, True)
# Check bank payment line
bank_lines = self.bank_line_model.search([
('partner_id', '=', self.partner_agrolait.id)])
self.assertEquals(len(bank_lines), 1)
self.assertEqual(len(bank_lines), 1)
agrolait_bank_line = bank_lines[0]
self.assertEquals(
self.assertEqual(
agrolait_bank_line.currency_id.id, self.eur_currency_id)
self.assertEquals(float_compare(
self.assertEqual(float_compare(
agrolait_bank_line.amount_currency, 42.0, precision_digits=accpre),
0)
self.assertEquals(agrolait_bank_line.communication_type, 'normal')
self.assertEquals(
self.assertEqual(agrolait_bank_line.communication_type, 'normal')
self.assertEqual(
agrolait_bank_line.communication, invoice1.number)
self.assertEquals(
self.assertEqual(
agrolait_bank_line.mandate_id, invoice1.mandate_id)
self.assertEquals(
self.assertEqual(
agrolait_bank_line.partner_bank_id,
invoice1.mandate_id.partner_bank_id)
action = self.payment_order.open2generated()
self.assertEquals(self.payment_order.state, 'generated')
self.assertEquals(action['res_model'], 'ir.attachment')
action = payment_order.open2generated()
self.assertEqual(payment_order.state, 'generated')
self.assertEqual(action['res_model'], 'ir.attachment')
attachment = self.attachment_model.browse(action['res_id'])
self.assertEquals(attachment.datas_fname[-4:], '.xml')
xml_file = attachment.datas.decode('base64')
self.assertEqual(attachment.datas_fname[-4:], '.xml')
xml_file = base64.b64decode(attachment.datas)
xml_root = etree.fromstring(xml_file)
# print "xml_file=", etree.tostring(xml_root, pretty_print=True)
namespaces = xml_root.nsmap
@@ -133,20 +152,20 @@ class TestSDD(AccountingTestCase):
namespaces.pop(None)
pay_method_xpath = xml_root.xpath(
'//p:PmtInf/p:PmtMtd', namespaces=namespaces)
self.assertEquals(pay_method_xpath[0].text, 'DD')
self.assertEqual(pay_method_xpath[0].text, 'DD')
sepa_xpath = xml_root.xpath(
'//p:PmtInf/p:PmtTpInf/p:SvcLvl/p:Cd', namespaces=namespaces)
self.assertEquals(sepa_xpath[0].text, 'SEPA')
self.assertEqual(sepa_xpath[0].text, 'SEPA')
debtor_acc_xpath = xml_root.xpath(
'//p:PmtInf/p:CdtrAcct/p:Id/p:IBAN', namespaces=namespaces)
self.assertEquals(
self.assertEqual(
debtor_acc_xpath[0].text,
self.payment_order.company_partner_bank_id.sanitized_acc_number)
self.payment_order.generated2uploaded()
self.assertEquals(self.payment_order.state, 'uploaded')
payment_order.company_partner_bank_id.sanitized_acc_number)
payment_order.generated2uploaded()
self.assertEqual(payment_order.state, 'uploaded')
for inv in [invoice1, invoice2]:
self.assertEquals(inv.state, 'paid')
self.assertEquals(self.env.ref(
self.assertEqual(inv.state, 'paid')
self.assertEqual(self.env.ref(
'account_banking_sepa_direct_debit.res_partner_2_mandate').
recurrent_sequence_type, 'recurring')
return

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
© 2013-2016 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
-->
<!--
Customize all mandate views (and actions) to fit SEPA mandate style

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2015-2017 Tecnativa
Copyright 2016 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). -->
<odoo>

View File

@@ -2,17 +2,23 @@
<odoo>
<record id="view_account_config_settings" model="ir.ui.view">
<field name="name">sepa_direct_debit.account_config_settings.form</field>
<field name="model">account.config.settings</field>
<field name="inherit_id" ref="account_banking_pain_base.view_account_config_settings"/>
<field name="arch" type="xml">
<group name="pain" position="inside">
<field name="sepa_creditor_identifier"
placeholder="Write the ICS of your company"/>
</group>
</field>
</record>
<record id="view_account_config_settings" model="ir.ui.view">
<field name="name">sepa_direct_debit.account_config_settings.form
</field>
<field name="model">res.config.settings</field>
<field name="inherit_id"
ref="account_banking_pain_base.view_account_config_settings"/>
<field name="arch" type="xml">
<xpath expr="//div[@id='pain']/div/div/div" position="inside">
<div class="row mt16">
<label for="sepa_creditor_identifier"
class="col-md-3 o_light_label"/>
<field name="sepa_creditor_identifier"
placeholder="Write the ICS of your company"/>
</div>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1 @@
__import__('pkg_resources').declare_namespace(__name__)

View File

@@ -0,0 +1 @@
__import__('pkg_resources').declare_namespace(__name__)

View File

@@ -0,0 +1 @@
../../../../account_banking_sepa_direct_debit

View File

@@ -0,0 +1,6 @@
import setuptools
setuptools.setup(
setup_requires=['setuptools-odoo'],
odoo_addon=True,
)