first commit
This commit is contained in:
504
modules/account_payment_sepa/tests/test_module.py
Normal file
504
modules/account_payment_sepa/tests/test_module.py
Normal file
@@ -0,0 +1,504 @@
|
||||
# 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 as dt
|
||||
import os
|
||||
from decimal import Decimal
|
||||
from io import BytesIO, open
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
from lxml import etree
|
||||
|
||||
from trytond.exceptions import UserError
|
||||
from trytond.modules.account.tests import create_chart
|
||||
from trytond.modules.account_payment_sepa.payment import CAMT054
|
||||
from trytond.modules.company.tests import (
|
||||
CompanyTestMixin, create_company, set_company)
|
||||
from trytond.modules.currency.tests import create_currency
|
||||
from trytond.modules.party.tests import PartyCheckReplaceMixin
|
||||
from trytond.pool import Pool
|
||||
from trytond.tests.test_tryton import ModuleTestCase, with_transaction
|
||||
from trytond.transaction import Transaction
|
||||
|
||||
|
||||
def setup_environment():
|
||||
pool = Pool()
|
||||
Address = pool.get('party.address')
|
||||
Party = pool.get('party.party')
|
||||
Bank = pool.get('bank')
|
||||
Identifier = pool.get('party.identifier')
|
||||
|
||||
currency = create_currency('EUR')
|
||||
company = create_company(currency=currency)
|
||||
sepa = Identifier(party=company.party, code='ES23ZZZ47690558N',
|
||||
type='eu_at_02')
|
||||
sepa.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', postal_code='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,
|
||||
'address': customer.addresses[0],
|
||||
'account_number': account.numbers[0],
|
||||
'identification': 'MANDATE',
|
||||
'type': 'recurrent',
|
||||
'sequence_type_rcur': False,
|
||||
'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']
|
||||
with set_company(company):
|
||||
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' if kind == 'payable' else 'submitted',
|
||||
'reference': 'PAYMENT',
|
||||
'date': Date.today(),
|
||||
}])
|
||||
|
||||
session_id, _, _ = ProcessPayment.create()
|
||||
process_payment = ProcessPayment(session_id)
|
||||
with Transaction().set_context(
|
||||
active_model=Payment.__name__, 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 = bytes(message.message)
|
||||
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(
|
||||
PartyCheckReplaceMixin, CompanyTestMixin, ModuleTestCase):
|
||||
'Test Account Payment SEPA module'
|
||||
module = 'account_payment_sepa'
|
||||
|
||||
@with_transaction()
|
||||
def test_pain001_001_03(self):
|
||||
'Test pain001.001.03 xsd validation'
|
||||
validate_file('pain.001.001.03', 'payable')
|
||||
|
||||
@with_transaction()
|
||||
def test_pain001_001_05(self):
|
||||
'Test pain001.001.05 xsd validation'
|
||||
validate_file('pain.001.001.05', 'payable')
|
||||
|
||||
@with_transaction()
|
||||
def test_pain001_003_03(self):
|
||||
'Test pain001.003.03 xsd validation'
|
||||
validate_file('pain.001.003.03', 'payable')
|
||||
|
||||
@with_transaction()
|
||||
def test_pain008_001_02(self):
|
||||
'Test pain008.001.02 xsd validation'
|
||||
validate_file('pain.008.001.02', 'receivable')
|
||||
|
||||
@with_transaction()
|
||||
def test_pain008_001_04(self):
|
||||
'Test pain008.001.04 xsd validation'
|
||||
validate_file('pain.008.001.04', 'receivable')
|
||||
|
||||
@with_transaction()
|
||||
def test_pain008_003_02(self):
|
||||
'Test pain008.003.02 xsd validation'
|
||||
validate_file('pain.008.003.02', 'receivable')
|
||||
|
||||
@with_transaction()
|
||||
def test_sepa_mandate_sequence(self):
|
||||
'Test SEPA mandate sequence'
|
||||
pool = Pool()
|
||||
Configuration = pool.get('account.configuration')
|
||||
Sequence = pool.get('ir.sequence')
|
||||
SequenceType = pool.get('ir.sequence.type')
|
||||
Party = pool.get('party.party')
|
||||
Mandate = pool.get('account.payment.sepa.mandate')
|
||||
|
||||
party = Party(name='Test')
|
||||
party.save()
|
||||
|
||||
company = create_company()
|
||||
with set_company(company):
|
||||
mandate = Mandate(party=party)
|
||||
mandate.save()
|
||||
self.assertFalse(mandate.identification)
|
||||
|
||||
sequence_type, = SequenceType.search([
|
||||
('name', '=', "SEPA Mandate"),
|
||||
], limit=1)
|
||||
sequence = Sequence(name="Test", sequence_type=sequence_type)
|
||||
sequence.save()
|
||||
config = Configuration(1)
|
||||
config.sepa_mandate_sequence = sequence
|
||||
config.save()
|
||||
|
||||
mandate = Mandate(party=party)
|
||||
mandate.save()
|
||||
self.assertTrue(mandate.identification)
|
||||
|
||||
@with_transaction()
|
||||
def test_identification_unique(self):
|
||||
'Test unique identification constraint'
|
||||
pool = Pool()
|
||||
Party = pool.get('party.party')
|
||||
Mandate = pool.get('account.payment.sepa.mandate')
|
||||
|
||||
same_id = '1'
|
||||
|
||||
party = Party(name='Test')
|
||||
party.save()
|
||||
|
||||
company = create_company()
|
||||
with set_company(company):
|
||||
mandate = Mandate(party=party, identification=same_id)
|
||||
mandate.save()
|
||||
|
||||
for i in range(2):
|
||||
mandate = Mandate(party=party)
|
||||
mandate.save()
|
||||
|
||||
mandate = Mandate(party=party, identification='')
|
||||
mandate.save()
|
||||
self.assertEqual(mandate.identification, None)
|
||||
|
||||
Mandate.write([mandate], {
|
||||
'identification': '',
|
||||
})
|
||||
self.assertEqual(mandate.identification, None)
|
||||
|
||||
self.assertRaises(UserError, Mandate.create, [{
|
||||
'party': party.id,
|
||||
'identification': same_id,
|
||||
}])
|
||||
|
||||
@with_transaction()
|
||||
def test_payment_sepa_bank_account_number(self):
|
||||
'Test Payment.sepa_bank_account_number'
|
||||
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')
|
||||
|
||||
company = create_company()
|
||||
with set_company(company):
|
||||
create_chart(company)
|
||||
account_number = AccountNumber()
|
||||
mandate = Mandate(account_number=account_number)
|
||||
payment = Payment(kind='receivable', sepa_mandate=mandate)
|
||||
|
||||
self.assertEqual(id(payment.sepa_bank_account_number),
|
||||
id(account_number))
|
||||
|
||||
other_account_number = AccountNumber(type='other')
|
||||
iban_account_number = AccountNumber(type='iban')
|
||||
bank_account = BankAccount(
|
||||
numbers=[other_account_number, iban_account_number])
|
||||
party = Party(
|
||||
bank_accounts_used=[bank_account])
|
||||
payment = Payment(
|
||||
kind='payable', party=party,
|
||||
sepa_payable_bank_account_number=None)
|
||||
|
||||
self.assertEqual(id(payment.sepa_bank_account_number),
|
||||
id(iban_account_number))
|
||||
|
||||
payment.sepa_payable_bank_account_number = iban_account_number
|
||||
party.bank_accounts_used = []
|
||||
self.assertEqual(
|
||||
payment.sepa_bank_account_number,
|
||||
iban_account_number)
|
||||
|
||||
@with_transaction()
|
||||
def test_payment_sequence_type(self):
|
||||
'Test payment sequence type'
|
||||
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']
|
||||
with set_company(company):
|
||||
company_account, customer_account = setup_accounts(
|
||||
bank, company, customer)
|
||||
mandate = setup_mandate(company, customer, customer_account)
|
||||
journal = setup_journal('pain.008.001.02', 'receivable',
|
||||
company, company_account)
|
||||
|
||||
self.assertFalse(mandate.has_payments)
|
||||
self.assertEqual(mandate.sequence_type, 'FRST')
|
||||
mandate.sequence_type_rcur = True
|
||||
self.assertEqual(mandate.sequence_type, 'RCUR')
|
||||
mandate.sequence_type_rcur = False
|
||||
|
||||
payment, = Payment.create([{
|
||||
'company': company,
|
||||
'party': customer,
|
||||
'journal': journal,
|
||||
'kind': 'receivable',
|
||||
'amount': Decimal('1000.0'),
|
||||
'state': 'submitted',
|
||||
'reference': 'PAYMENT',
|
||||
'date': Date.today(),
|
||||
}])
|
||||
|
||||
session_id, _, _ = ProcessPayment.create()
|
||||
process_payment = ProcessPayment(session_id)
|
||||
with Transaction().set_context(
|
||||
active_model=Payment.__name__, active_ids=[payment.id]):
|
||||
_, data = process_payment.do_process(None)
|
||||
|
||||
self.assertEqual(payment.sepa_mandate_sequence_type, 'FRST')
|
||||
self.assertTrue(payment.sepa_mandate.has_payments)
|
||||
|
||||
payments = Payment.create([{
|
||||
'company': company,
|
||||
'party': customer,
|
||||
'journal': journal,
|
||||
'kind': 'receivable',
|
||||
'amount': Decimal('2000.0'),
|
||||
'state': 'submitted',
|
||||
'reference': 'PAYMENT',
|
||||
'date': Date.today(),
|
||||
}, {
|
||||
'company': company,
|
||||
'party': customer,
|
||||
'journal': journal,
|
||||
'kind': 'receivable',
|
||||
'amount': Decimal('3000.0'),
|
||||
'state': 'submitted',
|
||||
'reference': 'PAYMENT',
|
||||
'date': Date.today(),
|
||||
},
|
||||
])
|
||||
|
||||
session_id, _, _ = ProcessPayment.create()
|
||||
process_payment = ProcessPayment(session_id)
|
||||
payment_ids = [p.id for p in payments]
|
||||
with Transaction().set_context(
|
||||
active_model=Payment.__name__, active_ids=payment_ids):
|
||||
_, data = process_payment.do_process(None)
|
||||
|
||||
for payment in payments:
|
||||
self.assertEqual(payment.sepa_mandate_sequence_type, 'RCUR')
|
||||
self.assertTrue(payment.sepa_info_id)
|
||||
self.assertIsNotNone(payment.group.sepa_id)
|
||||
|
||||
@with_transaction()
|
||||
def test_payment_sequence_type_ordered_date(self):
|
||||
"Test sequence type by ordered date"
|
||||
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']
|
||||
with set_company(company):
|
||||
company_account, customer_account = setup_accounts(
|
||||
bank, company, customer)
|
||||
mandate = setup_mandate(company, customer, customer_account)
|
||||
journal = setup_journal('pain.008.001.02', 'receivable',
|
||||
company, company_account)
|
||||
|
||||
self.assertEqual(mandate.sequence_type, 'FRST')
|
||||
|
||||
payments = Payment.create([{
|
||||
'company': company,
|
||||
'party': customer,
|
||||
'journal': journal,
|
||||
'kind': 'receivable',
|
||||
'amount': Decimal('1000.0'),
|
||||
'state': 'submitted',
|
||||
'reference': 'PAYMENT',
|
||||
'date': Date.today() + dt.timedelta(days=1),
|
||||
}, {
|
||||
'company': company,
|
||||
'party': customer,
|
||||
'journal': journal,
|
||||
'kind': 'receivable',
|
||||
'amount': Decimal('1500.0'),
|
||||
'state': 'submitted',
|
||||
'reference': 'PAYMENT',
|
||||
'date': Date.today(),
|
||||
}, {
|
||||
'company': company,
|
||||
'party': customer,
|
||||
'journal': journal,
|
||||
'kind': 'receivable',
|
||||
'amount': Decimal('2000.0'),
|
||||
'state': 'submitted',
|
||||
'reference': 'PAYMENT',
|
||||
'date': Date.today(),
|
||||
}])
|
||||
|
||||
session_id, _, _ = ProcessPayment.create()
|
||||
process_payment = ProcessPayment(session_id)
|
||||
payment_ids = [p.id for p in payments]
|
||||
with Transaction().set_context(
|
||||
active_model=Payment.__name__, active_ids=payment_ids):
|
||||
_, data = process_payment.do_process(None)
|
||||
self.assertEqual(
|
||||
[p.sepa_mandate_sequence_type for p in payments],
|
||||
['RCUR', 'FRST', 'RCUR'])
|
||||
|
||||
@with_transaction()
|
||||
def handle_camt054(self, flavor):
|
||||
'Handle camt.054'
|
||||
pool = Pool()
|
||||
Message = pool.get('account.payment.sepa.message')
|
||||
|
||||
message_file = os.path.join(os.path.dirname(__file__),
|
||||
'%s.xml' % flavor)
|
||||
with open(message_file, 'rb') as fp:
|
||||
message = fp.read()
|
||||
namespace = Message.get_namespace(message)
|
||||
self.assertEqual(namespace,
|
||||
'urn:iso:std:iso:20022:tech:xsd:%s' % flavor)
|
||||
|
||||
payment = Mock()
|
||||
Payment = Mock()
|
||||
Payment.search.return_value = [payment]
|
||||
|
||||
handler = CAMT054(BytesIO(message), Payment)
|
||||
|
||||
self.assertEqual(handler.msg_id, 'AAAASESS-FP-00001')
|
||||
Payment.search.assert_called_with([
|
||||
('sepa_end_to_end_id', '=', 'MUELL/FINP/RA12345'),
|
||||
('kind', '=', 'payable'),
|
||||
])
|
||||
Payment.succeed.assert_called_with([payment])
|
||||
|
||||
payment.reset_mock()
|
||||
Payment.reset_mock()
|
||||
with patch.object(CAMT054, 'is_returned') as is_returned:
|
||||
is_returned.return_value = True
|
||||
handler = CAMT054(BytesIO(message), Payment)
|
||||
|
||||
Payment.save.assert_called_with([payment])
|
||||
Payment.fail.assert_called_with([payment])
|
||||
|
||||
def test_camt054_001_01(self):
|
||||
'Test camt.054.001.01 handling'
|
||||
self.handle_camt054('camt.054.001.01')
|
||||
|
||||
def test_camt054_001_02(self):
|
||||
'Test camt.054.001.02 handling'
|
||||
self.handle_camt054('camt.054.001.02')
|
||||
|
||||
def test_camt054_001_03(self):
|
||||
'Test camt.054.001.03 handling'
|
||||
self.handle_camt054('camt.054.001.03')
|
||||
|
||||
def test_camt054_001_04(self):
|
||||
'Test camt.054.001.04 handling'
|
||||
self.handle_camt054('camt.054.001.04')
|
||||
|
||||
@with_transaction()
|
||||
def test_sepa_mandate_report(self):
|
||||
'Test sepa mandate report'
|
||||
pool = Pool()
|
||||
Report = pool.get('account.payment.sepa.mandate', type='report')
|
||||
|
||||
environment = setup_environment()
|
||||
company = environment['company']
|
||||
bank = environment['bank']
|
||||
customer = environment['customer']
|
||||
with set_company(company):
|
||||
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)
|
||||
|
||||
|
||||
del ModuleTestCase
|
||||
Reference in New Issue
Block a user