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.

347 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) != 0.0)
  184. display_ledger_lines = _p['ledger_lines'][account.id]
  185. if _p.display_account_raw(data) == 'all' or \
  186. (display_ledger_lines or display_initial_balance):
  187. # TO DO : replace cumul amounts by xls formulas
  188. cnt += 1
  189. cumul_debit = 0.0
  190. cumul_credit = 0.0
  191. cumul_balance = 0.0
  192. cumul_balance_curr = 0.0
  193. c_specs = [
  194. ('acc_title', 11, 0, 'text',
  195. ' - '.join([account.code, account.name])),
  196. ]
  197. row_data = self.xls_row_template(
  198. c_specs, [x[0] for x in c_specs])
  199. row_pos = self.xls_write_row(
  200. ws, row_pos, row_data, c_title_cell_style)
  201. row_pos = self.xls_write_row(ws, row_pos, c_hdr_data)
  202. row_start = row_pos
  203. if display_initial_balance:
  204. init_balance = _p['init_balance'][account.id]
  205. cumul_debit = init_balance.get('debit') or 0.0
  206. cumul_credit = init_balance.get('credit') or 0.0
  207. cumul_balance = init_balance.get('init_balance') or 0.0
  208. cumul_balance_curr = init_balance.get(
  209. 'init_balance_currency') or 0.0
  210. c_specs = [('empty%s' % x, 1, 0, 'text', None)
  211. for x in range(6)]
  212. c_specs += [
  213. ('init_bal', 1, 0, 'text', _('Initial Balance')),
  214. ('counterpart', 1, 0, 'text', None),
  215. ('debit', 1, 0, 'number', cumul_debit,
  216. None, c_init_cell_style_decimal),
  217. ('credit', 1, 0, 'number', cumul_credit,
  218. None, c_init_cell_style_decimal),
  219. ('cumul_bal', 1, 0, 'number', cumul_balance,
  220. None, c_init_cell_style_decimal),
  221. ]
  222. if _p.amount_currency(data):
  223. c_specs += [
  224. ('curr_bal', 1, 0, 'number', cumul_balance_curr,
  225. None, c_init_cell_style_decimal),
  226. ('curr_code', 1, 0, 'text', None),
  227. ]
  228. row_data = self.xls_row_template(
  229. c_specs, [x[0] for x in c_specs])
  230. row_pos = self.xls_write_row(
  231. ws, row_pos, row_data, c_init_cell_style)
  232. for line in _p['ledger_lines'][account.id]:
  233. cumul_debit += line.get('debit') or 0.0
  234. cumul_credit += line.get('credit') or 0.0
  235. cumul_balance_curr += line.get('amount_currency') or 0.0
  236. cumul_balance += line.get('balance') or 0.0
  237. label_elements = [line.get('lname') or '']
  238. if line.get('invoice_number'):
  239. label_elements.append(
  240. "(%s)" % (line['invoice_number'],))
  241. label = ' '.join(label_elements)
  242. if line.get('ldate'):
  243. c_specs = [
  244. ('ldate', 1, 0, 'date', datetime.strptime(
  245. line['ldate'], '%Y-%m-%d'), None,
  246. ll_cell_style_date),
  247. ]
  248. else:
  249. c_specs = [
  250. ('ldate', 1, 0, 'text', None),
  251. ]
  252. c_specs += [
  253. ('period', 1, 0, 'text',
  254. line.get('period_code') or ''),
  255. ('move', 1, 0, 'text', line.get('move_name') or ''),
  256. ('journal', 1, 0, 'text', line.get('jcode') or ''),
  257. ('account_code', 1, 0, 'text', account.code),
  258. ('partner', 1, 0, 'text',
  259. line.get('partner_name') or ''),
  260. ('label', 1, 0, 'text', label),
  261. ('counterpart', 1, 0, 'text',
  262. line.get('counterparts') or ''),
  263. ('debit', 1, 0, 'number', line.get('debit', 0.0),
  264. None, ll_cell_style_decimal),
  265. ('credit', 1, 0, 'number', line.get('credit', 0.0),
  266. None, ll_cell_style_decimal),
  267. ('cumul_bal', 1, 0, 'number', cumul_balance,
  268. None, ll_cell_style_decimal),
  269. ]
  270. if _p.amount_currency(data):
  271. c_specs += [
  272. ('curr_bal', 1, 0, 'number', line.get(
  273. 'amount_currency') or 0.0, None,
  274. ll_cell_style_decimal),
  275. ('curr_code', 1, 0, 'text', line.get(
  276. 'currency_code') or '', None,
  277. ll_cell_style_center),
  278. ]
  279. row_data = self.xls_row_template(
  280. c_specs, [x[0] for x in c_specs])
  281. row_pos = self.xls_write_row(
  282. ws, row_pos, row_data, ll_cell_style)
  283. debit_start = rowcol_to_cell(row_start, 8)
  284. debit_end = rowcol_to_cell(row_pos - 1, 8)
  285. debit_formula = 'SUM(' + debit_start + ':' + debit_end + ')'
  286. credit_start = rowcol_to_cell(row_start, 9)
  287. credit_end = rowcol_to_cell(row_pos - 1, 9)
  288. credit_formula = 'SUM(' + credit_start + ':' + credit_end + ')'
  289. balance_debit = rowcol_to_cell(row_pos, 8)
  290. balance_credit = rowcol_to_cell(row_pos, 9)
  291. balance_formula = balance_debit + '-' + balance_credit
  292. c_specs = [
  293. ('acc_title', 7, 0, 'text',
  294. ' - '.join([account.code, account.name])),
  295. ('cum_bal', 1, 0, 'text',
  296. _('Cumulated Balance on Account'),
  297. None, c_hdr_cell_style_right),
  298. ('debit', 1, 0, 'number', None,
  299. debit_formula, c_hdr_cell_style_decimal),
  300. ('credit', 1, 0, 'number', None,
  301. credit_formula, c_hdr_cell_style_decimal),
  302. ('balance', 1, 0, 'number', None,
  303. balance_formula, c_hdr_cell_style_decimal),
  304. ]
  305. if _p.amount_currency(data):
  306. if account.currency_id:
  307. c_specs += [('curr_bal', 1, 0, 'number',
  308. cumul_balance_curr, None,
  309. c_hdr_cell_style_decimal)]
  310. else:
  311. c_specs += [('curr_bal', 1, 0, 'text', None)]
  312. c_specs += [('curr_code', 1, 0, 'text', None)]
  313. row_data = self.xls_row_template(
  314. c_specs, [x[0] for x in c_specs])
  315. row_pos = self.xls_write_row(
  316. ws, row_pos, row_data, c_hdr_cell_style)
  317. row_pos += 1
  318. general_ledger_xls('report.account.account_report_general_ledger_xls',
  319. 'account.account',
  320. parser=GeneralLedgerWebkit)