mirror of
https://github.com/OCA/bank-payment.git
synced 2025-02-02 10:37:31 +02:00
[FIX] Remove unused imports
[FIX] Translation is not available (no context) [FIX] Assign statement date [FIX] Effective vs. execution date confusion [FIX] Remove debug statements [FIX] Don't say 'TxDtl' when processing TxDtls node [FIX] Xpath of address line [ADD] Some docstrings
This commit is contained in:
@@ -3,8 +3,6 @@ from datetime import datetime
|
||||
import re
|
||||
from account_banking.parsers import models
|
||||
from account_banking.parsers.convert import str2date
|
||||
from account_banking.sepa import postalcode
|
||||
from tools.translate import _
|
||||
|
||||
bt = models.mem_bank_transaction
|
||||
|
||||
@@ -15,13 +13,16 @@ class transaction(models.mem_bank_transaction):
|
||||
for attr in values:
|
||||
setattr(self, attr, values[attr])
|
||||
|
||||
def is_valid(self):
|
||||
return not self.error_message
|
||||
|
||||
class parser(models.parser):
|
||||
code = 'CAMT'
|
||||
country_code = 'NL'
|
||||
name = _('Generic CAMT Format')
|
||||
doc = _('''\
|
||||
name = 'Generic CAMT Format'
|
||||
doc = '''\
|
||||
CAMT Format parser
|
||||
''')
|
||||
'''
|
||||
|
||||
def tag(self, node):
|
||||
"""
|
||||
@@ -34,9 +35,9 @@ CAMT Format parser
|
||||
Get node's stripped tag and compare with expected
|
||||
"""
|
||||
assert self.tag(node) == expected, (
|
||||
_("Expected tag '%s', got '%s' instead") %
|
||||
"Expected tag '%s', got '%s' instead" %
|
||||
(self.tag(node), expected))
|
||||
|
||||
|
||||
def xpath(self, node, expr):
|
||||
"""
|
||||
Wrap namespaces argument into call to Element.xpath():
|
||||
@@ -103,6 +104,9 @@ CAMT Format parser
|
||||
return self.parse_amount(nodes[-1])
|
||||
|
||||
def parse_Stmt(self, node):
|
||||
"""
|
||||
Parse a single Stmt node
|
||||
"""
|
||||
statement = models.mem_bank_statement()
|
||||
statement.id = node.find(self.ns + 'Id').text
|
||||
statement.local_account = (
|
||||
@@ -112,9 +116,15 @@ CAMT Format parser
|
||||
statement.local_currency = self.xpath(node, './ns:Acct/ns:Ccy')[0].text
|
||||
statement.start_balance = self.get_start_balance(node)
|
||||
statement.end_balance = self.get_end_balance(node)
|
||||
print "Number of Ntry in statement: %s" % len(self.xpath(node, './ns:Ntry'))
|
||||
number = 0
|
||||
for Ntry in self.xpath(node, './ns:Ntry'):
|
||||
for transaction_detail in self.parse_Ntry(Ntry):
|
||||
if number == 0:
|
||||
# Take the statement date from the first transaction
|
||||
statement.date = str2date(
|
||||
transaction_detail['execution_date'], "%Y-%m-%d")
|
||||
number += 1
|
||||
transaction_detail['id'] = str(number).zfill(4)
|
||||
statement.transactions.append(
|
||||
transaction(transaction_detail))
|
||||
return statement
|
||||
@@ -129,41 +139,40 @@ CAMT Format parser
|
||||
return False
|
||||
|
||||
def parse_Ntry(self, node):
|
||||
"""
|
||||
:param node: Ntry node
|
||||
"""
|
||||
entry_description = self.get_entry_description(node)
|
||||
entry_details = {
|
||||
'effective_date': self.xpath(node, './ns:BookgDt/ns:Dt')[0].text,
|
||||
'transaction_date': self.xpath(node, './ns:ValDt/ns:Dt')[0].text,
|
||||
'execution_date': self.xpath(node, './ns:BookgDt/ns:Dt')[0].text,
|
||||
'effective_date': self.xpath(node, './ns:ValDt/ns:Dt')[0].text,
|
||||
'transfer_type': bt.ORDER,
|
||||
'transferred_amount': self.parse_amount(node)
|
||||
}
|
||||
amount_sign = -1 if node.find(self.ns + 'CdtDbtInd').text == 'CRDT' else 1
|
||||
transaction_details = []
|
||||
print " NUmber of NtryDtls in Ntry with code %s: %s" % (
|
||||
entry_description, len(self.xpath(node, './ns:NtryDtls')))
|
||||
for NtryDtl in self.xpath(node, './ns:NtryDtls'):
|
||||
TxDtls = self.xpath(NtryDtl, './ns:TxDtls')
|
||||
# Todo: process Btch tag on entry-detail level
|
||||
print " NUmber of TxDtls in NtryDtl: %s" % len(TxDtls)
|
||||
if len(TxDtls) == 1:
|
||||
vals = self.parse_TxDtl(TxDtls[0], entry_details, amount_sign)
|
||||
vals = self.parse_TxDtls(TxDtls[0], entry_details, amount_sign)
|
||||
else:
|
||||
vals = entry_details
|
||||
print vals
|
||||
transaction_details.append(transaction(vals))
|
||||
transaction_details.append(vals)
|
||||
return transaction_details
|
||||
|
||||
def get_party_values(self, TxDtl):
|
||||
def get_party_values(self, TxDtls):
|
||||
"""
|
||||
Determine to get either the debtor or creditor party node
|
||||
and extract the available data from it
|
||||
"""
|
||||
vals = {}
|
||||
party_type = self.find(
|
||||
TxDtl, '../../ns:CdtDbtInd').text == 'CRDT' and 'Dbtr' or 'Cdtr'
|
||||
party_node = self.find(TxDtl, './ns:RltdPties/ns:%s' % party_type)
|
||||
account_node = self.find(TxDtl, './ns:RltdPties/ns:%sAcct/ns:Id' % party_type)
|
||||
TxDtls, '../../ns:CdtDbtInd').text == 'CRDT' and 'Dbtr' or 'Cdtr'
|
||||
party_node = self.find(TxDtls, './ns:RltdPties/ns:%s' % party_type)
|
||||
account_node = self.find(TxDtls, './ns:RltdPties/ns:%sAcct/ns:Id' % party_type)
|
||||
bic_node = self.find(
|
||||
TxDtl,
|
||||
TxDtls,
|
||||
'./ns:RltdAgts/ns:%sAgt/ns:FinInstnId/ns:BIC' % party_type)
|
||||
if party_node is not None:
|
||||
name_node = self.find(party_node, './ns:Nm')
|
||||
@@ -171,7 +180,7 @@ CAMT Format parser
|
||||
country_node = self.find(party_node, './ns:PstlAdr/ns:Ctry')
|
||||
vals['remote_owner_country'] = (
|
||||
country_node.text if country_node is not None else False)
|
||||
address_node = self.find(party_node, './ns:AdrLine')
|
||||
address_node = self.find(party_node, './ns:PstlAdr/ns:AdrLine')
|
||||
vals['remote_owner_address'] = (
|
||||
address_node.text if address_node is not None else False)
|
||||
if account_node is not None:
|
||||
@@ -186,22 +195,28 @@ CAMT Format parser
|
||||
domestic_node.text if domestic_node is not None else False)
|
||||
return vals
|
||||
|
||||
def parse_TxDtl(self, TxDtl, entry_values, amount_sign):
|
||||
def parse_TxDtls(self, TxDtls, entry_values, amount_sign):
|
||||
"""
|
||||
Parse a single TxDtls node
|
||||
"""
|
||||
vals = dict(entry_values)
|
||||
# amount = amount_sign * float(node.find(self.ns + 'Amt').text)
|
||||
unstructured = self.xpath(TxDtl, './ns:RmtInf/ns:Ustrd')
|
||||
unstructured = self.xpath(TxDtls, './ns:RmtInf/ns:Ustrd')
|
||||
if unstructured:
|
||||
vals['message'] = ' '.join([x.text for x in unstructured])
|
||||
structured = self.find(TxDtl, './ns:RmtInf/ns:Strd/ns:CdtrRefInf/ns:Ref')
|
||||
structured = self.find(TxDtls, './ns:RmtInf/ns:Strd/ns:CdtrRefInf/ns:Ref')
|
||||
if structured is not None:
|
||||
vals['reference'] = structured.text
|
||||
else:
|
||||
if vals['message'] and re.match('^[^\s]$', vals['message']):
|
||||
if vals['message'] and re.match('^[^\s]+$', vals['message']):
|
||||
vals['reference'] = vals['message']
|
||||
vals.update(self.get_party_values(TxDtl))
|
||||
vals.update(self.get_party_values(TxDtls))
|
||||
return vals
|
||||
|
||||
def parse(self, cr, data):
|
||||
"""
|
||||
Parse a CAMT053 XML file
|
||||
"""
|
||||
root = etree.fromstring(data)
|
||||
self.ns = root.tag[:root.tag.index("}") + 1]
|
||||
self.assert_tag(root[0][0], 'GrpHdr')
|
||||
|
||||
Reference in New Issue
Block a user