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.

1431 lines
44 KiB

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