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.

251 lines
7.1 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. self.compute_data_for_report()
  98. if report_type == 'xlsx':
  99. report_name = 'a_f_r.report_trial_balance_xlsx'
  100. else:
  101. report_name = 'account_financial_report.' \
  102. 'report_trial_balance_qweb'
  103. return self.env['ir.actions.report'].search(
  104. [('report_name', '=', report_name),
  105. ('report_type', '=', report_type)], limit=1).report_action(self)
  106. def _prepare_report_general_ledger(self):
  107. self.ensure_one()
  108. return {
  109. 'date_from': self.date_from,
  110. 'date_to': self.date_to,
  111. 'only_posted_moves': self.only_posted_moves,
  112. 'hide_account_balance_at_0': self.hide_account_balance_at_0,
  113. 'company_id': self.company_id.id,
  114. 'filter_account_ids': [(6, 0, self.filter_account_ids.ids)],
  115. 'filter_partner_ids': [(6, 0, self.filter_partner_ids.ids)],
  116. 'fy_start_date': self.fy_start_date,
  117. }
  118. @api.multi
  119. def compute_data_for_report(self):
  120. self.ensure_one()
  121. # Compute General Ledger Report Data.
  122. # The data of Trial Balance Report
  123. # are based on General Ledger Report data.
  124. model = self.env['report_general_ledger']
  125. self.general_ledger_id = model.create(
  126. self._prepare_report_general_ledger()
  127. )
  128. self.general_ledger_id.compute_data_for_report(
  129. with_line_details=False, with_partners=self.show_partner_details
  130. )
  131. # Compute report data
  132. self._inject_account_values()
  133. if self.show_partner_details:
  134. self._inject_partner_values()
  135. # Refresh cache because all data are computed with SQL requests
  136. self.refresh()
  137. def _inject_account_values(self):
  138. """Inject report values for report_trial_balance_account"""
  139. query_inject_account = """
  140. INSERT INTO
  141. report_trial_balance_account
  142. (
  143. report_id,
  144. create_uid,
  145. create_date,
  146. account_id,
  147. code,
  148. name,
  149. initial_balance,
  150. debit,
  151. credit,
  152. final_balance
  153. )
  154. SELECT
  155. %s AS report_id,
  156. %s AS create_uid,
  157. NOW() AS create_date,
  158. rag.account_id,
  159. rag.code,
  160. rag.name,
  161. rag.initial_balance AS initial_balance,
  162. rag.final_debit - rag.initial_debit AS debit,
  163. rag.final_credit - rag.initial_credit AS credit,
  164. rag.final_balance AS final_balance
  165. FROM
  166. report_general_ledger_account rag
  167. WHERE
  168. rag.report_id = %s
  169. """
  170. query_inject_account_params = (
  171. self.id,
  172. self.env.uid,
  173. self.general_ledger_id.id,
  174. )
  175. self.env.cr.execute(query_inject_account, query_inject_account_params)
  176. def _inject_partner_values(self):
  177. """Inject report values for report_trial_balance_partner"""
  178. query_inject_partner = """
  179. INSERT INTO
  180. report_trial_balance_partner
  181. (
  182. report_account_id,
  183. create_uid,
  184. create_date,
  185. partner_id,
  186. name,
  187. initial_balance,
  188. debit,
  189. credit,
  190. final_balance
  191. )
  192. SELECT
  193. ra.id AS report_account_id,
  194. %s AS create_uid,
  195. NOW() AS create_date,
  196. rpg.partner_id,
  197. rpg.name,
  198. rpg.initial_balance AS initial_balance,
  199. rpg.final_debit - rpg.initial_debit AS debit,
  200. rpg.final_credit - rpg.initial_credit AS credit,
  201. rpg.final_balance AS final_balance
  202. FROM
  203. report_general_ledger_partner rpg
  204. INNER JOIN
  205. report_general_ledger_account rag ON rpg.report_account_id = rag.id
  206. INNER JOIN
  207. report_trial_balance_account ra ON rag.code = ra.code
  208. WHERE
  209. rag.report_id = %s
  210. AND ra.report_id = %s
  211. """
  212. query_inject_partner_params = (
  213. self.env.uid,
  214. self.general_ledger_id.id,
  215. self.id,
  216. )
  217. self.env.cr.execute(query_inject_partner, query_inject_partner_params)