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.

168 lines
7.0 KiB

  1. # Copyright 2018 ForgeFlow, S.L. (https://www.forgeflow.com)
  2. # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
  3. from odoo import api, models
  4. class OutstandingStatement(models.AbstractModel):
  5. """Model of Outstanding Statement"""
  6. _inherit = "statement.common"
  7. _name = "report.partner_statement.outstanding_statement"
  8. _description = "Partner Outstanding Statement"
  9. def _display_lines_sql_q1(self, partners, date_end, account_type):
  10. partners = tuple(partners)
  11. return str(
  12. self._cr.mogrify(
  13. """
  14. SELECT l.id, m.name AS move_id, l.partner_id, l.date, l.name,
  15. l.blocked, l.currency_id, l.company_id,
  16. CASE WHEN l.ref IS NOT NULL THEN l.ref ELSE m.ref END as ref,
  17. CASE WHEN (l.currency_id is not null AND l.amount_currency > 0.0)
  18. THEN avg(l.amount_currency)
  19. ELSE avg(l.debit)
  20. END as debit,
  21. CASE WHEN (l.currency_id is not null AND l.amount_currency < 0.0)
  22. THEN avg(-l.amount_currency)
  23. ELSE avg(l.credit)
  24. END as credit,
  25. (abs(COALESCE(l.balance, 0.0)) + sum(
  26. coalesce(pr.pr_sign, 0.0) * coalesce(pr.amount, 0.0))
  27. ) * sign(COALESCE(l.balance, 0.0)) AS open_amount,
  28. (abs(COALESCE(l.amount_currency, 0.0)) + sum(
  29. coalesce(pr.pr_sign, 0.0) * CASE
  30. WHEN pr.currency_id IS NOT NULL AND pr.currency_id = l.currency_id
  31. THEN coalesce(pr.amount_currency, 0.0)
  32. WHEN cur.id IS NOT NULL AND ROUND(
  33. abs(COALESCE(l.balance, 0.0)), cur.decimal_places) > 0.0
  34. THEN ROUND(coalesce(pr.amount, 0.0) *
  35. COALESCE(l.amount_currency, 0.0) / NULLIF(l.balance, 0.0),
  36. cur.decimal_places)
  37. ELSE ROUND(coalesce(pr.amount, 0.0) *
  38. COALESCE((
  39. SELECT r.rate FROM res_currency_rate r
  40. JOIN account_move_line aml
  41. ON pr.credit_move_id = aml.id
  42. WHERE r.currency_id = l.currency_id
  43. AND r.name <= aml.date
  44. AND (r.company_id IS NULL
  45. OR r.company_id = l.company_id)
  46. ORDER BY r.company_id, r.name DESC LIMIT 1), 1.0),
  47. cur.decimal_places)
  48. END)
  49. ) * sign(COALESCE(l.amount_currency, 0.0)) AS open_amount_currency,
  50. CASE WHEN l.date_maturity is null
  51. THEN l.date
  52. ELSE l.date_maturity
  53. END as date_maturity
  54. FROM (
  55. SELECT l.*, CASE
  56. WHEN l.debit = 0.0 AND l.credit = 0.0 AND l.currency_id IS NOT NULL
  57. AND ROUND(COALESCE(l.amount_currency, 0.0),
  58. cur.decimal_places) > 0.0 THEN 1
  59. WHEN l.debit = 0.0 AND l.credit = 0.0 AND l.currency_id IS NOT NULL
  60. AND ROUND(COALESCE(l.amount_currency, 0.0),
  61. cur.decimal_places) < 0.0 THEN -1
  62. WHEN l.balance > 0.0 THEN 1 ELSE -1 END as sign
  63. FROM account_move_line l
  64. LEFT JOIN res_currency cur ON cur.id = l.currency_id
  65. ) l
  66. JOIN account_move m ON l.move_id = m.id
  67. LEFT JOIN res_currency cur ON cur.id = l.currency_id
  68. LEFT JOIN LATERAL (SELECT pr.*,
  69. CASE WHEN pr.credit_move_id = l.id THEN l.sign
  70. ELSE -l.sign END AS pr_sign
  71. FROM account_partial_reconcile pr
  72. WHERE pr.max_date <= %(date_end)s AND (
  73. (pr.debit_move_id = l.id) OR (pr.credit_move_id = l.id))
  74. ) as pr ON TRUE
  75. WHERE l.partner_id IN %(partners)s
  76. AND l.account_internal_type = %(account_type)s
  77. AND (
  78. (pr.id IS NOT NULL AND pr.max_date <= %(date_end)s) OR
  79. (pr.id IS NULL)
  80. ) AND l.date <= %(date_end)s AND m.state IN ('posted')
  81. GROUP BY l.id, l.partner_id, m.name, l.date, l.date_maturity, l.name,
  82. CASE WHEN l.ref IS NOT NULL THEN l.ref ELSE m.ref END,
  83. l.blocked, l.currency_id, l.balance, l.amount_currency, l.company_id
  84. """,
  85. locals(),
  86. ),
  87. "utf-8",
  88. )
  89. def _display_lines_sql_q2(self):
  90. return str(
  91. self._cr.mogrify(
  92. """
  93. SELECT Q1.partner_id, Q1.currency_id, Q1.move_id,
  94. Q1.date, Q1.date_maturity, Q1.debit, Q1.credit,
  95. Q1.name, Q1.ref, Q1.blocked, Q1.company_id,
  96. CASE WHEN Q1.currency_id is not null
  97. THEN Q1.open_amount_currency
  98. ELSE Q1.open_amount
  99. END as open_amount
  100. FROM Q1
  101. """,
  102. locals(),
  103. ),
  104. "utf-8",
  105. )
  106. def _display_lines_sql_q3(self, company_id):
  107. return str(
  108. self._cr.mogrify(
  109. """
  110. SELECT Q2.partner_id, Q2.move_id, Q2.date, Q2.date_maturity,
  111. Q2.name, Q2.ref, Q2.debit, Q2.credit,
  112. Q2.debit-Q2.credit AS amount, blocked,
  113. COALESCE(Q2.currency_id, c.currency_id) AS currency_id,
  114. Q2.open_amount
  115. FROM Q2
  116. JOIN res_company c ON (c.id = Q2.company_id)
  117. JOIN res_currency cur ON cur.id = COALESCE(Q2.currency_id, c.currency_id)
  118. WHERE c.id = %(company_id)s AND
  119. round(Q2.open_amount, cur.decimal_places) != 0.0
  120. """,
  121. locals(),
  122. ),
  123. "utf-8",
  124. )
  125. def _get_account_display_lines(
  126. self, company_id, partner_ids, date_start, date_end, account_type
  127. ):
  128. res = dict(map(lambda x: (x, []), partner_ids))
  129. partners = tuple(partner_ids)
  130. # pylint: disable=E8103
  131. self.env.cr.execute(
  132. """
  133. WITH Q1 as (%s),
  134. Q2 AS (%s),
  135. Q3 AS (%s)
  136. SELECT partner_id, currency_id, move_id, date, date_maturity, debit,
  137. credit, amount, open_amount, name, ref, blocked
  138. FROM Q3
  139. ORDER BY date, date_maturity, move_id"""
  140. % (
  141. self._display_lines_sql_q1(partners, date_end, account_type),
  142. self._display_lines_sql_q2(),
  143. self._display_lines_sql_q3(company_id),
  144. )
  145. )
  146. for row in self.env.cr.dictfetchall():
  147. res[row.pop("partner_id")].append(row)
  148. return res
  149. @api.model
  150. def _get_report_values(self, docids, data=None):
  151. if not data:
  152. data = {}
  153. if "company_id" not in data:
  154. wiz = self.env["outstanding.statement.wizard"].with_context(
  155. active_ids=docids, model="res.partner"
  156. )
  157. data.update(wiz.create({})._prepare_statement())
  158. data["amount_field"] = "open_amount"
  159. return super()._get_report_values(docids, data)