Browse Source

[ENH] Improve determination of start and end balance for camt.

pull/153/head
Ronald Portier 8 years ago
parent
commit
49a7b8408b
  1. 102
      account_bank_statement_import_camt/models/parser.py

102
account_bank_statement_import_camt/models/parser.py

@ -2,8 +2,9 @@
"""Class to parse camt files."""
##############################################################################
#
# Copyright (C) 2013-2015 Therp BV <http://therp.nl>
# Copyright (C) 2013-2018 Therp BV <http://therp.nl>
# Copyright 2017 Open Net Sàrl
# (C) 2015 1200wd.com
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published
@ -19,14 +20,13 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import logging
import re
from copy import copy
from datetime import datetime
from lxml import etree
from openerp import _
from openerp.addons.account_bank_statement_import.parserlib import (
BankStatement)
@ -195,38 +195,53 @@ class CamtParser(models.AbstractModel):
transaction['data'] = etree.tostring(data)
yield transaction
def get_balance_amounts(self, ns, node):
"""Return opening and closing balance.
def get_balance_type_node(self, node, balance_type):
"""
:param node: BkToCstmrStmt/Stmt/Bal node
:param balance type: one of 'OPBD', 'PRCD', 'ITBD', 'CLBD'
"""
code_expr = (
'./ns:Bal/ns:Tp/ns:CdOrPrtry/ns:Cd[text()="%s"]/../../..' %
balance_type
)
return self.xpath(node, code_expr)
Depending on kind of balance and statement, the balance might be in a
different kind of node:
OPBD = OpeningBalance
PRCD = PreviousClosingBalance
ITBD = InterimBalance (first ITBD is start-, second is end-balance)
CLBD = ClosingBalance
def get_start_balance(self, node):
"""
start_balance_node = None
end_balance_node = None
for node_name in ['OPBD', 'PRCD', 'CLBD', 'ITBD']:
code_expr = (
'./ns:Bal/ns:Tp/ns:CdOrPrtry/ns:Cd[text()="%s"]/../../..' %
node_name
)
balance_node = node.xpath(code_expr, namespaces={'ns': ns})
if balance_node:
if node_name in ['OPBD', 'PRCD']:
start_balance_node = balance_node[0]
elif node_name == 'CLBD':
end_balance_node = balance_node[0]
else:
if not start_balance_node:
start_balance_node = balance_node[0]
if not end_balance_node:
end_balance_node = balance_node[-1]
return (
self.parse_amount(ns, start_balance_node),
self.parse_amount(ns, end_balance_node)
Find the (only) balance node with code OpeningBalance, or
the only one with code 'PreviousClosingBalance'
or the first balance node with code InterimBalance in
the case of preceeding pagination.
:param node: BkToCstmrStmt/Stmt/Bal node
"""
balance = 0
nodes = (
self.get_balance_type_node(node, 'OPBD') or
self.get_balance_type_node(node, 'PRCD') or
self.get_balance_type_node(node, 'ITBD')
)
if nodes:
balance = self.parse_amount(nodes[0])
return balance
def get_end_balance(self, node):
"""
Find the (only) balance node with code ClosingBalance, or
the second (and last) balance node with code InterimBalance in
the case of continued pagination.
:param node: BkToCstmrStmt/Stmt/Bal node
"""
balance = 0
nodes = (
self.get_balance_type_node(node, 'CLAV') or
self.get_balance_type_node(node, 'CLBD') or
self.get_balance_type_node(node, 'ITBD')
)
if nodes:
balance = self.parse_amount(nodes[-1])
return balance
def parse_statement(self, ns, node):
"""Parse a single Stmt node."""
@ -241,14 +256,14 @@ class CamtParser(models.AbstractModel):
ns, node, './ns:Id', statement, 'statement_id')
self.add_value_from_node(
ns, node, './ns:Acct/ns:Ccy', statement, 'local_currency')
(statement.start_balance, statement.end_balance) = (
self.get_balance_amounts(ns, node))
entry_nodes = node.xpath('./ns:Ntry', namespaces={'ns': ns})
transactions = []
for entry_node in entry_nodes:
statement.start_balance = self.get_start_balance(node)
statement.end_balance = self.get_end_balance(node)
transaction_nodes = node.xpath('./ns:Ntry', namespaces={'ns': ns})
total_amount = 0
for entry_node in transaction_nodes:
transaction = statement.create_transaction()
transactions.extend(self.parse_entry(ns, entry_node, transaction))
statement['transactions'] = transactions
total_amount += transaction['transferred_amount']
self.parse_transaction(ns, entry_node, transaction)
if statement['transactions']:
execution_date = statement['transactions'][0].execution_date[:10]
statement.date = datetime.strptime(execution_date, "%Y-%m-%d")
@ -256,6 +271,15 @@ class CamtParser(models.AbstractModel):
if execution_date not in statement.statement_id:
statement.statement_id = "%s-%s" % (
execution_date, statement.statement_id)
if statement.start_balance == 0 and statement.end_balance != 0:
statement.start_balance = statement.end_balance - total_amount
_logger.debug(
_("Start balance %s calculated from end balance %s and"
" Total amount %s."),
statement.start_balance,
statement.end_balance,
total_amount
)
return statement
def check_version(self, ns, root):

Loading…
Cancel
Save