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.

93 lines
3.8 KiB

6 years ago
6 years ago
  1. # Copyright 2015 Odoo S. A.
  2. # Copyright 2015 Laurent Mignon <laurent.mignon@acsone.eu>
  3. # Copyright 2015 Ronald Portier <rportier@therp.nl>
  4. # Copyright 2016-2017 Tecnativa - Pedro M. Baeza
  5. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
  6. import dateutil.parser
  7. from odoo.tools.translate import _
  8. from odoo import api, models
  9. from odoo.exceptions import UserError
  10. class AccountBankStatementImport(models.TransientModel):
  11. _inherit = "account.bank.statement.import"
  12. @api.model
  13. def _check_qif(self, data_file):
  14. return data_file.strip().startswith(b'!Type:')
  15. def _parse_file(self, data_file):
  16. if not self._check_qif(data_file):
  17. return super(AccountBankStatementImport, self)._parse_file(
  18. data_file)
  19. try:
  20. file_data = data_file.decode()
  21. if '\r' in file_data:
  22. data_list = file_data.split('\r')
  23. else:
  24. data_list = file_data.split('\n')
  25. header = data_list[0].strip()
  26. header = header.split(":")[1]
  27. except:
  28. raise UserError(_('Could not decipher the QIF file.'))
  29. transactions = []
  30. vals_line = {}
  31. total = 0
  32. if header in ("Bank", "CCard"):
  33. vals_bank_statement = {}
  34. for line in data_list:
  35. line = line.strip()
  36. if not line:
  37. continue
  38. if line[0] == 'D': # date of transaction
  39. vals_line['date'] = dateutil.parser.parse(
  40. line[1:], fuzzy=True).date()
  41. elif line[0] == 'T': # Total amount
  42. total += float(line[1:].replace(',', ''))
  43. vals_line['amount'] = float(line[1:].replace(',', ''))
  44. elif line[0] == 'N': # Check number
  45. vals_line['ref'] = line[1:]
  46. elif line[0] == 'P': # Payee
  47. vals_line['name'] = (
  48. 'name' in vals_line and
  49. line[1:] + ': ' + vals_line['name'] or line[1:]
  50. )
  51. elif line[0] == 'M': # Memo
  52. vals_line['name'] = ('name' in vals_line and
  53. vals_line['name'] + ': ' + line[1:] or
  54. line[1:])
  55. elif line[0] == '^' and vals_line: # end of item
  56. transactions.append(vals_line)
  57. vals_line = {}
  58. elif line[0] == '\n':
  59. transactions = []
  60. else:
  61. pass
  62. else:
  63. raise UserError(_('This file is either not a bank statement or is '
  64. 'not correctly formed.'))
  65. vals_bank_statement.update({
  66. 'balance_end_real': total,
  67. 'transactions': transactions
  68. })
  69. return None, None, [vals_bank_statement]
  70. def _complete_stmts_vals(self, stmt_vals, journal_id, account_number):
  71. """Match partner_id if hasn't been deducted yet."""
  72. res = super(AccountBankStatementImport, self)._complete_stmts_vals(
  73. stmt_vals, journal_id, account_number,
  74. )
  75. # Since QIF doesn't provide account numbers (normal behaviour is to
  76. # provide 'account_number', which the generic module uses to find
  77. # the partner), we have to find res.partner through the name
  78. partner_obj = self.env['res.partner']
  79. for statement in res:
  80. for line_vals in statement['transactions']:
  81. if not line_vals.get('partner_id') and line_vals.get('name'):
  82. partner = partner_obj.search(
  83. [('name', 'ilike', line_vals['name'])], limit=1,
  84. )
  85. line_vals['partner_id'] = partner.id
  86. return res