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.

348 lines
16 KiB

11 years ago
11 years ago
  1. # -*- encoding: utf-8 -*-
  2. ##############################################################################
  3. #
  4. # OpenERP, Open Source Management Solution
  5. #
  6. # Copyright (c) 2013 Noviat nv/sa (www.noviat.com). All rights reserved.
  7. #
  8. # This program is free software: you can redistribute it and/or modify
  9. # it under the terms of the GNU Affero General Public License as
  10. # published by the Free Software Foundation, either version 3 of the
  11. # License, or (at your option) any later version.
  12. #
  13. # This program is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. # GNU Affero General Public License for more details.
  17. #
  18. # You should have received a copy of the GNU Affero General Public License
  19. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. #
  21. ##############################################################################
  22. import xlwt
  23. from datetime import datetime
  24. from openerp.addons.report_xls.report_xls import report_xls
  25. from openerp.addons.report_xls.utils import rowcol_to_cell
  26. from openerp.addons.account_financial_report_webkit.report.general_ledger \
  27. import GeneralLedgerWebkit
  28. from openerp.tools.translate import _
  29. # import logging
  30. # _logger = logging.getLogger(__name__)
  31. _column_sizes = [
  32. ('date', 12),
  33. ('period', 12),
  34. ('move', 20),
  35. ('journal', 12),
  36. ('account_code', 12),
  37. ('partner', 30),
  38. ('label', 45),
  39. ('counterpart', 30),
  40. ('debit', 15),
  41. ('credit', 15),
  42. ('cumul_bal', 15),
  43. ('curr_bal', 15),
  44. ('curr_code', 7),
  45. ]
  46. class general_ledger_xls(report_xls):
  47. column_sizes = [x[1] for x in _column_sizes]
  48. def generate_xls_report(self, _p, _xs, data, objects, wb):
  49. ws = wb.add_sheet(_p.report_name[:31])
  50. ws.panes_frozen = True
  51. ws.remove_splits = True
  52. ws.portrait = 0 # Landscape
  53. ws.fit_width_to_pages = 1
  54. row_pos = 0
  55. # set print header/footer
  56. ws.header_str = self.xls_headers['standard']
  57. ws.footer_str = self.xls_footers['standard']
  58. # cf. account_report_general_ledger.mako
  59. initial_balance_text = {'initial_balance': _('Computed'),
  60. 'opening_balance': _('Opening Entries'),
  61. False: _('No')}
  62. # Title
  63. cell_style = xlwt.easyxf(_xs['xls_title'])
  64. report_name = ' - '.join([_p.report_name.upper(),
  65. _p.company.partner_id.name,
  66. _p.company.currency_id.name])
  67. c_specs = [
  68. ('report_name', 1, 0, 'text', report_name),
  69. ]
  70. row_data = self.xls_row_template(c_specs, [x[0] for x in c_specs])
  71. row_pos = self.xls_write_row(
  72. ws, row_pos, row_data, row_style=cell_style)
  73. # write empty row to define column sizes
  74. c_sizes = self.column_sizes
  75. c_specs = [('empty%s' % i, 1, c_sizes[i], 'text', None)
  76. for i in range(0, len(c_sizes))]
  77. row_data = self.xls_row_template(c_specs, [x[0] for x in c_specs])
  78. row_pos = self.xls_write_row(
  79. ws, row_pos, row_data, set_column_size=True)
  80. # Header Table
  81. cell_format = _xs['bold'] + _xs['fill_blue'] + _xs['borders_all']
  82. cell_style = xlwt.easyxf(cell_format)
  83. cell_style_center = xlwt.easyxf(cell_format + _xs['center'])
  84. c_specs = [
  85. ('coa', 2, 0, 'text', _('Chart of Account')),
  86. ('fy', 1, 0, 'text', _('Fiscal Year')),
  87. ('df', 3, 0, 'text', _p.filter_form(data) ==
  88. 'filter_date' and _('Dates Filter') or _('Periods Filter')),
  89. ('af', 1, 0, 'text', _('Accounts Filter')),
  90. ('tm', 2, 0, 'text', _('Target Moves')),
  91. ('ib', 2, 0, 'text', _('Initial Balance')),
  92. ]
  93. row_data = self.xls_row_template(c_specs, [x[0] for x in c_specs])
  94. row_pos = self.xls_write_row(
  95. ws, row_pos, row_data, row_style=cell_style_center)
  96. cell_format = _xs['borders_all']
  97. cell_style = xlwt.easyxf(cell_format)
  98. cell_style_center = xlwt.easyxf(cell_format + _xs['center'])
  99. c_specs = [
  100. ('coa', 2, 0, 'text', _p.chart_account.name),
  101. ('fy', 1, 0, 'text', _p.fiscalyear.name if _p.fiscalyear else '-'),
  102. ]
  103. df = _('From') + ': '
  104. if _p.filter_form(data) == 'filter_date':
  105. df += _p.start_date if _p.start_date else u''
  106. else:
  107. df += _p.start_period.name if _p.start_period else u''
  108. df += ' ' + _('To') + ': '
  109. if _p.filter_form(data) == 'filter_date':
  110. df += _p.stop_date if _p.stop_date else u''
  111. else:
  112. df += _p.stop_period.name if _p.stop_period else u''
  113. c_specs += [
  114. ('df', 3, 0, 'text', df),
  115. ('af', 1, 0, 'text', _p.accounts(data) and ', '.join(
  116. [account.code for account in _p.accounts(data)]) or _('All')),
  117. ('tm', 2, 0, 'text', _p.display_target_move(data)),
  118. ('ib', 2, 0, 'text', initial_balance_text[
  119. _p.initial_balance_mode]),
  120. ]
  121. row_data = self.xls_row_template(c_specs, [x[0] for x in c_specs])
  122. row_pos = self.xls_write_row(
  123. ws, row_pos, row_data, row_style=cell_style_center)
  124. ws.set_horz_split_pos(row_pos)
  125. row_pos += 1
  126. # Column Title Row
  127. cell_format = _xs['bold']
  128. c_title_cell_style = xlwt.easyxf(cell_format)
  129. # Column Header Row
  130. cell_format = _xs['bold'] + _xs['fill'] + _xs['borders_all']
  131. c_hdr_cell_style = xlwt.easyxf(cell_format)
  132. c_hdr_cell_style_right = xlwt.easyxf(cell_format + _xs['right'])
  133. c_hdr_cell_style_center = xlwt.easyxf(cell_format + _xs['center'])
  134. c_hdr_cell_style_decimal = xlwt.easyxf(
  135. cell_format + _xs['right'],
  136. num_format_str=report_xls.decimal_format)
  137. # Column Initial Balance Row
  138. cell_format = _xs['italic'] + _xs['borders_all']
  139. c_init_cell_style = xlwt.easyxf(cell_format)
  140. c_init_cell_style_decimal = xlwt.easyxf(
  141. cell_format + _xs['right'],
  142. num_format_str=report_xls.decimal_format)
  143. c_specs = [
  144. ('date', 1, 0, 'text', _('Date'), None, c_hdr_cell_style),
  145. ('period', 1, 0, 'text', _('Period'), None, c_hdr_cell_style),
  146. ('move', 1, 0, 'text', _('Entry'), None, c_hdr_cell_style),
  147. ('journal', 1, 0, 'text', _('Journal'), None, c_hdr_cell_style),
  148. ('account_code', 1, 0, 'text',
  149. _('Account'), None, c_hdr_cell_style),
  150. ('partner', 1, 0, 'text', _('Partner'), None, c_hdr_cell_style),
  151. ('label', 1, 0, 'text', _('Label'), None, c_hdr_cell_style),
  152. ('counterpart', 1, 0, 'text',
  153. _('Counterpart'), None, c_hdr_cell_style),
  154. ('debit', 1, 0, 'text', _('Debit'), None, c_hdr_cell_style_right),
  155. ('credit', 1, 0, 'text', _('Credit'),
  156. None, c_hdr_cell_style_right),
  157. ('cumul_bal', 1, 0, 'text', _('Cumul. Bal.'),
  158. None, c_hdr_cell_style_right),
  159. ]
  160. if _p.amount_currency(data):
  161. c_specs += [
  162. ('curr_bal', 1, 0, 'text', _('Curr. Bal.'),
  163. None, c_hdr_cell_style_right),
  164. ('curr_code', 1, 0, 'text', _('Curr.'),
  165. None, c_hdr_cell_style_center),
  166. ]
  167. c_hdr_data = self.xls_row_template(c_specs, [x[0] for x in c_specs])
  168. # cell styles for ledger lines
  169. ll_cell_format = _xs['borders_all']
  170. ll_cell_style = xlwt.easyxf(ll_cell_format)
  171. ll_cell_style_center = xlwt.easyxf(ll_cell_format + _xs['center'])
  172. ll_cell_style_date = xlwt.easyxf(
  173. ll_cell_format + _xs['left'],
  174. num_format_str=report_xls.date_format)
  175. ll_cell_style_decimal = xlwt.easyxf(
  176. ll_cell_format + _xs['right'],
  177. num_format_str=report_xls.decimal_format)
  178. cnt = 0
  179. for account in objects:
  180. display_initial_balance = _p['init_balance'][account.id] and \
  181. (_p['init_balance'][account.id].get(
  182. 'debit', 0.0) != 0.0 or
  183. _p['init_balance'][account.id].get('credit', 0.0)
  184. != 0.0)
  185. display_ledger_lines = _p['ledger_lines'][account.id]
  186. if _p.display_account_raw(data) == 'all' or \
  187. (display_ledger_lines or display_initial_balance):
  188. # TO DO : replace cumul amounts by xls formulas
  189. cnt += 1
  190. cumul_debit = 0.0
  191. cumul_credit = 0.0
  192. cumul_balance = 0.0
  193. cumul_balance_curr = 0.0
  194. c_specs = [
  195. ('acc_title', 11, 0, 'text',
  196. ' - '.join([account.code, account.name])),
  197. ]
  198. row_data = self.xls_row_template(
  199. c_specs, [x[0] for x in c_specs])
  200. row_pos = self.xls_write_row(
  201. ws, row_pos, row_data, c_title_cell_style)
  202. row_pos = self.xls_write_row(ws, row_pos, c_hdr_data)
  203. row_start = row_pos
  204. if display_initial_balance:
  205. init_balance = _p['init_balance'][account.id]
  206. cumul_debit = init_balance.get('debit') or 0.0
  207. cumul_credit = init_balance.get('credit') or 0.0
  208. cumul_balance = init_balance.get('init_balance') or 0.0
  209. cumul_balance_curr = init_balance.get(
  210. 'init_balance_currency') or 0.0
  211. c_specs = [('empty%s' % x, 1, 0, 'text', None)
  212. for x in range(6)]
  213. c_specs += [
  214. ('init_bal', 1, 0, 'text', _('Initial Balance')),
  215. ('counterpart', 1, 0, 'text', None),
  216. ('debit', 1, 0, 'number', cumul_debit,
  217. None, c_init_cell_style_decimal),
  218. ('credit', 1, 0, 'number', cumul_credit,
  219. None, c_init_cell_style_decimal),
  220. ('cumul_bal', 1, 0, 'number', cumul_balance,
  221. None, c_init_cell_style_decimal),
  222. ]
  223. if _p.amount_currency(data):
  224. c_specs += [
  225. ('curr_bal', 1, 0, 'number', cumul_balance_curr,
  226. None, c_init_cell_style_decimal),
  227. ('curr_code', 1, 0, 'text', None),
  228. ]
  229. row_data = self.xls_row_template(
  230. c_specs, [x[0] for x in c_specs])
  231. row_pos = self.xls_write_row(
  232. ws, row_pos, row_data, c_init_cell_style)
  233. for line in _p['ledger_lines'][account.id]:
  234. cumul_debit += line.get('debit') or 0.0
  235. cumul_credit += line.get('credit') or 0.0
  236. cumul_balance_curr += line.get('amount_currency') or 0.0
  237. cumul_balance += line.get('balance') or 0.0
  238. label_elements = [line.get('lname') or '']
  239. if line.get('invoice_number'):
  240. label_elements.append(
  241. "(%s)" % (line['invoice_number'],))
  242. label = ' '.join(label_elements)
  243. if line.get('ldate'):
  244. c_specs = [
  245. ('ldate', 1, 0, 'date', datetime.strptime(
  246. line['ldate'], '%Y-%m-%d'), None,
  247. ll_cell_style_date),
  248. ]
  249. else:
  250. c_specs = [
  251. ('ldate', 1, 0, 'text', None),
  252. ]
  253. c_specs += [
  254. ('period', 1, 0, 'text',
  255. line.get('period_code') or ''),
  256. ('move', 1, 0, 'text', line.get('move_name') or ''),
  257. ('journal', 1, 0, 'text', line.get('jcode') or ''),
  258. ('account_code', 1, 0, 'text', account.code),
  259. ('partner', 1, 0, 'text',
  260. line.get('partner_name') or ''),
  261. ('label', 1, 0, 'text', label),
  262. ('counterpart', 1, 0, 'text',
  263. line.get('counterparts') or ''),
  264. ('debit', 1, 0, 'number', line.get('debit', 0.0),
  265. None, ll_cell_style_decimal),
  266. ('credit', 1, 0, 'number', line.get('credit', 0.0),
  267. None, ll_cell_style_decimal),
  268. ('cumul_bal', 1, 0, 'number', cumul_balance,
  269. None, ll_cell_style_decimal),
  270. ]
  271. if _p.amount_currency(data):
  272. c_specs += [
  273. ('curr_bal', 1, 0, 'number', line.get(
  274. 'amount_currency') or 0.0, None,
  275. ll_cell_style_decimal),
  276. ('curr_code', 1, 0, 'text', line.get(
  277. 'currency_code') or '', None,
  278. ll_cell_style_center),
  279. ]
  280. row_data = self.xls_row_template(
  281. c_specs, [x[0] for x in c_specs])
  282. row_pos = self.xls_write_row(
  283. ws, row_pos, row_data, ll_cell_style)
  284. debit_start = rowcol_to_cell(row_start, 8)
  285. debit_end = rowcol_to_cell(row_pos - 1, 8)
  286. debit_formula = 'SUM(' + debit_start + ':' + debit_end + ')'
  287. credit_start = rowcol_to_cell(row_start, 9)
  288. credit_end = rowcol_to_cell(row_pos - 1, 9)
  289. credit_formula = 'SUM(' + credit_start + ':' + credit_end + ')'
  290. balance_debit = rowcol_to_cell(row_pos, 8)
  291. balance_credit = rowcol_to_cell(row_pos, 9)
  292. balance_formula = balance_debit + '-' + balance_credit
  293. c_specs = [
  294. ('acc_title', 7, 0, 'text',
  295. ' - '.join([account.code, account.name])),
  296. ('cum_bal', 1, 0, 'text',
  297. _('Cumulated Balance on Account'),
  298. None, c_hdr_cell_style_right),
  299. ('debit', 1, 0, 'number', None,
  300. debit_formula, c_hdr_cell_style_decimal),
  301. ('credit', 1, 0, 'number', None,
  302. credit_formula, c_hdr_cell_style_decimal),
  303. ('balance', 1, 0, 'number', None,
  304. balance_formula, c_hdr_cell_style_decimal),
  305. ]
  306. if _p.amount_currency(data):
  307. if account.currency_id:
  308. c_specs += [('curr_bal', 1, 0, 'number',
  309. cumul_balance_curr, None,
  310. c_hdr_cell_style_decimal)]
  311. else:
  312. c_specs += [('curr_bal', 1, 0, 'text', None)]
  313. c_specs += [('curr_code', 1, 0, 'text', None)]
  314. row_data = self.xls_row_template(
  315. c_specs, [x[0] for x in c_specs])
  316. row_pos = self.xls_write_row(
  317. ws, row_pos, row_data, c_hdr_cell_style)
  318. row_pos += 1
  319. general_ledger_xls('report.account.account_report_general_ledger_xls',
  320. 'account.account',
  321. parser=GeneralLedgerWebkit)