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.

94 lines
3.3 KiB

  1. # -*- coding: utf-8 -*-
  2. import logging
  3. import StringIO
  4. from odoo import api, models, fields, _
  5. from odoo.exceptions import UserError
  6. from odoo.tools import float_is_zero
  7. _logger = logging.getLogger(__name__)
  8. try:
  9. from ofxparse import OfxParser
  10. except ImportError:
  11. _logger.debug("ofxparse not found.")
  12. OfxParser = None
  13. class AccountBankStatementImport(models.TransientModel):
  14. _inherit = 'account.bank.statement.import'
  15. @api.model
  16. def _check_ofx(self, data_file):
  17. if not OfxParser:
  18. return False
  19. try:
  20. ofx = OfxParser.parse(StringIO.StringIO(data_file))
  21. except Exception as e:
  22. _logger.debug(e)
  23. return False
  24. return ofx
  25. @api.model
  26. def _prepare_ofx_transaction_line(self, transaction):
  27. # since odoo 9, the account module defines a constraint
  28. # on account.bank.statement.line: 'amount' must be != 0
  29. # But some banks have some transactions with amount=0
  30. # for bank charges that are offered, which blocks the import
  31. precision = self.env['decimal.precision'].precision_get('Account')
  32. if float_is_zero(
  33. float(transaction.amount), precision_digits=precision):
  34. return False
  35. # Since ofxparse doesn't provide account numbers,
  36. # we cannot provide the key 'bank_account_id',
  37. # nor the key 'account_number'
  38. # If you read odoo10/addons/account_bank_statement_import/
  39. # account_bank_statement_import.py, it's the only 2 keys
  40. # we can provide to match a partner.
  41. vals = {
  42. 'date': transaction.date,
  43. 'name': transaction.payee + (
  44. transaction.memo and ': ' + transaction.memo or ''),
  45. 'ref': transaction.id,
  46. 'amount': float(transaction.amount),
  47. 'unique_import_id': transaction.id,
  48. }
  49. return vals
  50. @api.model
  51. def _parse_file(self, data_file):
  52. ofx = self._check_ofx(data_file)
  53. if not ofx:
  54. return super(AccountBankStatementImport, self)._parse_file(
  55. data_file)
  56. transactions = []
  57. total_amt = 0.00
  58. start_date = end_date = False
  59. try:
  60. for transaction in ofx.account.statement.transactions:
  61. vals = self._prepare_ofx_transaction_line(transaction)
  62. if vals:
  63. transactions.append(vals)
  64. total_amt += vals['amount']
  65. tdate = fields.Date.to_string(vals['date'])
  66. if not start_date or tdate < start_date:
  67. start_date = tdate
  68. if not end_date or tdate > end_date:
  69. end_date = tdate
  70. except Exception, e:
  71. raise UserError(_(
  72. "The following problem occurred during import. "
  73. "The file might not be valid.\n\n %s") % e.message)
  74. vals_bank_statement = {
  75. 'name': _('Account %s %s > %s') % (
  76. ofx.account.number, start_date, end_date),
  77. 'transactions': transactions,
  78. 'balance_start': ofx.account.statement.balance,
  79. 'balance_end_real':
  80. float(ofx.account.statement.balance) + total_amt,
  81. }
  82. return ofx.account.statement.currency, ofx.account.number, [
  83. vals_bank_statement]