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.

228 lines
9.9 KiB

  1. # -*- coding: utf-8 -*-
  2. # © 2017 Akretion France (Alexis de Lattre <alexis.delattre@akretion.com>)
  3. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
  4. from odoo.addons.report_xlsx.report.report_xlsx import ReportXlsx
  5. from odoo import fields, _
  6. from odoo.tools import DEFAULT_SERVER_DATE_FORMAT
  7. from datetime import datetime
  8. class BankReconciliationXlsx(ReportXlsx):
  9. def generate_xlsx_report(self, workbook, data, wizard):
  10. date = wizard.date
  11. date_dt = fields.Date.from_string(date)
  12. no_bank_journal = True
  13. for o in wizard.journal_ids:
  14. no_bank_journal = False
  15. # Start styles
  16. lang_code = self.env.user.lang
  17. lang = False
  18. if lang_code:
  19. lang = self.env['res.lang'].search([('code', '=', lang_code)])
  20. if not lang:
  21. lang = self.env['res.lang'].search([], limit=1)
  22. xls_date_format = lang.date_format.replace('%Y', 'yyyy').\
  23. replace('%m', 'mm').replace('%d', 'dd').replace('%y', 'yy')
  24. doc_title = workbook.add_format({'bold': True, 'font_size': 16})
  25. col_title = workbook.add_format({
  26. 'bold': True, 'bg_color': '#e2e2fa',
  27. 'text_wrap': True, 'font_size': 10,
  28. })
  29. title_right = workbook.add_format({
  30. 'bold': True, 'bg_color': '#e6e6fa',
  31. 'font_size': 10, 'align': 'right',
  32. })
  33. title_date = workbook.add_format({
  34. 'bg_color': '#f6f6ff', 'bold': True,
  35. 'num_format': xls_date_format,
  36. 'font_size': 10,
  37. 'align': 'left'})
  38. label_bold = workbook.add_format({
  39. 'bold': True, 'text_wrap': False, 'font_size': 10})
  40. none = workbook.add_format({
  41. 'bold': True, 'font_size': 10, 'align': 'right'})
  42. regular = workbook.add_format({'font_size': 10})
  43. if '%' in xls_date_format:
  44. # fallback
  45. xls_date_format = 'yyyy-mm-dd'
  46. regular_date = workbook.add_format({
  47. 'num_format': xls_date_format,
  48. 'font_size': 10,
  49. 'align': 'left'})
  50. cur_format = u'#,##0.00 %s' % (
  51. o.company_id.currency_id.symbol or
  52. o.company_id.currency_id.name)
  53. # It seems that Excel replaces automatically the decimal
  54. # and thousand separator by those of the language under which
  55. # Excel runs
  56. regular_currency = workbook.add_format(
  57. {'num_format': cur_format, 'font_size': 10})
  58. regular_currency_bg = workbook.add_format({
  59. 'num_format': cur_format, 'font_size': 10,
  60. 'bg_color': '#f6f6ff'})
  61. # End styles
  62. sheet = workbook.add_worksheet(o.code or o.name)
  63. sheet.write(
  64. 0, 0,
  65. _('%s - %s - Bank Reconciliation') % (
  66. o.company_id.name, o.display_name),
  67. doc_title)
  68. sheet.set_row(0, 26)
  69. sheet.set_row(1, 25)
  70. sheet.set_column(0, 0, 10)
  71. sheet.set_column(1, 1, 40)
  72. sheet.set_column(2, 2, 15)
  73. sheet.set_column(3, 3, 25)
  74. sheet.set_column(4, 4, 12)
  75. sheet.set_column(5, 5, 18)
  76. sheet.set_column(6, 6, 14)
  77. sheet.set_column(7, 7, 14)
  78. row = 2
  79. sheet.write(row, 0, _("Date:"), title_right)
  80. sheet.write(row, 1, date_dt, title_date)
  81. # 1) Show accounting balance of bank account
  82. row += 2
  83. bank_account = o.default_debit_account_id
  84. for col in range(3):
  85. sheet.write(row, col, '', title_right)
  86. sheet.write(
  87. row, 3,
  88. _('Balance %s:') % bank_account.code, title_right)
  89. amount_field = 'balance'
  90. # TODO: add support for bank accounts in foreign currency
  91. # if not o.currency_id else 'amount_currency'
  92. query = """
  93. SELECT sum(%s) FROM account_move_line
  94. WHERE account_id=%%s AND date <= %%s""" % (amount_field, )
  95. self.env.cr.execute(query, (bank_account.id, date))
  96. query_results = self.env.cr.dictfetchall()
  97. if query_results:
  98. account_bal = query_results[0].get('sum') or 0.0
  99. else:
  100. account_bal = 0.0
  101. sheet.write(row, 4, account_bal, regular_currency_bg)
  102. bank_bal = account_bal
  103. formula = '=E%d' % (row + 1)
  104. # 2) Show account move line that are not linked to bank statement
  105. # line or linked to a statement line after the date
  106. row += 2
  107. sheet.write(
  108. row, 0, _(
  109. 'Journal items of account %s not linked to a bank '
  110. 'statement line:') % bank_account.code,
  111. label_bold)
  112. mlines = self.env['account.move.line'].search([
  113. ('account_id', '=', bank_account.id),
  114. ('journal_id', '=', o.id), # to avoid initial line
  115. ('date', '<=', date),
  116. '|', ('statement_line_date', '=', False),
  117. ('statement_line_date', '>', date)])
  118. if not mlines:
  119. sheet.write(row, 4, _('NONE'), none)
  120. else:
  121. row += 1
  122. col_labels = [
  123. _('Date'), _('Label'), _('Ref.'), _('Partner'),
  124. _('Amount'), _('Statement Line Date'), _('Move Number'),
  125. _('Counter-part')]
  126. col = 0
  127. for col_label in col_labels:
  128. sheet.write(row, col, col_label, col_title)
  129. col += 1
  130. m_start_row = m_end_row = row + 1
  131. for mline in mlines:
  132. row += 1
  133. m_end_row = row
  134. move = mline.move_id
  135. bank_bal -= mline.balance
  136. date_dt = fields.Date.from_string(mline.date)
  137. sheet.write(row, 0, date_dt, regular_date)
  138. sheet.write(row, 1, mline.name, regular)
  139. sheet.write(row, 2, mline.ref or '', regular)
  140. sheet.write(
  141. row, 3, mline.partner_id.display_name or '', regular)
  142. sheet.write(row, 4, mline.balance, regular_currency)
  143. if mline.statement_line_date:
  144. stl_date_dt = fields.Date.from_string(
  145. mline.statement_line_date)
  146. else:
  147. stl_date_dt = ''
  148. sheet.write(row, 5, stl_date_dt, regular_date)
  149. sheet.write(row, 6, move.name, regular)
  150. # counter-part accounts
  151. cpart = []
  152. for line in move.line_ids:
  153. if (
  154. line.account_id != bank_account and
  155. line.account_id.code not in cpart):
  156. cpart.append(line.account_id.code)
  157. sheet.write(row, 7, ' ,'.join(cpart), regular)
  158. formula += '-SUM(E%d:E%d)' % (m_start_row + 1, m_end_row + 1)
  159. # 3) Add draft bank statement lines
  160. row += 2 # skip 1 line
  161. sheet.write(
  162. row, 0, _(
  163. 'Draft bank statement lines:'),
  164. label_bold)
  165. blines = self.env['account.bank.statement.line'].search([
  166. ('journal_entry_ids', '=', False),
  167. ('journal_id', '=', o.id),
  168. ('date', '<=', date)])
  169. if not blines:
  170. sheet.write(row, 4, _('NONE'), none)
  171. else:
  172. row += 1
  173. col_labels = [
  174. _('Date'), _('Label'), _('Ref.'),
  175. _('Partner'), _('Amount'), _('Statement Ref.'), '', '']
  176. col = 0
  177. for col_label in col_labels:
  178. sheet.write(row, col, col_label, col_title)
  179. col += 1
  180. b_start_row = b_end_row = row + 1
  181. for bline in blines:
  182. row += 1
  183. b_end_row = row
  184. bank_bal += bline.amount
  185. date_dt = datetime.strptime(
  186. bline.date, DEFAULT_SERVER_DATE_FORMAT)
  187. sheet.write(row, 0, date_dt, regular_date)
  188. sheet.write(row, 1, bline.name, regular)
  189. sheet.write(row, 2, bline.ref or '', regular)
  190. sheet.write(
  191. row, 3, bline.partner_id.display_name or '', regular)
  192. sheet.write(row, 4, bline.amount, regular_currency)
  193. sheet.write(
  194. row, 5, bline.statement_id.display_name or '',
  195. regular_currency)
  196. formula += '+SUM(E%d:E%d)' % (b_start_row + 1, b_end_row + 1)
  197. # 4) Theoric bank account balance at the bank
  198. row += 2
  199. for col in range(3):
  200. sheet.write(row, col, '', title_right)
  201. sheet.write(
  202. row, 3, _('Computed Bank Account Balance at the Bank:'),
  203. title_right)
  204. sheet.write_formula(
  205. row, 4, formula, regular_currency_bg, bank_bal)
  206. if no_bank_journal:
  207. sheet = workbook.add_worksheet(_('No Bank Journal'))
  208. sheet.set_row(0, 30)
  209. warn_msg = workbook.add_format(
  210. {'bold': True, 'font_size': 16, 'font_color': '#003b6f'})
  211. sheet.write(
  212. 0, 0, _(
  213. "No bank journal selected. "
  214. "This report is only for bank journals."), warn_msg)
  215. BankReconciliationXlsx(
  216. 'report.bank.reconciliation.xlsx', 'bank.reconciliation.report.wizard')