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.

716 lines
24 KiB

  1. # Copyright 2017 ACSONE SA/NV
  2. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
  3. from odoo import api, fields, models
  4. DIGITS = (16, 2)
  5. class ReportJournalLedger(models.TransientModel):
  6. _name = "report_journal_ledger"
  7. _description = "Journal Ledger Report"
  8. _inherit = "account_financial_report_abstract"
  9. date_from = fields.Date(required=True)
  10. date_to = fields.Date(required=True)
  11. company_id = fields.Many2one(
  12. comodel_name="res.company", required=True, ondelete="cascade"
  13. )
  14. move_target = fields.Selection(
  15. selection="_get_move_targets", default="all", required=True,
  16. )
  17. sort_option = fields.Selection(
  18. selection="_get_sort_options", default="move_name", required=True,
  19. )
  20. group_option = fields.Selection(
  21. selection="_get_group_options", default="journal", required=True,
  22. )
  23. journal_ids = fields.Many2many(comodel_name="account.journal", required=True,)
  24. report_journal_ledger_ids = fields.One2many(
  25. comodel_name="report_journal_ledger_journal", inverse_name="report_id",
  26. )
  27. report_move_ids = fields.One2many(
  28. comodel_name="report_journal_ledger_move", inverse_name="report_id",
  29. )
  30. report_move_line_ids = fields.One2many(
  31. comodel_name="report_journal_ledger_move_line", inverse_name="report_id",
  32. )
  33. report_journal_ledger_tax_line_ids = fields.One2many(
  34. comodel_name="report_journal_ledger_journal_tax_line", inverse_name="report_id",
  35. )
  36. report_tax_line_ids = fields.One2many(
  37. comodel_name="report_journal_ledger_report_tax_line", inverse_name="report_id",
  38. )
  39. foreign_currency = fields.Boolean()
  40. with_account_name = fields.Boolean()
  41. @api.model
  42. def _get_move_targets(self):
  43. return self.env["journal.ledger.report.wizard"]._get_move_targets()
  44. @api.model
  45. def _get_sort_options(self):
  46. return self.env["journal.ledger.report.wizard"]._get_sort_options()
  47. @api.model
  48. def _get_group_options(self):
  49. return self.env["journal.ledger.report.wizard"]._get_group_options()
  50. def compute_data_for_report(self):
  51. self.ensure_one()
  52. self._inject_journal_values()
  53. self._inject_move_values()
  54. self._inject_move_line_values()
  55. self._inject_journal_tax_values()
  56. self._update_journal_report_total_values()
  57. if self.group_option == "none":
  58. self._inject_report_tax_values()
  59. # Refresh cache because all data are computed with SQL requests
  60. self.invalidate_cache()
  61. def _inject_journal_values(self):
  62. self.ensure_one()
  63. sql = """
  64. DELETE
  65. FROM report_journal_ledger_journal
  66. WHERE report_id = %s
  67. """
  68. params = (self.id,)
  69. self.env.cr.execute(sql, params)
  70. sql = """
  71. INSERT INTO report_journal_ledger_journal (
  72. create_uid,
  73. create_date,
  74. report_id,
  75. journal_id,
  76. name,
  77. code,
  78. company_id,
  79. currency_id
  80. )
  81. SELECT
  82. %s as create_uid,
  83. NOW() as create_date,
  84. %s as report_id,
  85. aj.id as journal_id,
  86. aj.name as name,
  87. aj.code as code,
  88. aj.company_id as company_id,
  89. COALESCE(aj.currency_id, company.currency_id) as currency_id
  90. FROM
  91. account_journal aj
  92. LEFT JOIN
  93. res_company company on (company.id = aj.company_id)
  94. WHERE
  95. aj.id in %s
  96. AND
  97. aj.company_id = %s
  98. ORDER BY
  99. aj.name
  100. """
  101. params = (
  102. self.env.uid,
  103. self.id,
  104. tuple(self.journal_ids.ids),
  105. self.company_id.id,
  106. )
  107. self.env.cr.execute(sql, params)
  108. def _inject_move_values(self):
  109. self.ensure_one()
  110. sql = """
  111. DELETE
  112. FROM report_journal_ledger_move
  113. WHERE report_id = %s
  114. """
  115. params = (self.id,)
  116. self.env.cr.execute(sql, params)
  117. sql = self._get_inject_move_insert()
  118. sql += self._get_inject_move_select()
  119. sql += self._get_inject_move_where_clause()
  120. sql += self._get_inject_move_order_by()
  121. params = self._get_inject_move_params()
  122. self.env.cr.execute(sql, params)
  123. def _get_inject_move_insert(self):
  124. return """
  125. INSERT INTO report_journal_ledger_move (
  126. create_uid,
  127. create_date,
  128. report_id,
  129. report_journal_ledger_id,
  130. move_id,
  131. name,
  132. company_id
  133. )
  134. """
  135. def _get_inject_move_select(self):
  136. return """
  137. SELECT
  138. %s as create_uid,
  139. NOW() as create_date,
  140. rjqj.report_id as report_id,
  141. rjqj.id as report_journal_ledger_id,
  142. am.id as move_id,
  143. am.name as name,
  144. am.company_id as company_id
  145. FROM
  146. account_move am
  147. INNER JOIN
  148. report_journal_ledger_journal rjqj
  149. on (rjqj.journal_id = am.journal_id)
  150. """
  151. def _get_inject_move_where_clause(self):
  152. self.ensure_one()
  153. where_clause = """
  154. WHERE
  155. rjqj.report_id = %s
  156. AND
  157. am.date >= %s
  158. AND
  159. am.date <= %s
  160. """
  161. if self.move_target != "all":
  162. where_clause += """
  163. AND
  164. am.state = %s
  165. """
  166. return where_clause
  167. def _get_inject_move_order_by(self):
  168. self.ensure_one()
  169. order_by = """
  170. ORDER BY
  171. """
  172. if self.sort_option == "move_name":
  173. order_by += " am.name"
  174. elif self.sort_option == "date":
  175. order_by += " am.date, am.name"
  176. return order_by
  177. def _get_inject_move_params(self):
  178. params = [self.env.uid, self.id, self.date_from, self.date_to]
  179. if self.move_target != "all":
  180. params.append(self.move_target)
  181. return tuple(params)
  182. def _inject_move_line_values(self):
  183. self.ensure_one()
  184. sql = """
  185. DELETE
  186. FROM report_journal_ledger_move_line
  187. WHERE report_id = %s
  188. """
  189. params = (self.id,)
  190. self.env.cr.execute(sql, params)
  191. sql = """
  192. INSERT INTO report_journal_ledger_move_line (
  193. create_uid,
  194. create_date,
  195. report_id,
  196. report_journal_ledger_id,
  197. report_move_id,
  198. move_line_id,
  199. account_id,
  200. account,
  201. account_code,
  202. account_type,
  203. partner_id,
  204. partner,
  205. date,
  206. entry,
  207. label,
  208. debit,
  209. credit,
  210. company_currency_id,
  211. amount_currency,
  212. currency_id,
  213. currency_name,
  214. tax_id,
  215. taxes_description,
  216. company_id
  217. )
  218. SELECT
  219. %s as create_uid,
  220. NOW() as create_date,
  221. rjqm.report_id as report_id,
  222. rjqm.report_journal_ledger_id as report_journal_ledger_id,
  223. rjqm.id as report_move_id,
  224. aml.id as move_line_id,
  225. aml.account_id as account_id,
  226. aa.name as account,
  227. aa.code as account_code,
  228. aa.internal_type as account_type,
  229. aml.partner_id as partner_id,
  230. p.name as partner,
  231. aml.date as date,
  232. rjqm.name as entry,
  233. aml.name as label,
  234. aml.debit as debit,
  235. aml.credit as credit,
  236. aml.company_currency_id as currency_id,
  237. aml.amount_currency as amount_currency,
  238. aml.currency_id as currency_id,
  239. currency.name as currency_name,
  240. aml.tax_line_id as tax_id,
  241. CASE
  242. WHEN
  243. aml.tax_line_id is not null
  244. THEN
  245. COALESCE(at.description, at.name)
  246. WHEN
  247. aml.tax_line_id is null
  248. THEN
  249. (SELECT
  250. array_to_string(
  251. array_agg(COALESCE(at.description, at.name)
  252. ), ', ')
  253. FROM
  254. account_move_line_account_tax_rel aml_at_rel
  255. LEFT JOIN
  256. account_tax at on (at.id = aml_at_rel.account_tax_id)
  257. WHERE
  258. aml_at_rel.account_move_line_id = aml.id)
  259. ELSE
  260. ''
  261. END as taxes_description,
  262. aml.company_id as company_id
  263. FROM
  264. account_move_line aml
  265. INNER JOIN
  266. report_journal_ledger_move rjqm
  267. on (rjqm.move_id = aml.move_id)
  268. LEFT JOIN
  269. account_account aa
  270. on (aa.id = aml.account_id)
  271. LEFT JOIN
  272. res_partner p
  273. on (p.id = aml.partner_id)
  274. LEFT JOIN
  275. account_tax at
  276. on (at.id = aml.tax_line_id)
  277. LEFT JOIN
  278. res_currency currency
  279. on (currency.id = aml.currency_id)
  280. WHERE
  281. rjqm.report_id = %s
  282. """
  283. params = (
  284. self.env.uid,
  285. self.id,
  286. )
  287. self.env.cr.execute(sql, params)
  288. def _inject_report_tax_values(self):
  289. self.ensure_one()
  290. sql_distinct_tax_id = """
  291. SELECT
  292. distinct(jrqjtl.tax_id)
  293. FROM
  294. report_journal_ledger_journal_tax_line jrqjtl
  295. WHERE
  296. jrqjtl.report_id = %s
  297. """
  298. self.env.cr.execute(sql_distinct_tax_id, (self.id,))
  299. rows = self.env.cr.fetchall()
  300. tax_ids = {row[0] for row in rows}
  301. sql = """
  302. INSERT INTO report_journal_ledger_report_tax_line (
  303. create_uid,
  304. create_date,
  305. report_id,
  306. tax_id,
  307. tax_name,
  308. tax_code,
  309. base_debit,
  310. base_credit,
  311. tax_debit,
  312. tax_credit
  313. )
  314. SELECT
  315. %s as create_uid,
  316. NOW() as create_date,
  317. %s as report_id,
  318. %s as tax_id,
  319. at.name as tax_name,
  320. at.description as tax_code,
  321. (
  322. SELECT sum(base_debit)
  323. FROM report_journal_ledger_journal_tax_line jrqjtl2
  324. WHERE jrqjtl2.report_id = %s
  325. AND jrqjtl2.tax_id = %s
  326. ) as base_debit,
  327. (
  328. SELECT sum(base_credit)
  329. FROM report_journal_ledger_journal_tax_line jrqjtl2
  330. WHERE jrqjtl2.report_id = %s
  331. AND jrqjtl2.tax_id = %s
  332. ) as base_credit,
  333. (
  334. SELECT sum(tax_debit)
  335. FROM report_journal_ledger_journal_tax_line jrqjtl2
  336. WHERE jrqjtl2.report_id = %s
  337. AND jrqjtl2.tax_id = %s
  338. ) as tax_debit,
  339. (
  340. SELECT sum(tax_credit)
  341. FROM report_journal_ledger_journal_tax_line jrqjtl2
  342. WHERE jrqjtl2.report_id = %s
  343. AND jrqjtl2.tax_id = %s
  344. ) as tax_credit
  345. FROM
  346. report_journal_ledger_journal_tax_line jrqjtl
  347. LEFT JOIN
  348. account_tax at
  349. on (at.id = jrqjtl.tax_id)
  350. WHERE
  351. jrqjtl.report_id = %s
  352. AND
  353. jrqjtl.tax_id = %s
  354. """
  355. for tax_id in tax_ids:
  356. params = (
  357. self.env.uid,
  358. self.id,
  359. tax_id,
  360. self.id,
  361. tax_id,
  362. self.id,
  363. tax_id,
  364. self.id,
  365. tax_id,
  366. self.id,
  367. tax_id,
  368. self.id,
  369. tax_id,
  370. )
  371. self.env.cr.execute(sql, params)
  372. def _inject_journal_tax_values(self):
  373. self.ensure_one()
  374. sql = """
  375. DELETE
  376. FROM report_journal_ledger_journal_tax_line
  377. WHERE report_id = %s
  378. """
  379. params = (self.id,)
  380. self.env.cr.execute(sql, params)
  381. sql_distinct_tax_id = """
  382. SELECT
  383. distinct(jrqml.tax_id)
  384. FROM
  385. report_journal_ledger_move_line jrqml
  386. WHERE
  387. jrqml.report_journal_ledger_id = %s
  388. """
  389. tax_ids_by_journal_id = {}
  390. for report_journal in self.report_journal_ledger_ids:
  391. if report_journal.id not in tax_ids_by_journal_id:
  392. tax_ids_by_journal_id[report_journal.id] = []
  393. self.env.cr.execute(sql_distinct_tax_id, (report_journal.id,))
  394. rows = self.env.cr.fetchall()
  395. tax_ids_by_journal_id[report_journal.id].extend(
  396. [row[0] for row in rows if row[0]]
  397. )
  398. sql = """
  399. INSERT INTO report_journal_ledger_journal_tax_line (
  400. create_uid,
  401. create_date,
  402. report_id,
  403. report_journal_ledger_id,
  404. tax_id,
  405. tax_name,
  406. tax_code,
  407. base_debit,
  408. base_credit,
  409. tax_debit,
  410. tax_credit
  411. )
  412. SELECT
  413. %s as create_uid,
  414. NOW() as create_date,
  415. %s as report_id,
  416. %s as report_journal_ledger_id,
  417. %s as tax_id,
  418. at.name as tax_name,
  419. at.description as tax_code,
  420. (
  421. SELECT sum(debit)
  422. FROM report_journal_ledger_move_line jrqml2
  423. WHERE jrqml2.report_journal_ledger_id = %s
  424. AND (
  425. SELECT
  426. count(*)
  427. FROM
  428. account_move_line_account_tax_rel aml_at_rel
  429. WHERE
  430. aml_at_rel.account_move_line_id =
  431. jrqml2.move_line_id
  432. AND
  433. aml_at_rel.account_tax_id = %s
  434. ) > 0
  435. ) as base_debit,
  436. (
  437. SELECT sum(credit)
  438. FROM report_journal_ledger_move_line jrqml2
  439. WHERE jrqml2.report_journal_ledger_id = %s
  440. AND (
  441. SELECT
  442. count(*)
  443. FROM
  444. account_move_line_account_tax_rel aml_at_rel
  445. WHERE
  446. aml_at_rel.account_move_line_id =
  447. jrqml2.move_line_id
  448. AND
  449. aml_at_rel.account_tax_id = %s
  450. ) > 0
  451. ) as base_credit,
  452. (
  453. SELECT sum(debit)
  454. FROM report_journal_ledger_move_line jrqml2
  455. WHERE jrqml2.report_journal_ledger_id = %s
  456. AND jrqml2.tax_id = %s
  457. ) as tax_debit,
  458. (
  459. SELECT sum(credit)
  460. FROM report_journal_ledger_move_line jrqml2
  461. WHERE jrqml2.report_journal_ledger_id = %s
  462. AND jrqml2.tax_id = %s
  463. ) as tax_credit
  464. FROM
  465. report_journal_ledger_journal rjqj
  466. LEFT JOIN
  467. account_tax at
  468. on (at.id = %s)
  469. WHERE
  470. rjqj.id = %s
  471. """
  472. for report_journal_ledger_id in tax_ids_by_journal_id:
  473. tax_ids = tax_ids_by_journal_id[report_journal_ledger_id]
  474. for tax_id in tax_ids:
  475. params = (
  476. self.env.uid,
  477. self.id,
  478. report_journal_ledger_id,
  479. tax_id,
  480. report_journal_ledger_id,
  481. tax_id,
  482. report_journal_ledger_id,
  483. tax_id,
  484. report_journal_ledger_id,
  485. tax_id,
  486. report_journal_ledger_id,
  487. tax_id,
  488. tax_id,
  489. report_journal_ledger_id,
  490. )
  491. self.env.cr.execute(sql, params)
  492. def _update_journal_report_total_values(self):
  493. self.ensure_one()
  494. sql = """
  495. UPDATE
  496. report_journal_ledger_journal rjqj
  497. SET
  498. debit = (
  499. SELECT sum(rjqml.debit)
  500. FROM report_journal_ledger_move_line rjqml
  501. WHERE rjqml.report_journal_ledger_id = rjqj.id
  502. ),
  503. credit = (
  504. SELECT sum(rjqml.credit)
  505. FROM report_journal_ledger_move_line rjqml
  506. WHERE rjqml.report_journal_ledger_id = rjqj.id
  507. )
  508. WHERE
  509. rjqj.report_id = %s
  510. """
  511. self.env.cr.execute(sql, (self.id,))
  512. def print_report(self, report_type):
  513. self.ensure_one()
  514. if report_type == "xlsx":
  515. report_name = "a_f_r.report_journal_ledger_xlsx"
  516. else:
  517. report_name = "account_financial_report." "report_journal_ledger_qweb"
  518. return (
  519. self.env["ir.actions.report"]
  520. .search(
  521. [("report_name", "=", report_name), ("report_type", "=", report_type)],
  522. limit=1,
  523. )
  524. .report_action(self, config=False)
  525. )
  526. def _get_html(self):
  527. result = {}
  528. rcontext = {}
  529. context = dict(self.env.context)
  530. report = self.browse(context.get("active_id"))
  531. if report:
  532. rcontext["o"] = report
  533. result["html"] = self.env.ref(
  534. "account_financial_report.report_journal_ledger"
  535. ).render(rcontext)
  536. return result
  537. @api.model
  538. def get_html(self, given_context=None):
  539. return self._get_html()
  540. @api.model
  541. def _transient_vacuum(self, force=False):
  542. """Remove journal ledger subtables first for avoiding a costly
  543. ondelete operation.
  544. """
  545. # Next 3 lines adapted from super method for mimicking behavior
  546. cls = type(self)
  547. if not force and (cls._transient_check_count < 21):
  548. return True # no vacuum cleaning this time
  549. self.env.cr.execute("DELETE FROM report_journal_ledger_move_line")
  550. self.env.cr.execute("DELETE FROM report_journal_ledger_move")
  551. return super(ReportJournalLedger, self)._transient_vacuum(force=force)
  552. class ReportJournalLedgerJournal(models.TransientModel):
  553. _name = "report_journal_ledger_journal"
  554. _inherit = "account_financial_report_abstract"
  555. name = fields.Char(required=True,)
  556. code = fields.Char()
  557. report_id = fields.Many2one(
  558. comodel_name="report_journal_ledger", required=True, ondelete="cascade"
  559. )
  560. journal_id = fields.Many2one(
  561. comodel_name="account.journal", required=True, ondelete="cascade",
  562. )
  563. report_move_ids = fields.One2many(
  564. comodel_name="report_journal_ledger_move",
  565. inverse_name="report_journal_ledger_id",
  566. )
  567. report_tax_line_ids = fields.One2many(
  568. comodel_name="report_journal_ledger_journal_tax_line",
  569. inverse_name="report_journal_ledger_id",
  570. )
  571. debit = fields.Float(digits=DIGITS,)
  572. credit = fields.Float(digits=DIGITS,)
  573. company_id = fields.Many2one(
  574. comodel_name="res.company", required=True, ondelete="cascade"
  575. )
  576. currency_id = fields.Many2one(comodel_name="res.currency",)
  577. class ReportJournalLedgerMove(models.TransientModel):
  578. _name = "report_journal_ledger_move"
  579. _inherit = "account_financial_report_abstract"
  580. report_id = fields.Many2one(
  581. comodel_name="report_journal_ledger", required=True, ondelete="cascade"
  582. )
  583. report_journal_ledger_id = fields.Many2one(
  584. comodel_name="report_journal_ledger_journal", required=True, ondelete="cascade",
  585. )
  586. move_id = fields.Many2one(
  587. comodel_name="account.move", required=True, ondelete="cascade",
  588. )
  589. report_move_line_ids = fields.One2many(
  590. comodel_name="report_journal_ledger_move_line", inverse_name="report_move_id",
  591. )
  592. name = fields.Char()
  593. company_id = fields.Many2one(
  594. comodel_name="res.company", required=True, ondelete="cascade"
  595. )
  596. class ReportJournalLedgerMoveLine(models.TransientModel):
  597. _name = "report_journal_ledger_move_line"
  598. _inherit = "account_financial_report_abstract"
  599. _order = "partner_id desc, account_id desc"
  600. report_id = fields.Many2one(
  601. comodel_name="report_journal_ledger", required=True, ondelete="cascade"
  602. )
  603. report_journal_ledger_id = fields.Many2one(
  604. comodel_name="report_journal_ledger_journal", required=True, ondelete="cascade",
  605. )
  606. report_move_id = fields.Many2one(
  607. comodel_name="report_journal_ledger_move", required=True, ondelete="cascade",
  608. )
  609. move_line_id = fields.Many2one(
  610. comodel_name="account.move.line", required=True, ondelete="cascade",
  611. )
  612. account_id = fields.Many2one(comodel_name="account.account", string="Account ID",)
  613. account = fields.Char()
  614. account_code = fields.Char()
  615. account_type = fields.Char()
  616. partner = fields.Char()
  617. partner_id = fields.Many2one(comodel_name="res.partner", string="Partner ID",)
  618. date = fields.Date()
  619. entry = fields.Char()
  620. label = fields.Char()
  621. debit = fields.Float(digits=DIGITS,)
  622. credit = fields.Float(digits=DIGITS,)
  623. company_currency_id = fields.Many2one(comodel_name="res.currency",)
  624. amount_currency = fields.Monetary(currency_field="currency_id",)
  625. currency_id = fields.Many2one(comodel_name="res.currency",)
  626. currency_name = fields.Char()
  627. taxes_description = fields.Char()
  628. tax_id = fields.Many2one(comodel_name="account.tax")
  629. company_id = fields.Many2one(
  630. comodel_name="res.company", required=True, ondelete="cascade"
  631. )
  632. class ReportJournalLedgerReportTaxLine(models.TransientModel):
  633. _name = "report_journal_ledger_report_tax_line"
  634. _inherit = "account_financial_report_abstract"
  635. _order = "tax_code"
  636. report_id = fields.Many2one(
  637. comodel_name="report_journal_ledger", required=True, ondelete="cascade"
  638. )
  639. tax_id = fields.Many2one(comodel_name="account.tax")
  640. tax_name = fields.Char()
  641. tax_code = fields.Char()
  642. base_debit = fields.Float(digits=DIGITS,)
  643. base_credit = fields.Float(digits=DIGITS,)
  644. base_balance = fields.Float(digits=DIGITS, compute="_compute_base_balance",)
  645. tax_debit = fields.Float(digits=DIGITS,)
  646. tax_credit = fields.Float(digits=DIGITS,)
  647. tax_balance = fields.Float(digits=DIGITS, compute="_compute_tax_balance")
  648. def _compute_base_balance(self):
  649. for rec in self:
  650. rec.base_balance = rec.base_debit - rec.base_credit
  651. def _compute_tax_balance(self):
  652. for rec in self:
  653. rec.tax_balance = rec.tax_debit - rec.tax_credit
  654. class ReportJournalLedgerJournalTaxLine(models.TransientModel):
  655. _name = "report_journal_ledger_journal_tax_line"
  656. _inherit = "report_journal_ledger_report_tax_line"
  657. _order = "tax_code"
  658. report_journal_ledger_id = fields.Many2one(
  659. comodel_name="report_journal_ledger_journal", required=True, ondelete="cascade",
  660. )