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.

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