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.

210 lines
7.2 KiB

  1. # -*- coding: utf-8 -*-
  2. # © 2015 Yannick Vaucher (Camptocamp)
  3. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
  4. from openerp import models, fields, api
  5. from openerp import tools
  6. class FinancialReportLine(models.Model):
  7. _inherit = 'financial.report.line'
  8. _name = 'general.ledger.line'
  9. _description = "General Ledger report"
  10. _auto = False
  11. _order = 'account_id, date'
  12. @api.depends('invoice_number', 'name')
  13. def _get_label(self):
  14. for rec in self:
  15. invoice_number = ''
  16. if rec.invoice_number:
  17. invoice_number = ' (rec.invoice_number)'
  18. rec.label = u'%(line_name)s%(invoice_number)s' % {
  19. 'line_name': rec.name,
  20. 'invoice_number': invoice_number}
  21. label = fields.Char(compute='_get_label', readonly=True, store=False)
  22. def init(self, cr):
  23. report_name = self._name.replace('.', '_')
  24. tools.drop_view_if_exists(cr, report_name)
  25. query = """
  26. CREATE OR REPLACE VIEW %(report_name)s AS (
  27. SELECT
  28. acc.id AS account_id,
  29. acc.code AS account_code,
  30. acc.centralized,
  31. ml.id,
  32. ml.name,
  33. ml.ref,
  34. ml.date,
  35. date_part('year', ml.date) || '-' || date_part('month', ml.date)
  36. AS month,
  37. part.ref AS partner_ref,
  38. part.name AS partner_name,
  39. ml.journal_id,
  40. ml.currency_id,
  41. cur.name AS currency_code,
  42. ml.debit,
  43. ml.credit,
  44. ml.debit - ml.credit AS balance,
  45. ml.amount_currency,
  46. SUM(amount_currency) OVER w_account AS balance_curr,
  47. SUM(debit) OVER w_account AS cumul_debit,
  48. SUM(credit) OVER w_account AS cumul_credit,
  49. SUM(debit - credit) OVER w_account AS cumul_balance,
  50. SUM(amount_currency) OVER w_account AS cumul_balance_curr,
  51. SUM(debit) OVER w_account - debit AS init_debit,
  52. SUM(credit) OVER w_account - credit AS init_credit,
  53. SUM(debit - credit) OVER w_account - (debit - credit) AS init_balance,
  54. SUM(amount_currency) OVER w_account - (amount_currency)
  55. AS init_balance_curr,
  56. SUM(debit) OVER w_account_centralized AS debit_centralized,
  57. SUM(credit) OVER w_account_centralized AS credit_centralized,
  58. SUM(debit - credit) OVER w_account_centralized AS balance_centralized,
  59. SUM(amount_currency) OVER w_account_centralized
  60. AS balance_curr_centralized,
  61. SUM(debit) OVER w_account - SUM(debit)
  62. OVER w_account_centralized AS init_debit_centralized,
  63. SUM(credit) OVER w_account - SUM(credit)
  64. OVER w_account_centralized AS init_credit_centralized,
  65. SUM(debit - credit) OVER w_account - SUM(debit - credit)
  66. OVER w_account_centralized AS init_balance_centralized,
  67. SUM(amount_currency) OVER w_account - SUM(amount_currency)
  68. OVER w_account_centralized AS init_balance_curr_centralized,
  69. m.name AS move_name,
  70. m.state AS move_state,
  71. i.number AS invoice_number
  72. FROM
  73. account_account AS acc
  74. LEFT JOIN account_move_line AS ml ON (ml.account_id = acc.id)
  75. INNER JOIN res_partner AS part ON (ml.partner_id = part.id)
  76. INNER JOIN account_move AS m ON (ml.move_id = m.id)
  77. LEFT JOIN account_invoice AS i ON (m.id = i.move_id)
  78. LEFT JOIN res_currency AS cur ON (ml.currency_id = cur.id)
  79. WINDOW w_account AS (PARTITION BY acc.code ORDER BY ml.date, ml.id),
  80. w_account_centralized AS (
  81. PARTITION BY acc.code,
  82. date_part('year', ml.date),
  83. date_part('month', ml.date),
  84. ml.journal_id,
  85. ml.partner_id
  86. ORDER BY ml.date, ml.journal_id, ml.id)
  87. )
  88. """ % {'report_name': report_name}
  89. cr.execute(query)
  90. class GeneralLedgerReport(models.TransientModel):
  91. _name = 'report.account.report_generalledger_qweb'
  92. _inherit = 'account.report.common'
  93. @api.multi
  94. def _get_account_ids(self):
  95. res = False
  96. context = self.env.context
  97. if (context.get('active_model') == 'account.account' and
  98. context.get('active_ids')):
  99. res = context['active_ids']
  100. return res
  101. name = fields.Char()
  102. initial_balance = fields.Integer()
  103. account_ids = fields.Many2many(
  104. 'account.account',
  105. string='Filter on accounts',
  106. default=_get_account_ids,
  107. help="Only selected accounts will be printed. Leave empty to "
  108. "print all accounts.")
  109. journal_ids = fields.Many2many(
  110. 'account.journal',
  111. string='Filter on jourvals',
  112. help="Only selected journals will be printed. Leave empty to "
  113. "print all journals.")
  114. balance_mode = fields.Selection(
  115. [('initial_balance', 'Initial balance'),
  116. ('opening_balance', 'Opening balance')]
  117. )
  118. display_account = fields.Char()
  119. display_ledger_lines = fields.Boolean()
  120. display_initial_balance = fields.Boolean()
  121. MAPPING = {
  122. 'date_from': 'start_date',
  123. 'date_to': 'end_date',
  124. }
  125. @api.model
  126. def _get_values_from_wizard(self, data):
  127. """ Get values from wizard """
  128. values = {}
  129. for key, val in data.iteritems():
  130. if key in self.MAPPING:
  131. values[self.MAPPING[key]] = val
  132. elif key == 'fiscalyear':
  133. if val:
  134. values[key] = val[0]
  135. elif key == 'journal_ids':
  136. if val:
  137. values[key] = [(6, 0, val)]
  138. else:
  139. values[key] = val
  140. return values
  141. @api.multi
  142. def _get_centralized_move_ids(self, domain):
  143. """ Get last line of each selected centralized accounts """
  144. # inverse search on centralized boolean to finish the search to get the
  145. # ids of last lines of centralized accounts
  146. # XXX USE DISTINCT to speed up ?
  147. domain = domain[:]
  148. centralize_index = domain.index(('centralized', '=', False))
  149. domain[centralize_index] = ('centralized', '=', True)
  150. gl_lines = self.env['general.ledger.line'].search(domain)
  151. accounts = gl_lines.mapped('account_id')
  152. line_ids = []
  153. for acc in accounts:
  154. acc_lines = gl_lines.filtered(lambda rec: rec.account_id == acc)
  155. line_ids.append(acc_lines[-1].id)
  156. return line_ids
  157. @api.multi
  158. def _get_moves_from_dates(self):
  159. domain = self._get_moves_from_dates_domain()
  160. if self.centralize:
  161. centralized_ids = self._get_centralized_move_ids(domain)
  162. if centralized_ids:
  163. domain.insert(0, '|')
  164. domain.append(('id', 'in', centralized_ids))
  165. return self.env['general.ledger.line'].search(domain)
  166. @api.multi
  167. def render_html(self, data=None):
  168. report_name = 'account.report_generalledger_qweb'
  169. if data is None:
  170. return
  171. values = self._get_values_from_wizard(data['form'])
  172. report = self.create(values)
  173. report_lines = report._get_moves_from_dates()
  174. # TODO warning if no report_lines
  175. self.env['report']._get_report_from_name(report_name)
  176. docargs = {
  177. 'doc_ids': report.ids,
  178. 'doc_model': self._name,
  179. 'report_lines': report_lines,
  180. 'docs': report,
  181. # XXX
  182. 'has_currency': True
  183. }
  184. return self.env['report'].render(report_name, docargs)