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.

1463 lines
46 KiB

8 years ago
8 years ago
  1. # -*- coding: utf-8 -*-
  2. # © 2016 Julien Coux (Camptocamp)
  3. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
  4. from odoo import models, fields, api, _
  5. class GeneralLedgerReport(models.TransientModel):
  6. """ Here, we just define class fields.
  7. For methods, go more bottom at this file.
  8. The class hierarchy is :
  9. * GeneralLedgerReport
  10. ** GeneralLedgerReportAccount
  11. *** GeneralLedgerReportMoveLine
  12. For non receivable/payable accounts
  13. For receivable/payable centralized accounts
  14. *** GeneralLedgerReportPartner
  15. For receivable/payable and not centralized accounts
  16. **** GeneralLedgerReportMoveLine
  17. For receivable/payable and not centralized accounts
  18. """
  19. _name = 'report_general_ledger_qweb'
  20. # Filters fields, used for data computation
  21. date_from = fields.Date()
  22. date_to = fields.Date()
  23. fy_start_date = fields.Date()
  24. only_posted_moves = fields.Boolean()
  25. hide_account_balance_at_0 = fields.Boolean()
  26. foreign_currency = fields.Boolean()
  27. company_id = fields.Many2one(comodel_name='res.company')
  28. filter_account_ids = fields.Many2many(comodel_name='account.account')
  29. filter_partner_ids = fields.Many2many(comodel_name='res.partner')
  30. filter_journal_ids = fields.Many2many(comodel_name='account.journal')
  31. filter_cost_center_ids = fields.Many2many(
  32. comodel_name='account.analytic.account'
  33. )
  34. centralize = fields.Boolean()
  35. # Flag fields, used for report display
  36. show_cost_center = fields.Boolean(
  37. default=lambda self: self.env.user.has_group(
  38. 'analytic.group_analytic_accounting'
  39. )
  40. )
  41. # Data fields, used to browse report data
  42. account_ids = fields.One2many(
  43. comodel_name='report_general_ledger_qweb_account',
  44. inverse_name='report_id'
  45. )
  46. # Compute of unaffected earnings account
  47. @api.depends('company_id')
  48. def _compute_unaffected_earnings_account(self):
  49. account_type = self.env.ref('account.data_unaffected_earnings')
  50. self.unaffected_earnings_account = self.env['account.account'].search(
  51. [
  52. ('user_type_id', '=', account_type.id),
  53. ('company_id', '=', self.company_id.id)
  54. ])
  55. unaffected_earnings_account = fields.Many2one(
  56. comodel_name='account.account',
  57. compute='_compute_unaffected_earnings_account',
  58. store=True
  59. )
  60. class GeneralLedgerReportAccount(models.TransientModel):
  61. _name = 'report_general_ledger_qweb_account'
  62. _order = 'code ASC'
  63. report_id = fields.Many2one(
  64. comodel_name='report_general_ledger_qweb',
  65. ondelete='cascade',
  66. index=True
  67. )
  68. # Data fields, used to keep link with real object
  69. account_id = fields.Many2one(
  70. 'account.account',
  71. index=True
  72. )
  73. # Data fields, used for report display
  74. code = fields.Char()
  75. name = fields.Char()
  76. initial_debit = fields.Float(digits=(16, 2))
  77. initial_credit = fields.Float(digits=(16, 2))
  78. initial_balance = fields.Float(digits=(16, 2))
  79. currency_id = fields.Many2one(comodel_name='res.currency')
  80. initial_balance_foreign_currency = fields.Float(digits=(16, 2))
  81. final_debit = fields.Float(digits=(16, 2))
  82. final_credit = fields.Float(digits=(16, 2))
  83. final_balance = fields.Float(digits=(16, 2))
  84. final_balance_foreign_currency = fields.Float(digits=(16, 2))
  85. # Flag fields, used for report display and for data computation
  86. is_partner_account = fields.Boolean()
  87. # Data fields, used to browse report data
  88. move_line_ids = fields.One2many(
  89. comodel_name='report_general_ledger_qweb_move_line',
  90. inverse_name='report_account_id'
  91. )
  92. partner_ids = fields.One2many(
  93. comodel_name='report_general_ledger_qweb_partner',
  94. inverse_name='report_account_id'
  95. )
  96. class GeneralLedgerReportPartner(models.TransientModel):
  97. _name = 'report_general_ledger_qweb_partner'
  98. report_account_id = fields.Many2one(
  99. comodel_name='report_general_ledger_qweb_account',
  100. ondelete='cascade',
  101. index=True
  102. )
  103. # Data fields, used to keep link with real object
  104. partner_id = fields.Many2one(
  105. 'res.partner',
  106. index=True
  107. )
  108. # Data fields, used for report display
  109. name = fields.Char()
  110. initial_debit = fields.Float(digits=(16, 2))
  111. initial_credit = fields.Float(digits=(16, 2))
  112. initial_balance = fields.Float(digits=(16, 2))
  113. currency_id = fields.Many2one(comodel_name='res.currency')
  114. initial_balance_foreign_currency = fields.Float(digits=(16, 2))
  115. final_debit = fields.Float(digits=(16, 2))
  116. final_credit = fields.Float(digits=(16, 2))
  117. final_balance = fields.Float(digits=(16, 2))
  118. final_balance_foreign_currency = fields.Float(digits=(16, 2))
  119. # Data fields, used to browse report data
  120. move_line_ids = fields.One2many(
  121. comodel_name='report_general_ledger_qweb_move_line',
  122. inverse_name='report_partner_id'
  123. )
  124. @api.model
  125. def _generate_order_by(self, order_spec, query):
  126. """Custom order to display "No partner allocated" at last position."""
  127. return """
  128. ORDER BY
  129. CASE
  130. WHEN "report_general_ledger_qweb_partner"."partner_id" IS NOT NULL
  131. THEN 0
  132. ELSE 1
  133. END,
  134. "report_general_ledger_qweb_partner"."name"
  135. """
  136. class GeneralLedgerReportMoveLine(models.TransientModel):
  137. _name = 'report_general_ledger_qweb_move_line'
  138. report_account_id = fields.Many2one(
  139. comodel_name='report_general_ledger_qweb_account',
  140. ondelete='cascade',
  141. index=True
  142. )
  143. report_partner_id = fields.Many2one(
  144. comodel_name='report_general_ledger_qweb_partner',
  145. ondelete='cascade',
  146. index=True
  147. )
  148. # Data fields, used to keep link with real object
  149. move_line_id = fields.Many2one('account.move.line')
  150. # Data fields, used for report display
  151. date = fields.Date()
  152. entry = fields.Char()
  153. journal = fields.Char()
  154. account = fields.Char()
  155. taxes_description = fields.Char()
  156. partner = fields.Char()
  157. label = fields.Char()
  158. cost_center = fields.Char()
  159. matching_number = fields.Char()
  160. debit = fields.Float(digits=(16, 2))
  161. credit = fields.Float(digits=(16, 2))
  162. cumul_balance = fields.Float(digits=(16, 2))
  163. currency_id = fields.Many2one(comodel_name='res.currency')
  164. amount_currency = fields.Float(digits=(16, 2))
  165. class GeneralLedgerReportCompute(models.TransientModel):
  166. """ Here, we just define methods.
  167. For class fields, go more top at this file.
  168. """
  169. _inherit = 'report_general_ledger_qweb'
  170. @api.multi
  171. def print_report(self, report_type):
  172. self.ensure_one()
  173. if report_type == 'xlsx':
  174. report_name = 'account_financial_report_qweb.' \
  175. 'report_general_ledger_xlsx'
  176. else:
  177. report_name = 'account_financial_report_qweb.' \
  178. 'report_general_ledger_qweb'
  179. return self.env['report'].get_action(docids=self.ids,
  180. report_name=report_name)
  181. def _get_html(self):
  182. result = {}
  183. rcontext = {}
  184. context = dict(self.env.context)
  185. report = self.browse(context.get('active_id'))
  186. if report:
  187. rcontext['o'] = report
  188. result['html'] = self.env.ref(
  189. 'account_financial_report_qweb.'
  190. 'report_general_ledger_html').render(rcontext)
  191. return result
  192. @api.model
  193. def get_html(self, given_context=None):
  194. return self._get_html()
  195. @api.multi
  196. def compute_data_for_report(
  197. self, with_line_details=True, with_partners=True):
  198. self.ensure_one()
  199. # Compute report data
  200. self._inject_account_values()
  201. if with_partners:
  202. self._inject_partner_values()
  203. if not self.filter_partner_ids:
  204. self._inject_partner_values(only_empty_partner=True)
  205. # Add unaffected earnings account
  206. if (not self.filter_account_ids or
  207. self.unaffected_earnings_account.id in
  208. self.filter_account_ids.ids):
  209. self._inject_unaffected_earnings_account_values()
  210. # Call this function even if we don't want line details because,
  211. # we need to compute
  212. # at least the values for unaffected earnings account
  213. # In this case, only unaffected earnings account values are computed
  214. only_unaffected_earnings_account = not with_line_details
  215. self._inject_line_not_centralized_values(
  216. only_unaffected_earnings_account=only_unaffected_earnings_account
  217. )
  218. if with_line_details:
  219. self._inject_line_not_centralized_values(
  220. is_account_line=False,
  221. is_partner_line=True)
  222. self._inject_line_not_centralized_values(
  223. is_account_line=False,
  224. is_partner_line=True,
  225. only_empty_partner_line=True)
  226. if self.centralize:
  227. self._inject_line_centralized_values()
  228. # Refresh cache because all data are computed with SQL requests
  229. self.invalidate_cache()
  230. def _get_account_sub_subquery_sum_amounts(
  231. self, include_initial_balance, date_included):
  232. """ Return subquery used to compute sum amounts on accounts """
  233. sub_subquery_sum_amounts = """
  234. SELECT
  235. a.id AS account_id,
  236. SUM(ml.debit) AS debit,
  237. SUM(ml.credit) AS credit,
  238. SUM(ml.balance) AS balance,
  239. c.id AS currency_id,
  240. CASE
  241. WHEN c.id IS NOT NULL
  242. THEN SUM(ml.amount_currency)
  243. ELSE NULL
  244. END AS balance_currency
  245. FROM
  246. accounts a
  247. INNER JOIN
  248. account_account_type at ON a.user_type_id = at.id
  249. INNER JOIN
  250. account_move_line ml
  251. ON a.id = ml.account_id
  252. """
  253. if date_included:
  254. sub_subquery_sum_amounts += """
  255. AND ml.date <= %s
  256. """
  257. else:
  258. sub_subquery_sum_amounts += """
  259. AND ml.date < %s
  260. """
  261. if not include_initial_balance:
  262. sub_subquery_sum_amounts += """
  263. AND at.include_initial_balance != TRUE AND ml.date >= %s
  264. """
  265. else:
  266. sub_subquery_sum_amounts += """
  267. AND at.include_initial_balance = TRUE
  268. """
  269. if self.only_posted_moves:
  270. sub_subquery_sum_amounts += """
  271. INNER JOIN
  272. account_move m ON ml.move_id = m.id AND m.state = 'posted'
  273. """
  274. if self.filter_cost_center_ids:
  275. sub_subquery_sum_amounts += """
  276. INNER JOIN
  277. account_analytic_account aa
  278. ON
  279. ml.analytic_account_id = aa.id
  280. AND aa.id IN %s
  281. """
  282. sub_subquery_sum_amounts += """
  283. LEFT JOIN
  284. res_currency c ON a.currency_id = c.id
  285. """
  286. sub_subquery_sum_amounts += """
  287. GROUP BY
  288. a.id, c.id
  289. """
  290. return sub_subquery_sum_amounts
  291. def _get_final_account_sub_subquery_sum_amounts(self, date_included):
  292. """ Return final subquery used to compute sum amounts on accounts """
  293. subquery_sum_amounts = """
  294. SELECT
  295. sub.account_id AS account_id,
  296. SUM(COALESCE(sub.debit, 0.0)) AS debit,
  297. SUM(COALESCE(sub.credit, 0.0)) AS credit,
  298. SUM(COALESCE(sub.balance, 0.0)) AS balance,
  299. MAX(sub.currency_id) AS currency_id,
  300. SUM(COALESCE(sub.balance_currency, 0.0)) AS balance_currency
  301. FROM
  302. (
  303. """
  304. subquery_sum_amounts += self._get_account_sub_subquery_sum_amounts(
  305. include_initial_balance=False, date_included=date_included
  306. )
  307. subquery_sum_amounts += """
  308. UNION
  309. """
  310. subquery_sum_amounts += self._get_account_sub_subquery_sum_amounts(
  311. include_initial_balance=True, date_included=date_included
  312. )
  313. subquery_sum_amounts += """
  314. ) sub
  315. GROUP BY
  316. sub.account_id
  317. """
  318. return subquery_sum_amounts
  319. def _inject_account_values(self):
  320. """Inject report values for report_general_ledger_qweb_account."""
  321. query_inject_account = """
  322. WITH
  323. accounts AS
  324. (
  325. SELECT
  326. a.id,
  327. a.code,
  328. a.name,
  329. a.internal_type IN ('payable', 'receivable')
  330. AS is_partner_account,
  331. a.user_type_id,
  332. a.currency_id
  333. FROM
  334. account_account a
  335. """
  336. if self.filter_partner_ids or self.filter_cost_center_ids:
  337. query_inject_account += """
  338. INNER JOIN
  339. account_move_line ml ON a.id = ml.account_id
  340. """
  341. if self.filter_partner_ids:
  342. query_inject_account += """
  343. INNER JOIN
  344. res_partner p ON ml.partner_id = p.id
  345. """
  346. if self.filter_cost_center_ids:
  347. query_inject_account += """
  348. INNER JOIN
  349. account_analytic_account aa
  350. ON
  351. ml.analytic_account_id = aa.id
  352. AND aa.id IN %s
  353. """
  354. query_inject_account += """
  355. WHERE
  356. a.company_id = %s
  357. AND a.id != %s
  358. """
  359. if self.filter_account_ids:
  360. query_inject_account += """
  361. AND
  362. a.id IN %s
  363. """
  364. if self.filter_partner_ids:
  365. query_inject_account += """
  366. AND
  367. p.id IN %s
  368. """
  369. if self.filter_partner_ids or self.filter_cost_center_ids:
  370. query_inject_account += """
  371. GROUP BY
  372. a.id
  373. """
  374. init_subquery = self._get_final_account_sub_subquery_sum_amounts(
  375. date_included=False
  376. )
  377. final_subquery = self._get_final_account_sub_subquery_sum_amounts(
  378. date_included=True
  379. )
  380. query_inject_account += """
  381. ),
  382. initial_sum_amounts AS ( """ + init_subquery + """ ),
  383. final_sum_amounts AS ( """ + final_subquery + """ )
  384. INSERT INTO
  385. report_general_ledger_qweb_account
  386. (
  387. report_id,
  388. create_uid,
  389. create_date,
  390. account_id,
  391. code,
  392. name,
  393. initial_debit,
  394. initial_credit,
  395. initial_balance,
  396. currency_id,
  397. initial_balance_foreign_currency,
  398. final_debit,
  399. final_credit,
  400. final_balance,
  401. final_balance_foreign_currency,
  402. is_partner_account
  403. )
  404. SELECT
  405. %s AS report_id,
  406. %s AS create_uid,
  407. NOW() AS create_date,
  408. a.id AS account_id,
  409. a.code,
  410. a.name,
  411. COALESCE(i.debit, 0.0) AS initial_debit,
  412. COALESCE(i.credit, 0.0) AS initial_credit,
  413. COALESCE(i.balance, 0.0) AS initial_balance,
  414. c.id AS currency_id,
  415. COALESCE(i.balance_currency, 0.0) AS initial_balance_foreign_currency,
  416. COALESCE(f.debit, 0.0) AS final_debit,
  417. COALESCE(f.credit, 0.0) AS final_credit,
  418. COALESCE(f.balance, 0.0) AS final_balance,
  419. COALESCE(f.balance_currency, 0.0) AS final_balance_foreign_currency,
  420. a.is_partner_account
  421. FROM
  422. accounts a
  423. LEFT JOIN
  424. initial_sum_amounts i ON a.id = i.account_id
  425. LEFT JOIN
  426. final_sum_amounts f ON a.id = f.account_id
  427. LEFT JOIN
  428. res_currency c ON c.id = a.currency_id
  429. WHERE
  430. (
  431. i.debit IS NOT NULL AND i.debit != 0
  432. OR i.credit IS NOT NULL AND i.credit != 0
  433. OR i.balance IS NOT NULL AND i.balance != 0
  434. OR f.debit IS NOT NULL AND f.debit != 0
  435. OR f.credit IS NOT NULL AND f.credit != 0
  436. OR f.balance IS NOT NULL AND f.balance != 0
  437. )
  438. """
  439. if self.hide_account_balance_at_0:
  440. query_inject_account += """
  441. AND
  442. f.balance IS NOT NULL AND f.balance != 0
  443. """
  444. query_inject_account_params = ()
  445. if self.filter_cost_center_ids:
  446. query_inject_account_params += (
  447. tuple(self.filter_cost_center_ids.ids),
  448. )
  449. query_inject_account_params += (
  450. self.company_id.id,
  451. self.unaffected_earnings_account.id,
  452. )
  453. if self.filter_account_ids:
  454. query_inject_account_params += (
  455. tuple(self.filter_account_ids.ids),
  456. )
  457. if self.filter_partner_ids:
  458. query_inject_account_params += (
  459. tuple(self.filter_partner_ids.ids),
  460. )
  461. query_inject_account_params += (
  462. self.date_from,
  463. self.fy_start_date,
  464. )
  465. if self.filter_cost_center_ids:
  466. query_inject_account_params += (
  467. tuple(self.filter_cost_center_ids.ids),
  468. )
  469. query_inject_account_params += (
  470. self.date_from,
  471. )
  472. if self.filter_cost_center_ids:
  473. query_inject_account_params += (
  474. tuple(self.filter_cost_center_ids.ids),
  475. )
  476. query_inject_account_params += (
  477. self.date_to,
  478. self.fy_start_date,
  479. )
  480. if self.filter_cost_center_ids:
  481. query_inject_account_params += (
  482. tuple(self.filter_cost_center_ids.ids),
  483. )
  484. query_inject_account_params += (
  485. self.date_to,
  486. )
  487. if self.filter_cost_center_ids:
  488. query_inject_account_params += (
  489. tuple(self.filter_cost_center_ids.ids),
  490. )
  491. query_inject_account_params += (
  492. self.id or 'NULL',
  493. self.env.uid,
  494. )
  495. self.env.cr.execute(query_inject_account, query_inject_account_params)
  496. def _get_partner_sub_subquery_sum_amounts(
  497. self, only_empty_partner, include_initial_balance, date_included
  498. ):
  499. """ Return subquery used to compute sum amounts on partners """
  500. sub_subquery_sum_amounts = """
  501. SELECT
  502. ap.account_id AS account_id,
  503. ap.partner_id AS partner_id,
  504. SUM(ml.debit) AS debit,
  505. SUM(ml.credit) AS credit,
  506. SUM(ml.balance) AS balance,
  507. c.id as currency_id,
  508. CASE
  509. WHEN c.id IS NOT NULL
  510. THEN SUM(ml.amount_currency)
  511. ELSE NULL
  512. END AS balance_currency
  513. FROM
  514. accounts_partners ap
  515. INNER JOIN account_account ac
  516. ON ac.id = ap.account_id
  517. LEFT JOIN
  518. res_currency c ON ac.currency_id = c.id
  519. INNER JOIN
  520. account_move_line ml
  521. ON ap.account_id = ml.account_id
  522. """
  523. if date_included:
  524. sub_subquery_sum_amounts += """
  525. AND ml.date <= %s
  526. """
  527. else:
  528. sub_subquery_sum_amounts += """
  529. AND ml.date < %s
  530. """
  531. if not only_empty_partner:
  532. sub_subquery_sum_amounts += """
  533. AND ap.partner_id = ml.partner_id
  534. """
  535. else:
  536. sub_subquery_sum_amounts += """
  537. AND ap.partner_id IS NULL AND ml.partner_id IS NULL
  538. """
  539. if not include_initial_balance:
  540. sub_subquery_sum_amounts += """
  541. AND ap.include_initial_balance != TRUE AND ml.date >= %s
  542. """
  543. else:
  544. sub_subquery_sum_amounts += """
  545. AND ap.include_initial_balance = TRUE
  546. """
  547. if self.only_posted_moves:
  548. sub_subquery_sum_amounts += """
  549. INNER JOIN
  550. account_move m ON ml.move_id = m.id AND m.state = 'posted'
  551. """
  552. if self.filter_cost_center_ids:
  553. sub_subquery_sum_amounts += """
  554. INNER JOIN
  555. account_analytic_account aa
  556. ON
  557. ml.analytic_account_id = aa.id
  558. AND aa.id IN %s
  559. """
  560. sub_subquery_sum_amounts += """
  561. GROUP BY
  562. ap.account_id, ap.partner_id, c.id
  563. """
  564. return sub_subquery_sum_amounts
  565. def _get_final_partner_sub_subquery_sum_amounts(self, only_empty_partner,
  566. date_included):
  567. """Return final subquery used to compute sum amounts on partners"""
  568. subquery_sum_amounts = """
  569. SELECT
  570. sub.account_id AS account_id,
  571. sub.partner_id AS partner_id,
  572. SUM(COALESCE(sub.debit, 0.0)) AS debit,
  573. SUM(COALESCE(sub.credit, 0.0)) AS credit,
  574. SUM(COALESCE(sub.balance, 0.0)) AS balance,
  575. MAX(sub.currency_id) AS currency_id,
  576. SUM(COALESCE(sub.balance_currency, 0.0)) AS balance_currency
  577. FROM
  578. (
  579. """
  580. subquery_sum_amounts += self._get_partner_sub_subquery_sum_amounts(
  581. only_empty_partner,
  582. include_initial_balance=False,
  583. date_included=date_included
  584. )
  585. subquery_sum_amounts += """
  586. UNION
  587. """
  588. subquery_sum_amounts += self._get_partner_sub_subquery_sum_amounts(
  589. only_empty_partner,
  590. include_initial_balance=True,
  591. date_included=date_included
  592. )
  593. subquery_sum_amounts += """
  594. ) sub
  595. GROUP BY
  596. sub.account_id, sub.partner_id
  597. """
  598. return subquery_sum_amounts
  599. def _inject_partner_values(self, only_empty_partner=False):
  600. """ Inject report values for report_general_ledger_qweb_partner.
  601. Only for "partner" accounts (payable and receivable).
  602. """
  603. # pylint: disable=sql-injection
  604. query_inject_partner = """
  605. WITH
  606. accounts_partners AS
  607. (
  608. SELECT
  609. ra.id AS report_account_id,
  610. a.id AS account_id,
  611. at.include_initial_balance AS include_initial_balance,
  612. p.id AS partner_id,
  613. COALESCE(
  614. CASE
  615. WHEN
  616. NULLIF(p.name, '') IS NOT NULL
  617. AND NULLIF(p.ref, '') IS NOT NULL
  618. THEN p.name || ' (' || p.ref || ')'
  619. ELSE p.name
  620. END,
  621. '""" + _('No partner allocated') + """'
  622. ) AS partner_name
  623. FROM
  624. report_general_ledger_qweb_account ra
  625. INNER JOIN
  626. account_account a ON ra.account_id = a.id
  627. INNER JOIN
  628. account_account_type at ON a.user_type_id = at.id
  629. INNER JOIN
  630. account_move_line ml ON a.id = ml.account_id
  631. LEFT JOIN
  632. res_partner p ON ml.partner_id = p.id
  633. """
  634. if self.filter_cost_center_ids:
  635. query_inject_partner += """
  636. INNER JOIN
  637. account_analytic_account aa
  638. ON
  639. ml.analytic_account_id = aa.id
  640. AND aa.id IN %s
  641. """
  642. query_inject_partner += """
  643. WHERE
  644. ra.report_id = %s
  645. AND
  646. ra.is_partner_account = TRUE
  647. """
  648. if not only_empty_partner:
  649. query_inject_partner += """
  650. AND
  651. p.id IS NOT NULL
  652. """
  653. else:
  654. query_inject_partner += """
  655. AND
  656. p.id IS NULL
  657. """
  658. query_inject_partner += """
  659. """
  660. if self.centralize:
  661. query_inject_partner += """
  662. AND (a.centralized IS NULL OR a.centralized != TRUE)
  663. """
  664. if self.filter_partner_ids:
  665. query_inject_partner += """
  666. AND
  667. p.id IN %s
  668. """
  669. init_subquery = self._get_final_partner_sub_subquery_sum_amounts(
  670. only_empty_partner,
  671. date_included=False
  672. )
  673. final_subquery = self._get_final_partner_sub_subquery_sum_amounts(
  674. only_empty_partner,
  675. date_included=True
  676. )
  677. query_inject_partner += """
  678. GROUP BY
  679. ra.id,
  680. a.id,
  681. p.id,
  682. at.include_initial_balance
  683. ),
  684. initial_sum_amounts AS ( """ + init_subquery + """ ),
  685. final_sum_amounts AS ( """ + final_subquery + """ )
  686. INSERT INTO
  687. report_general_ledger_qweb_partner
  688. (
  689. report_account_id,
  690. create_uid,
  691. create_date,
  692. partner_id,
  693. name,
  694. initial_debit,
  695. initial_credit,
  696. initial_balance,
  697. currency_id,
  698. initial_balance_foreign_currency,
  699. final_debit,
  700. final_credit,
  701. final_balance,
  702. final_balance_foreign_currency
  703. )
  704. SELECT
  705. ap.report_account_id,
  706. %s AS create_uid,
  707. NOW() AS create_date,
  708. ap.partner_id,
  709. ap.partner_name,
  710. COALESCE(i.debit, 0.0) AS initial_debit,
  711. COALESCE(i.credit, 0.0) AS initial_credit,
  712. COALESCE(i.balance, 0.0) AS initial_balance,
  713. i.currency_id AS currency_id,
  714. COALESCE(i.balance_currency, 0.0) AS initial_balance_foreign_currency,
  715. COALESCE(f.debit, 0.0) AS final_debit,
  716. COALESCE(f.credit, 0.0) AS final_credit,
  717. COALESCE(f.balance, 0.0) AS final_balance,
  718. COALESCE(f.balance_currency, 0.0) AS final_balance_foreign_currency
  719. FROM
  720. accounts_partners ap
  721. LEFT JOIN
  722. initial_sum_amounts i
  723. ON
  724. (
  725. """
  726. if not only_empty_partner:
  727. query_inject_partner += """
  728. ap.partner_id = i.partner_id
  729. """
  730. else:
  731. query_inject_partner += """
  732. ap.partner_id IS NULL AND i.partner_id IS NULL
  733. """
  734. query_inject_partner += """
  735. )
  736. AND ap.account_id = i.account_id
  737. LEFT JOIN
  738. final_sum_amounts f
  739. ON
  740. (
  741. """
  742. if not only_empty_partner:
  743. query_inject_partner += """
  744. ap.partner_id = f.partner_id
  745. """
  746. else:
  747. query_inject_partner += """
  748. ap.partner_id IS NULL AND f.partner_id IS NULL
  749. """
  750. query_inject_partner += """
  751. )
  752. AND ap.account_id = f.account_id
  753. WHERE
  754. (
  755. i.debit IS NOT NULL AND i.debit != 0
  756. OR i.credit IS NOT NULL AND i.credit != 0
  757. OR i.balance IS NOT NULL AND i.balance != 0
  758. OR f.debit IS NOT NULL AND f.debit != 0
  759. OR f.credit IS NOT NULL AND f.credit != 0
  760. OR f.balance IS NOT NULL AND f.balance != 0
  761. )
  762. """
  763. if self.hide_account_balance_at_0:
  764. query_inject_partner += """
  765. AND
  766. f.balance IS NOT NULL AND f.balance != 0
  767. """
  768. query_inject_partner_params = ()
  769. if self.filter_cost_center_ids:
  770. query_inject_partner_params += (
  771. tuple(self.filter_cost_center_ids.ids),
  772. )
  773. query_inject_partner_params += (
  774. self.id,
  775. )
  776. if self.filter_partner_ids:
  777. query_inject_partner_params += (
  778. tuple(self.filter_partner_ids.ids),
  779. )
  780. query_inject_partner_params += (
  781. self.date_from,
  782. self.fy_start_date,
  783. )
  784. if self.filter_cost_center_ids:
  785. query_inject_partner_params += (
  786. tuple(self.filter_cost_center_ids.ids),
  787. )
  788. query_inject_partner_params += (
  789. self.date_from,
  790. )
  791. if self.filter_cost_center_ids:
  792. query_inject_partner_params += (
  793. tuple(self.filter_cost_center_ids.ids),
  794. )
  795. query_inject_partner_params += (
  796. self.date_to,
  797. self.fy_start_date,
  798. )
  799. if self.filter_cost_center_ids:
  800. query_inject_partner_params += (
  801. tuple(self.filter_cost_center_ids.ids),
  802. )
  803. query_inject_partner_params += (
  804. self.date_to,
  805. )
  806. if self.filter_cost_center_ids:
  807. query_inject_partner_params += (
  808. tuple(self.filter_cost_center_ids.ids),
  809. )
  810. query_inject_partner_params += (
  811. self.env.uid,
  812. )
  813. self.env.cr.execute(query_inject_partner, query_inject_partner_params)
  814. def _inject_line_not_centralized_values(
  815. self,
  816. is_account_line=True,
  817. is_partner_line=False,
  818. only_empty_partner_line=False,
  819. only_unaffected_earnings_account=False):
  820. """ Inject report values for report_general_ledger_qweb_move_line.
  821. If centralized option have been chosen,
  822. only non centralized accounts are computed.
  823. In function of `is_account_line` and `is_partner_line` values,
  824. the move_line link is made either with account or either with partner.
  825. The "only_empty_partner_line" value is used
  826. to compute data without partner.
  827. """
  828. query_inject_move_line = """
  829. INSERT INTO
  830. report_general_ledger_qweb_move_line
  831. (
  832. """
  833. if is_account_line:
  834. query_inject_move_line += """
  835. report_account_id,
  836. """
  837. elif is_partner_line:
  838. query_inject_move_line += """
  839. report_partner_id,
  840. """
  841. query_inject_move_line += """
  842. create_uid,
  843. create_date,
  844. move_line_id,
  845. date,
  846. entry,
  847. journal,
  848. account,
  849. taxes_description,
  850. partner,
  851. label,
  852. cost_center,
  853. matching_number,
  854. debit,
  855. credit,
  856. cumul_balance,
  857. currency_id,
  858. amount_currency
  859. )
  860. SELECT
  861. """
  862. if is_account_line:
  863. query_inject_move_line += """
  864. ra.id AS report_account_id,
  865. """
  866. elif is_partner_line:
  867. query_inject_move_line += """
  868. rp.id AS report_partner_id,
  869. """
  870. query_inject_move_line += """
  871. %s AS create_uid,
  872. NOW() AS create_date,
  873. ml.id AS move_line_id,
  874. ml.date,
  875. m.name AS entry,
  876. j.code AS journal,
  877. a.code AS account,
  878. CASE
  879. WHEN
  880. ml.tax_line_id is not null
  881. THEN
  882. COALESCE(at.description, at.name)
  883. WHEN
  884. ml.tax_line_id is null
  885. THEN
  886. (SELECT
  887. array_to_string(
  888. array_agg(COALESCE(at.description, at.name)
  889. ), ', ')
  890. FROM
  891. account_move_line_account_tax_rel aml_at_rel
  892. LEFT JOIN
  893. account_tax at on (at.id = aml_at_rel.account_tax_id)
  894. WHERE
  895. aml_at_rel.account_move_line_id = ml.id)
  896. ELSE
  897. ''
  898. END as taxes_description,
  899. """
  900. if not only_empty_partner_line:
  901. query_inject_move_line += """
  902. CASE
  903. WHEN
  904. NULLIF(p.name, '') IS NOT NULL
  905. AND NULLIF(p.ref, '') IS NOT NULL
  906. THEN p.name || ' (' || p.ref || ')'
  907. ELSE p.name
  908. END AS partner,
  909. """
  910. elif only_empty_partner_line:
  911. query_inject_move_line += """
  912. '""" + _('No partner allocated') + """' AS partner,
  913. """
  914. query_inject_move_line += """
  915. CONCAT_WS(' - ', NULLIF(ml.ref, ''), NULLIF(ml.name, '')) AS label,
  916. aa.name AS cost_center,
  917. fr.name AS matching_number,
  918. ml.debit,
  919. ml.credit,
  920. """
  921. if is_account_line:
  922. query_inject_move_line += """
  923. ra.initial_balance + (
  924. SUM(ml.balance)
  925. OVER (PARTITION BY a.code
  926. ORDER BY a.code, ml.date, ml.id)
  927. ) AS cumul_balance,
  928. """
  929. elif is_partner_line and not only_empty_partner_line:
  930. query_inject_move_line += """
  931. rp.initial_balance + (
  932. SUM(ml.balance)
  933. OVER (PARTITION BY a.code, p.name
  934. ORDER BY a.code, p.name, ml.date, ml.id)
  935. ) AS cumul_balance,
  936. """
  937. elif is_partner_line and only_empty_partner_line:
  938. query_inject_move_line += """
  939. rp.initial_balance + (
  940. SUM(ml.balance)
  941. OVER (PARTITION BY a.code
  942. ORDER BY a.code, ml.date, ml.id)
  943. ) AS cumul_balance,
  944. """
  945. query_inject_move_line += """
  946. c.id AS currency_id,
  947. ml.amount_currency
  948. FROM
  949. """
  950. if is_account_line:
  951. query_inject_move_line += """
  952. report_general_ledger_qweb_account ra
  953. """
  954. elif is_partner_line:
  955. query_inject_move_line += """
  956. report_general_ledger_qweb_partner rp
  957. INNER JOIN
  958. report_general_ledger_qweb_account ra ON rp.report_account_id = ra.id
  959. """
  960. query_inject_move_line += """
  961. INNER JOIN
  962. account_move_line ml ON ra.account_id = ml.account_id
  963. INNER JOIN
  964. account_move m ON ml.move_id = m.id
  965. INNER JOIN
  966. account_journal j ON ml.journal_id = j.id
  967. INNER JOIN
  968. account_account a ON ml.account_id = a.id
  969. LEFT JOIN
  970. account_tax at ON ml.tax_line_id = at.id
  971. """
  972. if is_account_line:
  973. query_inject_move_line += """
  974. LEFT JOIN
  975. res_partner p ON ml.partner_id = p.id
  976. """
  977. elif is_partner_line and not only_empty_partner_line:
  978. query_inject_move_line += """
  979. INNER JOIN
  980. res_partner p
  981. ON ml.partner_id = p.id AND rp.partner_id = p.id
  982. """
  983. query_inject_move_line += """
  984. LEFT JOIN
  985. account_full_reconcile fr ON ml.full_reconcile_id = fr.id
  986. LEFT JOIN
  987. res_currency c ON ml.currency_id = c.id
  988. """
  989. if self.filter_cost_center_ids:
  990. query_inject_move_line += """
  991. INNER JOIN
  992. account_analytic_account aa
  993. ON
  994. ml.analytic_account_id = aa.id
  995. AND aa.id IN %s
  996. """
  997. else:
  998. query_inject_move_line += """
  999. LEFT JOIN
  1000. account_analytic_account aa ON ml.analytic_account_id = aa.id
  1001. """
  1002. query_inject_move_line += """
  1003. WHERE
  1004. ra.report_id = %s
  1005. AND
  1006. """
  1007. if only_unaffected_earnings_account:
  1008. query_inject_move_line += """
  1009. a.id = %s
  1010. AND
  1011. """
  1012. if is_account_line:
  1013. query_inject_move_line += """
  1014. (ra.is_partner_account IS NULL OR ra.is_partner_account != TRUE)
  1015. """
  1016. elif is_partner_line:
  1017. query_inject_move_line += """
  1018. ra.is_partner_account = TRUE
  1019. """
  1020. if self.centralize:
  1021. query_inject_move_line += """
  1022. AND
  1023. (a.centralized IS NULL OR a.centralized != TRUE)
  1024. """
  1025. query_inject_move_line += """
  1026. AND
  1027. ml.date BETWEEN %s AND %s
  1028. """
  1029. if self.only_posted_moves:
  1030. query_inject_move_line += """
  1031. AND
  1032. m.state = 'posted'
  1033. """
  1034. if only_empty_partner_line:
  1035. query_inject_move_line += """
  1036. AND
  1037. ml.partner_id IS NULL
  1038. AND
  1039. rp.partner_id IS NULL
  1040. """
  1041. if self.filter_journal_ids:
  1042. query_inject_move_line += """
  1043. AND
  1044. j.id IN %s
  1045. """
  1046. if is_account_line:
  1047. query_inject_move_line += """
  1048. ORDER BY
  1049. a.code, ml.date, ml.id
  1050. """
  1051. elif is_partner_line and not only_empty_partner_line:
  1052. query_inject_move_line += """
  1053. ORDER BY
  1054. a.code, p.name, ml.date, ml.id
  1055. """
  1056. elif is_partner_line and only_empty_partner_line:
  1057. query_inject_move_line += """
  1058. ORDER BY
  1059. a.code, ml.date, ml.id
  1060. """
  1061. query_inject_move_line_params = (
  1062. self.env.uid,
  1063. )
  1064. if self.filter_cost_center_ids:
  1065. query_inject_move_line_params += (
  1066. tuple(self.filter_cost_center_ids.ids),
  1067. )
  1068. query_inject_move_line_params += (
  1069. self.id,
  1070. )
  1071. if only_unaffected_earnings_account:
  1072. query_inject_move_line_params += (
  1073. self.unaffected_earnings_account.id,
  1074. )
  1075. query_inject_move_line_params += (
  1076. self.date_from,
  1077. self.date_to,
  1078. )
  1079. if self.filter_journal_ids:
  1080. query_inject_move_line_params += (tuple(
  1081. self.filter_journal_ids.ids,
  1082. ),)
  1083. self.env.cr.execute(
  1084. query_inject_move_line,
  1085. query_inject_move_line_params
  1086. )
  1087. def _inject_line_centralized_values(self):
  1088. """ Inject report values for report_general_ledger_qweb_move_line.
  1089. Only centralized accounts are computed.
  1090. """
  1091. query_inject_move_line_centralized = """
  1092. WITH
  1093. move_lines AS
  1094. (
  1095. SELECT
  1096. ml.account_id,
  1097. (
  1098. DATE_TRUNC('month', ml.date) + interval '1 month'
  1099. - interval '1 day'
  1100. )::date AS date,
  1101. SUM(ml.debit) AS debit,
  1102. SUM(ml.credit) AS credit,
  1103. SUM(ml.balance) AS balance,
  1104. ml.currency_id AS currency_id,
  1105. ml.journal_id as journal_id
  1106. FROM
  1107. report_general_ledger_qweb_account ra
  1108. INNER JOIN
  1109. account_move_line ml ON ra.account_id = ml.account_id
  1110. INNER JOIN
  1111. account_move m ON ml.move_id = m.id
  1112. INNER JOIN
  1113. account_account a ON ml.account_id = a.id
  1114. """
  1115. if self.filter_cost_center_ids:
  1116. query_inject_move_line_centralized += """
  1117. INNER JOIN
  1118. account_analytic_account aa
  1119. ON
  1120. ml.analytic_account_id = aa.id
  1121. AND aa.id IN %s
  1122. """
  1123. query_inject_move_line_centralized += """
  1124. WHERE
  1125. ra.report_id = %s
  1126. AND
  1127. a.centralized = TRUE
  1128. AND
  1129. ml.date BETWEEN %s AND %s
  1130. """
  1131. if self.only_posted_moves:
  1132. query_inject_move_line_centralized += """
  1133. AND
  1134. m.state = 'posted'
  1135. """
  1136. query_inject_move_line_centralized += """
  1137. GROUP BY
  1138. ra.id, ml.account_id, a.code, 2, ml.currency_id, ml.journal_id
  1139. )
  1140. INSERT INTO
  1141. report_general_ledger_qweb_move_line
  1142. (
  1143. report_account_id,
  1144. create_uid,
  1145. create_date,
  1146. date,
  1147. account,
  1148. journal,
  1149. label,
  1150. debit,
  1151. credit,
  1152. cumul_balance
  1153. )
  1154. SELECT
  1155. ra.id AS report_account_id,
  1156. %s AS create_uid,
  1157. NOW() AS create_date,
  1158. ml.date,
  1159. a.code AS account,
  1160. j.code as journal,
  1161. '""" + _('Centralized Entries') + """' AS label,
  1162. ml.debit AS debit,
  1163. ml.credit AS credit,
  1164. ra.initial_balance + (
  1165. SUM(ml.balance)
  1166. OVER (PARTITION BY a.code ORDER BY ml.date)
  1167. ) AS cumul_balance
  1168. FROM
  1169. report_general_ledger_qweb_account ra
  1170. INNER JOIN
  1171. move_lines ml ON ra.account_id = ml.account_id
  1172. INNER JOIN
  1173. account_account a ON ml.account_id = a.id
  1174. INNER JOIN
  1175. account_journal j ON ml.journal_id = j.id
  1176. LEFT JOIN
  1177. res_currency c ON ml.currency_id = c.id
  1178. WHERE
  1179. ra.report_id = %s
  1180. AND
  1181. (a.centralized IS NOT NULL AND a.centralized = TRUE)
  1182. """
  1183. if self.filter_journal_ids:
  1184. query_inject_move_line_centralized += """
  1185. AND
  1186. j.id in %s
  1187. """
  1188. query_inject_move_line_centralized += """
  1189. ORDER BY
  1190. a.code, ml.date
  1191. """
  1192. query_inject_move_line_centralized_params = ()
  1193. if self.filter_cost_center_ids:
  1194. query_inject_move_line_centralized_params += (
  1195. tuple(self.filter_cost_center_ids.ids),
  1196. )
  1197. query_inject_move_line_centralized_params += (
  1198. self.id,
  1199. self.date_from,
  1200. self.date_to,
  1201. self.env.uid,
  1202. self.id,
  1203. )
  1204. if self.filter_journal_ids:
  1205. query_inject_move_line_centralized_params += (tuple(
  1206. self.filter_journal_ids.ids,
  1207. ),)
  1208. self.env.cr.execute(
  1209. query_inject_move_line_centralized,
  1210. query_inject_move_line_centralized_params
  1211. )
  1212. def _get_unaffected_earnings_account_sub_subquery_sum_initial(
  1213. self
  1214. ):
  1215. """ Return subquery used to compute sum amounts on
  1216. unaffected earnings accounts """
  1217. sub_subquery_sum_amounts = """
  1218. SELECT
  1219. SUM(ml.balance) AS initial_balance,
  1220. 0.0 AS final_balance
  1221. FROM
  1222. account_account a
  1223. INNER JOIN
  1224. account_account_type at ON a.user_type_id = at.id
  1225. INNER JOIN
  1226. account_move_line ml
  1227. ON a.id = ml.account_id
  1228. AND ml.date < %(date_from)s
  1229. """
  1230. if self.only_posted_moves:
  1231. sub_subquery_sum_amounts += """
  1232. INNER JOIN
  1233. account_move m ON ml.move_id = m.id AND m.state = 'posted'
  1234. """
  1235. if self.filter_cost_center_ids:
  1236. sub_subquery_sum_amounts += """
  1237. INNER JOIN
  1238. account_analytic_account aa
  1239. ON
  1240. ml.analytic_account_id = aa.id
  1241. AND aa.id IN %(cost_center_ids)s
  1242. """
  1243. sub_subquery_sum_amounts += """
  1244. WHERE
  1245. a.company_id = %(company_id)s
  1246. AND
  1247. a.id IN %(unaffected_earnings_account_ids)s
  1248. """
  1249. if self.filter_journal_ids:
  1250. sub_subquery_sum_amounts += """
  1251. AND
  1252. ml.journal_id in %(filter_journal_ids)s """
  1253. return sub_subquery_sum_amounts
  1254. def _get_unaffected_earnings_account_sub_subquery_sum_final(self):
  1255. """ Return subquery used to compute sum amounts on
  1256. unaffected earnings accounts """
  1257. sub_subquery_sum_amounts = """
  1258. SELECT
  1259. 0.0 AS initial_balance,
  1260. SUM(ml.balance) AS final_balance
  1261. """
  1262. sub_subquery_sum_amounts += """
  1263. FROM
  1264. account_account a
  1265. INNER JOIN
  1266. account_account_type at ON a.user_type_id = at.id
  1267. INNER JOIN
  1268. account_move_line ml
  1269. ON a.id = ml.account_id
  1270. AND ml.date <= %(date_to)s
  1271. """
  1272. if self.only_posted_moves:
  1273. sub_subquery_sum_amounts += """
  1274. INNER JOIN
  1275. account_move m ON ml.move_id = m.id AND m.state = 'posted'
  1276. """
  1277. if self.filter_cost_center_ids:
  1278. sub_subquery_sum_amounts += """
  1279. INNER JOIN
  1280. account_analytic_account aa
  1281. ON
  1282. ml.analytic_account_id = aa.id
  1283. AND aa.id IN %(cost_center_ids)s
  1284. """
  1285. sub_subquery_sum_amounts += """
  1286. WHERE
  1287. a.company_id = %(company_id)s
  1288. AND
  1289. a.id IN %(unaffected_earnings_account_ids)s
  1290. """
  1291. if self.filter_journal_ids:
  1292. sub_subquery_sum_amounts += """
  1293. AND
  1294. ml.journal_id in %(filter_journal_ids)s
  1295. """
  1296. return sub_subquery_sum_amounts
  1297. def _inject_unaffected_earnings_account_values(self):
  1298. """Inject the report values of the unaffected earnings account
  1299. for report_general_ledger_qweb_account."""
  1300. subquery_sum_amounts = """
  1301. SELECT
  1302. SUM(COALESCE(sub.initial_balance, 0.0)) AS initial_balance,
  1303. SUM(COALESCE(sub.final_balance, 0.0)) AS final_balance
  1304. FROM
  1305. (
  1306. """
  1307. # Initial balances
  1308. subquery_sum_amounts += \
  1309. self._get_unaffected_earnings_account_sub_subquery_sum_initial()
  1310. subquery_sum_amounts += """
  1311. UNION
  1312. """
  1313. subquery_sum_amounts += \
  1314. self._get_unaffected_earnings_account_sub_subquery_sum_final()
  1315. subquery_sum_amounts += """
  1316. ) sub
  1317. """
  1318. # pylint: disable=sql-injection
  1319. query_inject_account = """
  1320. WITH
  1321. sum_amounts AS ( """ + subquery_sum_amounts + """ )
  1322. INSERT INTO
  1323. report_general_ledger_qweb_account
  1324. (
  1325. report_id,
  1326. create_uid,
  1327. create_date,
  1328. account_id,
  1329. code,
  1330. name,
  1331. is_partner_account,
  1332. initial_balance,
  1333. final_balance,
  1334. currency_id
  1335. )
  1336. SELECT
  1337. %(report_id)s AS report_id,
  1338. %(user_id)s AS create_uid,
  1339. NOW() AS create_date,
  1340. a.id AS account_id,
  1341. a.code,
  1342. a.name,
  1343. False AS is_partner_account,
  1344. COALESCE(i.initial_balance, 0.0) AS initial_balance,
  1345. COALESCE(i.final_balance, 0.0) AS final_balance,
  1346. c.id as currency_id
  1347. FROM
  1348. account_account a
  1349. LEFT JOIN
  1350. res_currency c ON c.id = a.currency_id,
  1351. sum_amounts i
  1352. WHERE
  1353. a.company_id = %(company_id)s
  1354. AND a.id = %(unaffected_earnings_account_id)s
  1355. """
  1356. query_inject_account_params = {
  1357. 'date_from': self.date_from,
  1358. 'date_to': self.date_to,
  1359. 'fy_start_date': self.fy_start_date,
  1360. }
  1361. if self.filter_cost_center_ids:
  1362. query_inject_account_params['cost_center_ids'] = \
  1363. tuple(self.filter_cost_center_ids.ids)
  1364. query_inject_account_params['company_id'] = self.company_id.id
  1365. query_inject_account_params['unaffected_earnings_account_id'] = \
  1366. self.unaffected_earnings_account.id
  1367. query_inject_account_params['report_id'] = self.id
  1368. query_inject_account_params['user_id'] = self.env.uid
  1369. if self.filter_journal_ids:
  1370. query_inject_account_params['filter_journal_ids'] = (tuple(
  1371. self.filter_journal_ids.ids,
  1372. ),)
  1373. # Fetch the profit and loss accounts
  1374. query_unaffected_earnings_account_ids = """
  1375. SELECT a.id
  1376. FROM account_account as a
  1377. INNER JOIN account_account_type as at
  1378. ON at.id = a.user_type_id
  1379. WHERE at.include_initial_balance = FALSE
  1380. """
  1381. self.env.cr.execute(query_unaffected_earnings_account_ids)
  1382. pl_account_ids = [r[0] for r in self.env.cr.fetchall()]
  1383. query_inject_account_params['unaffected_earnings_account_ids'] = \
  1384. tuple(pl_account_ids + [self.unaffected_earnings_account.id])
  1385. self.env.cr.execute(query_inject_account,
  1386. query_inject_account_params)