You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

90 lines
3.9 KiB

  1. # -*- coding: utf-8 -*-
  2. """Implement parser for MT940 files - Rabobank dialect."""
  3. ##############################################################################
  4. #
  5. # OpenERP, Open Source Management Solution
  6. # Copyright (C) 2015 Therp BV <http://therp.nl>.
  7. #
  8. # This program is free software: you can redistribute it and/or modify
  9. # it under the terms of the GNU Affero General Public License as
  10. # published by the Free Software Foundation, either version 3 of the
  11. # License, or (at your option) any later version.
  12. #
  13. # This program is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. # GNU Affero General Public License for more details.
  17. #
  18. # You should have received a copy of the GNU Affero General Public License
  19. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. #
  21. ##############################################################################
  22. import re
  23. from string import printable
  24. from datetime import datetime
  25. from openerp.addons.bank_statement_parse_mt940.mt940 import (
  26. MT940, str2amount, get_subfields, handle_common_subfields)
  27. class MT940Parser(MT940):
  28. """Implement parser for MT940 files - Rabobank dialect."""
  29. tag_61_regex = re.compile(
  30. r'^(?P<date>\d{6})(?P<sign>[CD])(?P<amount>\d+,\d{2})N(?P<type>.{3})'
  31. r'(?P<reference>MARF|EREF|PREF|NONREF)\s*'
  32. r'\n?(?P<remote_account>\w{1,16})?'
  33. )
  34. def __init__(self):
  35. """Initialize parser - override at least header_regex."""
  36. super(MT940Parser, self).__init__()
  37. self.header_lines = 1 # Number of lines to skip
  38. # Do not user $ for end of string below: line contains much
  39. # more data than just the first line.
  40. self.header_regex = '^:940:' # Start of relevant data
  41. def parse(self, data):
  42. """Filter Unprintable characters from file data.
  43. The file contents of the Rabobank tend to contain unprintable
  44. characters that prevent proper parsing. These will be removed.
  45. """
  46. data = ''.join([x for x in data if x in printable])
  47. return super(MT940Parser, self).parse(data)
  48. def handle_tag_61(self, data):
  49. """Handle tag 61: transaction data."""
  50. super(MT940Parser, self).handle_tag_61(data)
  51. parsed_data = self.tag_61_regex.match(data).groupdict()
  52. self.current_transaction.transferred_amount = (
  53. str2amount(parsed_data['sign'], parsed_data['amount']))
  54. self.current_transaction.reference = parsed_data['reference']
  55. if parsed_data['remote_account']:
  56. self.current_transaction.remote_account = (
  57. parsed_data['remote_account'])
  58. def handle_tag_86(self, data):
  59. """Handle tag 86: transaction details"""
  60. if not self.current_transaction:
  61. return
  62. codewords = ['RTRN', 'BENM', 'ORDP', 'CSID', 'BUSP', 'MARF', 'EREF',
  63. 'PREF', 'REMI', 'ID', 'PURP', 'ULTB', 'ULTD',
  64. 'CREF', 'IREF', 'NAME', 'ADDR', 'ULTC', 'EXCH', 'CHGS']
  65. subfields = get_subfields(data, codewords)
  66. transaction = self.current_transaction
  67. # If we have no subfields, set message to whole of data passed:
  68. if not subfields:
  69. transaction.message = data
  70. else:
  71. handle_common_subfields(transaction, subfields)
  72. # Use subfields for transaction details:
  73. if 'NAME' in subfields:
  74. transaction.remote_owner = ' '.join(subfields['NAME'])
  75. if 'ADDR' in subfields:
  76. # Do NOT join address fields, array is expected on other code!
  77. transaction.remote_owner_address = subfields['ADDR']
  78. # Prevent handling tag 86 later for non transaction details:
  79. self.current_transaction = None
  80. # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: