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.

118 lines
4.8 KiB

  1. from io import StringIO
  2. import csv
  3. import datetime
  4. import hashlib
  5. from odoo import models, _
  6. ACCOUNT = "Compte donneur d'ordre"
  7. CURRENCY = "Devise"
  8. DATE = "Date"
  9. AMOUNT = "Montant"
  10. COUNTERPART_NUMBER = "Compte contrepartie"
  11. COUNTERPART_NAME = "Contrepartie"
  12. COMMUNICATION = "Communication"
  13. TRANSACTION_TYPE = "Type d'opération"
  14. class CodaBankStatementImport(models.TransientModel):
  15. _inherit = 'account.bank.statement.import'
  16. _date_format = "%d/%m/%Y"
  17. _decimal_sep = "."
  18. _csv_delimiter = ";"
  19. _csv_quote = '"'
  20. _header = ['Date', 'Montant', 'Devise', 'Contrepartie', 'Compte contrepartie', "Type d'opération",
  21. 'Communication', "Compte donneur d'ordre"]
  22. def _generate_note_crelan(self, move):
  23. notes = []
  24. notes.append("%s: %s" % (_('Counter Party Name'), move[COUNTERPART_NAME]))
  25. notes.append("%s: %s" % (_('Counter Party Account'), move[COUNTERPART_NUMBER]))
  26. notes.append("%s: %s" % (_('Communication'), move[COMMUNICATION]))
  27. return '\n'.join(notes)
  28. def _get_move_value_crelan(self, move, sequence):
  29. move_data = {
  30. 'name': move[TRANSACTION_TYPE] + ": " + move[COMMUNICATION],
  31. 'note': self._generate_note_crelan(move),
  32. 'date': self._to_iso_date(move[DATE]),
  33. 'amount': float(move[AMOUNT]),
  34. 'account_number': move[COUNTERPART_NUMBER], # Ok
  35. 'partner_name': move[COUNTERPART_NAME], # Ok
  36. 'ref': move[DATE] + '-' + move[AMOUNT] + '-' + move[COUNTERPART_NUMBER] + '-' + move[COUNTERPART_NAME],
  37. 'sequence': sequence, # Ok
  38. 'unique_import_id': move[DATE] + '-' + move[AMOUNT] + '-' + move[COUNTERPART_NUMBER] + '-' +
  39. move[COUNTERPART_NAME] + '-' + hashlib.new('md5', move[COMMUNICATION].encode()).hexdigest()
  40. }
  41. return move_data
  42. def _get_statement_data_crelan(self, balance_start, balance_end, begin_date, end_date):
  43. statement_data = {
  44. 'name': _("Bank Statement from %s to %s") % (begin_date, end_date),
  45. 'date': self._to_iso_date(end_date),
  46. 'balance_start': balance_start, # Ok
  47. 'balance_end_real' : balance_end, # Ok
  48. 'transactions' : []
  49. }
  50. return statement_data
  51. def _get_acc_number_crelan(self, acc_number):
  52. # Check if we match the exact acc_number or the end of an acc number
  53. journal = self.env['account.journal'].search([('bank_acc_number', '=like', '%' + acc_number)])
  54. if not journal or len(journal) > 1: # If not found or ambiguious
  55. return acc_number
  56. return journal.bank_acc_number
  57. def _get_acc_balance_crelan(self, acc_number):
  58. if not self.init_balance == None:
  59. return self.init_balance
  60. journal = self.env['account.journal'].search([('bank_acc_number', '=like', '%' + acc_number)])
  61. currency = journal.currency_id or journal.company_id.currency_id
  62. if not journal or len(journal) > 1: # If not found or ambiguious
  63. self.init_balance = 0.0
  64. else:
  65. lang = self._context.get('lang', 'en_US')
  66. l = self.env['res.lang'].search([('code', '=', lang)])
  67. balance = journal.get_journal_dashboard_datas()['last_balance'][:-1]
  68. self.init_balance = float(balance.replace(currency.symbol, '').strip().replace(l.thousands_sep, '').replace(l.decimal_point, '.'))
  69. return self.init_balance
  70. def _to_iso_date(self, orig_date):
  71. date_obj = datetime.datetime.strptime(orig_date, self._date_format)
  72. return date_obj.strftime('%Y-%m-%d')
  73. def _parse_file(self, data_file):
  74. try:
  75. csv_file = StringIO(data_file.decode())
  76. data = csv.DictReader(csv_file, delimiter=self._csv_delimiter, quotechar=self._csv_quote)
  77. if not data.fieldnames == self._header:
  78. raise ValueError()
  79. except ValueError:
  80. return super(CodaBankStatementImport, self)._parse_file(data_file)
  81. currency_code = False
  82. account_number = False
  83. self.init_balance = None
  84. begin_date = False
  85. end_date = False
  86. transactions = []
  87. i = 1
  88. sum_transaction = 0
  89. for statement in data:
  90. begin_date = begin_date or statement[DATE]
  91. end_date = statement[DATE]
  92. account_number = statement[ACCOUNT]
  93. balance = self._get_acc_balance_crelan(account_number)
  94. currency_code = statement[CURRENCY]
  95. transactions.append(self._get_move_value_crelan(statement, i))
  96. sum_transaction += float(statement[AMOUNT])
  97. i += 1
  98. stmt = self._get_statement_data_crelan(balance, balance + sum_transaction, begin_date, end_date)
  99. stmt['transactions'] = transactions
  100. return currency_code, self._get_acc_number_crelan(account_number), [stmt]