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.

86 lines
3.8 KiB

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