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.

263 lines
7.5 KiB

  1. # © 2016 Julien Coux (Camptocamp)
  2. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
  3. from odoo import models, fields, api
  4. class TrialBalanceReport(models.TransientModel):
  5. """ Here, we just define class fields.
  6. For methods, go more bottom at this file.
  7. The class hierarchy is :
  8. * TrialBalanceReport
  9. ** TrialBalanceReportAccount
  10. *** TrialBalanceReportPartner
  11. If "show_partner_details" is selected
  12. """
  13. _name = 'report_trial_balance'
  14. # Filters fields, used for data computation
  15. date_from = fields.Date()
  16. date_to = fields.Date()
  17. fy_start_date = fields.Date()
  18. only_posted_moves = fields.Boolean()
  19. hide_account_balance_at_0 = fields.Boolean()
  20. company_id = fields.Many2one(comodel_name='res.company')
  21. filter_account_ids = fields.Many2many(comodel_name='account.account')
  22. filter_partner_ids = fields.Many2many(comodel_name='res.partner')
  23. show_partner_details = fields.Boolean()
  24. # General Ledger Report Data fields,
  25. # used as base for compute the data reports
  26. general_ledger_id = fields.Many2one(
  27. comodel_name='report_general_ledger'
  28. )
  29. # Data fields, used to browse report data
  30. account_ids = fields.One2many(
  31. comodel_name='report_trial_balance_account',
  32. inverse_name='report_id'
  33. )
  34. class TrialBalanceReportAccount(models.TransientModel):
  35. _name = 'report_trial_balance_account'
  36. _order = 'code ASC'
  37. report_id = fields.Many2one(
  38. comodel_name='report_trial_balance',
  39. ondelete='cascade',
  40. index=True
  41. )
  42. # Data fields, used to keep link with real object
  43. account_id = fields.Many2one(
  44. 'account.account',
  45. index=True
  46. )
  47. # Data fields, used for report display
  48. code = fields.Char()
  49. name = fields.Char()
  50. initial_balance = fields.Float(digits=(16, 2))
  51. debit = fields.Float(digits=(16, 2))
  52. credit = fields.Float(digits=(16, 2))
  53. final_balance = fields.Float(digits=(16, 2))
  54. # Data fields, used to browse report data
  55. partner_ids = fields.One2many(
  56. comodel_name='report_trial_balance_partner',
  57. inverse_name='report_account_id'
  58. )
  59. class TrialBalanceReportPartner(models.TransientModel):
  60. _name = 'report_trial_balance_partner'
  61. report_account_id = fields.Many2one(
  62. comodel_name='report_trial_balance_account',
  63. ondelete='cascade',
  64. index=True
  65. )
  66. # Data fields, used to keep link with real object
  67. partner_id = fields.Many2one(
  68. 'res.partner',
  69. index=True
  70. )
  71. # Data fields, used for report display
  72. name = fields.Char()
  73. initial_balance = fields.Float(digits=(16, 2))
  74. debit = fields.Float(digits=(16, 2))
  75. credit = fields.Float(digits=(16, 2))
  76. final_balance = fields.Float(digits=(16, 2))
  77. @api.model
  78. def _generate_order_by(self, order_spec, query):
  79. """Custom order to display "No partner allocated" at last position."""
  80. return """
  81. ORDER BY
  82. CASE
  83. WHEN "report_trial_balance_partner"."partner_id" IS NOT NULL
  84. THEN 0
  85. ELSE 1
  86. END,
  87. "report_trial_balance_partner"."name"
  88. """
  89. class TrialBalanceReportCompute(models.TransientModel):
  90. """ Here, we just define methods.
  91. For class fields, go more top at this file.
  92. """
  93. _inherit = 'report_trial_balance'
  94. @api.multi
  95. def print_report(self, report_type):
  96. self.ensure_one()
  97. if report_type == 'xlsx':
  98. report_name = 'a_f_r.report_trial_balance_xlsx'
  99. else:
  100. report_name = 'account_financial_report.' \
  101. 'report_trial_balance_qweb'
  102. return self.env['ir.actions.report'].search(
  103. [('report_name', '=', report_name),
  104. ('report_type', '=', report_type)], limit=1).report_action(self)
  105. def _get_html(self):
  106. result = {}
  107. rcontext = {}
  108. context = dict(self.env.context)
  109. report = self.browse(context.get('active_id'))
  110. if report:
  111. rcontext['o'] = report
  112. result['html'] = self.env.ref(
  113. 'account_financial_report.report_trial_balance').render(
  114. rcontext)
  115. return result
  116. @api.model
  117. def get_html(self, given_context=None):
  118. return self._get_html()
  119. def _prepare_report_general_ledger(self):
  120. self.ensure_one()
  121. return {
  122. 'date_from': self.date_from,
  123. 'date_to': self.date_to,
  124. 'only_posted_moves': self.only_posted_moves,
  125. 'hide_account_balance_at_0': self.hide_account_balance_at_0,
  126. 'company_id': self.company_id.id,
  127. 'filter_account_ids': [(6, 0, self.filter_account_ids.ids)],
  128. 'filter_partner_ids': [(6, 0, self.filter_partner_ids.ids)],
  129. 'fy_start_date': self.fy_start_date,
  130. }
  131. @api.multi
  132. def compute_data_for_report(self):
  133. self.ensure_one()
  134. # Compute General Ledger Report Data.
  135. # The data of Trial Balance Report
  136. # are based on General Ledger Report data.
  137. model = self.env['report_general_ledger']
  138. self.general_ledger_id = model.create(
  139. self._prepare_report_general_ledger()
  140. )
  141. self.general_ledger_id.compute_data_for_report(
  142. with_line_details=False, with_partners=self.show_partner_details
  143. )
  144. # Compute report data
  145. self._inject_account_values()
  146. if self.show_partner_details:
  147. self._inject_partner_values()
  148. # Refresh cache because all data are computed with SQL requests
  149. self.refresh()
  150. def _inject_account_values(self):
  151. """Inject report values for report_trial_balance_account"""
  152. query_inject_account = """
  153. INSERT INTO
  154. report_trial_balance_account
  155. (
  156. report_id,
  157. create_uid,
  158. create_date,
  159. account_id,
  160. code,
  161. name,
  162. initial_balance,
  163. debit,
  164. credit,
  165. final_balance
  166. )
  167. SELECT
  168. %s AS report_id,
  169. %s AS create_uid,
  170. NOW() AS create_date,
  171. rag.account_id,
  172. rag.code,
  173. rag.name,
  174. rag.initial_balance AS initial_balance,
  175. rag.final_debit - rag.initial_debit AS debit,
  176. rag.final_credit - rag.initial_credit AS credit,
  177. rag.final_balance AS final_balance
  178. FROM
  179. report_general_ledger_account rag
  180. WHERE
  181. rag.report_id = %s
  182. """
  183. query_inject_account_params = (
  184. self.id,
  185. self.env.uid,
  186. self.general_ledger_id.id,
  187. )
  188. self.env.cr.execute(query_inject_account, query_inject_account_params)
  189. def _inject_partner_values(self):
  190. """Inject report values for report_trial_balance_partner"""
  191. query_inject_partner = """
  192. INSERT INTO
  193. report_trial_balance_partner
  194. (
  195. report_account_id,
  196. create_uid,
  197. create_date,
  198. partner_id,
  199. name,
  200. initial_balance,
  201. debit,
  202. credit,
  203. final_balance
  204. )
  205. SELECT
  206. ra.id AS report_account_id,
  207. %s AS create_uid,
  208. NOW() AS create_date,
  209. rpg.partner_id,
  210. rpg.name,
  211. rpg.initial_balance AS initial_balance,
  212. rpg.final_debit - rpg.initial_debit AS debit,
  213. rpg.final_credit - rpg.initial_credit AS credit,
  214. rpg.final_balance AS final_balance
  215. FROM
  216. report_general_ledger_partner rpg
  217. INNER JOIN
  218. report_general_ledger_account rag ON rpg.report_account_id = rag.id
  219. INNER JOIN
  220. report_trial_balance_account ra ON rag.code = ra.code
  221. WHERE
  222. rag.report_id = %s
  223. AND ra.report_id = %s
  224. """
  225. query_inject_partner_params = (
  226. self.env.uid,
  227. self.general_ledger_id.id,
  228. self.id,
  229. )
  230. self.env.cr.execute(query_inject_partner, query_inject_partner_params)