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.

376 lines
14 KiB

  1. # Copyright 2019-20 ForgeFlow S.L. (https://www.forgeflow.com)
  2. # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
  3. import itertools
  4. import operator
  5. from odoo import api, models
  6. class JournalLedgerReport(models.AbstractModel):
  7. _name = "report.account_financial_report.journal_ledger"
  8. def _get_journal_ledger_data(self, journal):
  9. return {
  10. "id": journal.id,
  11. "name": journal.name,
  12. "currency_id": journal.currency_id.id,
  13. "currency_name": journal.currency_id
  14. and journal.currency_id.name
  15. or journal.company_id.currency_id.name,
  16. "debit": 0.0,
  17. "credit": 0.0,
  18. }
  19. def _get_journal_ledgers_domain(self, wizard, journal_ids, company):
  20. domain = []
  21. if company:
  22. domain += [("company_id", "=", company.id)]
  23. if journal_ids:
  24. domain += [("id", "in", journal_ids)]
  25. return domain
  26. def _get_journal_ledgers(self, wizard, journal_ids, company):
  27. journals = self.env["account.journal"].search(
  28. self._get_journal_ledgers_domain(wizard, journal_ids, company),
  29. order="name asc",
  30. )
  31. journal_ledgers_data = []
  32. for journal in journals:
  33. journal_ledgers_data.append(self._get_journal_ledger_data(journal))
  34. return journal_ledgers_data
  35. def _get_moves_domain(self, wizard, journal_ids):
  36. domain = [
  37. ("journal_id", "in", journal_ids),
  38. ("date", ">=", wizard.date_from),
  39. ("date", "<=", wizard.date_to),
  40. ]
  41. if wizard.move_target != "all":
  42. domain += [("state", "=", wizard.move_target)]
  43. return domain
  44. def _get_moves_order(self, wizard, journal_ids):
  45. search_order = ""
  46. if wizard.sort_option == "move_name":
  47. search_order = "name asc"
  48. elif wizard.sort_option == "date":
  49. search_order = "date asc, name asc"
  50. return search_order
  51. def _get_moves_data(self, move):
  52. return {
  53. "move_id": move.id,
  54. "journal_id": move.journal_id.id,
  55. "entry": move.name,
  56. }
  57. def _get_moves(self, wizard, journal_ids):
  58. moves = self.env["account.move"].search(
  59. self._get_moves_domain(wizard, journal_ids),
  60. order=self._get_moves_order(wizard, journal_ids),
  61. )
  62. Moves = []
  63. move_data = {}
  64. for move in moves:
  65. move_data[move.id] = self._get_moves_data(move)
  66. Moves.append(move_data[move.id])
  67. return moves.ids, Moves, move_data
  68. def _get_move_lines_domain(self, move_ids, wizard, journal_ids):
  69. return [
  70. ("move_id", "in", move_ids),
  71. ]
  72. def _get_move_lines_order(self, move_ids, wizard, journal_ids):
  73. return ""
  74. def _get_move_lines_data(self, ml, wizard, ml_taxes):
  75. base_debit = (
  76. base_credit
  77. ) = tax_debit = tax_credit = base_balance = tax_balance = 0.0
  78. if ml.tax_exigible:
  79. base_debit = ml_taxes and ml.debit or 0.0
  80. base_credit = ml_taxes and ml.credit or 0.0
  81. base_balance = ml_taxes and ml.balance or 0.0
  82. tax_debit = ml.tax_line_id and ml.debit or 0.0
  83. tax_credit = ml.tax_line_id and ml.credit or 0.0
  84. tax_balance = ml.tax_line_id and ml.balance or 0.0
  85. return {
  86. "move_line_id": ml.id,
  87. "move_id": ml.move_id.id,
  88. "date": ml.date,
  89. "journal_id": ml.journal_id.id,
  90. "account_id": ml.account_id.id,
  91. "partner_id": ml.partner_id.id,
  92. "label": ml.name,
  93. "debit": ml.debit,
  94. "credit": ml.credit,
  95. "company_currency_id": ml.company_currency_id.id,
  96. "amount_currency": ml.amount_currency,
  97. "currency_id": ml.currency_id.id,
  98. "tax_line_id": ml.tax_line_id.id,
  99. "tax_ids": list(ml_taxes.keys()),
  100. "base_debit": base_debit,
  101. "base_credit": base_credit,
  102. "tax_debit": tax_debit,
  103. "tax_credit": tax_credit,
  104. "base_balance": base_balance,
  105. "tax_balance": tax_balance,
  106. }
  107. def _get_account_data(self, accounts):
  108. data = {}
  109. for account in accounts:
  110. data[account.id] = self._get_account_id_data(account)
  111. return data
  112. def _get_account_id_data(self, account):
  113. return {
  114. "name": account.name,
  115. "code": account.code,
  116. "internal_type": account.internal_type,
  117. }
  118. def _get_partner_data(self, partners):
  119. data = {}
  120. for partner in partners:
  121. data[partner.id] = self._get_partner_id_data(partner)
  122. return data
  123. def _get_partner_id_data(self, partner):
  124. return {
  125. "name": partner.name,
  126. }
  127. def _get_currency_data(self, currencies):
  128. data = {}
  129. for currency in currencies:
  130. data[currency.id] = self._get_currency_id_data(currency)
  131. return data
  132. def _get_currency_id_data(self, currency):
  133. return {
  134. "name": currency.name,
  135. }
  136. def _get_tax_line_data(self, taxes):
  137. data = {}
  138. for tax in taxes:
  139. data[tax.id] = self._get_tax_line_id_data(tax)
  140. return data
  141. def _get_tax_line_id_data(self, tax):
  142. return {
  143. "name": tax.name,
  144. "description": tax.description,
  145. }
  146. def _get_query_taxes(self):
  147. return """
  148. SELECT aml_at_rel.account_move_line_id, aml_at_rel.account_tax_id,
  149. at.description, at.name
  150. FROM account_move_line_account_tax_rel AS aml_at_rel
  151. LEFT JOIN
  152. account_tax AS at on (at.id = aml_at_rel.account_tax_id)
  153. WHERE account_move_line_id IN %(move_line_ids)s
  154. """
  155. def _get_query_taxes_params(self, move_lines):
  156. return {
  157. "move_line_ids": tuple(move_lines.ids),
  158. }
  159. def _get_move_lines(self, move_ids, wizard, journal_ids):
  160. move_lines = self.env["account.move.line"].search(
  161. self._get_move_lines_domain(move_ids, wizard, journal_ids),
  162. order=self._get_move_lines_order(move_ids, wizard, journal_ids),
  163. )
  164. # Get the taxes ids for the move lines
  165. query_taxes_params = self._get_query_taxes_params(move_lines)
  166. query_taxes = self._get_query_taxes()
  167. move_line_ids_taxes_data = {}
  168. self.env.cr.execute(query_taxes, query_taxes_params)
  169. # Fetch the taxes associated to the move line
  170. for (
  171. move_line_id,
  172. account_tax_id,
  173. tax_description,
  174. tax_name,
  175. ) in self.env.cr.fetchall():
  176. if move_line_id not in move_line_ids_taxes_data.keys():
  177. move_line_ids_taxes_data[move_line_id] = {}
  178. move_line_ids_taxes_data[move_line_id][account_tax_id] = {
  179. "name": tax_name,
  180. "description": tax_description,
  181. }
  182. Move_Lines = {}
  183. accounts = self.env["account.account"]
  184. partners = self.env["res.partner"]
  185. currencies = self.env["res.currency"]
  186. tax_lines = self.env["account.tax"]
  187. for ml in move_lines:
  188. if ml.account_id not in accounts:
  189. accounts |= ml.account_id
  190. if ml.partner_id not in partners:
  191. partners |= ml.partner_id
  192. if ml.currency_id not in currencies:
  193. currencies |= ml.currency_id
  194. if ml.tax_line_id not in tax_lines:
  195. tax_lines |= ml.tax_line_id
  196. if ml.move_id.id not in Move_Lines.keys():
  197. Move_Lines[ml.move_id.id] = []
  198. taxes = (
  199. ml.id in move_line_ids_taxes_data.keys()
  200. and move_line_ids_taxes_data[ml.id]
  201. or {}
  202. )
  203. Move_Lines[ml.move_id.id].append(
  204. self._get_move_lines_data(ml, wizard, taxes)
  205. )
  206. account_ids_data = self._get_account_data(accounts)
  207. partner_ids_data = self._get_partner_data(partners)
  208. currency_ids_data = self._get_currency_data(currencies)
  209. tax_line_ids_data = self._get_tax_line_data(tax_lines)
  210. return (
  211. move_lines.ids,
  212. Move_Lines,
  213. account_ids_data,
  214. partner_ids_data,
  215. currency_ids_data,
  216. tax_line_ids_data,
  217. move_line_ids_taxes_data,
  218. )
  219. def _get_journal_tax_lines(self, wizard, moves_data):
  220. journals_taxes_data = {}
  221. for move_data in moves_data:
  222. report_move_lines = move_data["report_move_lines"]
  223. for report_move_line in report_move_lines:
  224. ml_data = report_move_line
  225. tax_ids = []
  226. if ml_data["tax_line_id"]:
  227. tax_ids.append(ml_data["tax_line_id"])
  228. if ml_data["tax_ids"]:
  229. tax_ids += ml_data["tax_ids"]
  230. tax_ids = list(set(tax_ids))
  231. journal_id = ml_data["journal_id"]
  232. if journal_id not in journals_taxes_data.keys():
  233. journals_taxes_data[journal_id] = {}
  234. taxes = self.env["account.tax"].browse(tax_ids)
  235. for tax in taxes:
  236. if tax.id not in journals_taxes_data[journal_id]:
  237. journals_taxes_data[journal_id][tax.id] = {
  238. "base_debit": 0.0,
  239. "base_credit": 0.0,
  240. "base_balance": 0.0,
  241. "tax_debit": 0.0,
  242. "tax_credit": 0.0,
  243. "tax_balance": 0.0,
  244. "tax_name": tax.name,
  245. "tax_code": tax.description,
  246. }
  247. field_keys = [
  248. "base_debit",
  249. "base_credit",
  250. "base_balance",
  251. "tax_debit",
  252. "tax_credit",
  253. "tax_balance",
  254. ]
  255. for field_key in field_keys:
  256. journals_taxes_data[journal_id][tax.id][field_key] += ml_data[
  257. field_key
  258. ]
  259. journals_taxes_data_2 = {}
  260. for journal_id in journals_taxes_data.keys():
  261. journals_taxes_data_2[journal_id] = []
  262. for tax_id in journals_taxes_data[journal_id].keys():
  263. journals_taxes_data_2[journal_id] += [
  264. journals_taxes_data[journal_id][tax_id]
  265. ]
  266. return journals_taxes_data_2
  267. @api.multi
  268. def _get_report_values(self, docids, data):
  269. wizard_id = data["wizard_id"]
  270. wizard = self.env["journal.ledger.report.wizard"].browse(wizard_id)
  271. company = self.env["res.company"].browse(data["company_id"])
  272. journal_ids = data["journal_ids"]
  273. journal_ledgers_data = self._get_journal_ledgers(wizard, journal_ids, company)
  274. move_ids, moves_data, move_ids_data = self._get_moves(wizard, journal_ids)
  275. journal_moves_data = {}
  276. for key, items in itertools.groupby(
  277. moves_data, operator.itemgetter("journal_id")
  278. ):
  279. if key not in journal_moves_data.keys():
  280. journal_moves_data[key] = []
  281. journal_moves_data[key] += list(items)
  282. move_lines_data = (
  283. account_ids_data
  284. ) = (
  285. partner_ids_data
  286. ) = currency_ids_data = tax_line_ids_data = move_line_ids_taxes_data = {}
  287. if move_ids:
  288. (
  289. move_line_ids,
  290. move_lines_data,
  291. account_ids_data,
  292. partner_ids_data,
  293. currency_ids_data,
  294. tax_line_ids_data,
  295. move_line_ids_taxes_data,
  296. ) = self._get_move_lines(move_ids, wizard, journal_ids)
  297. for move_data in moves_data:
  298. move_id = move_data["move_id"]
  299. move_data["report_move_lines"] = []
  300. if move_id in move_lines_data.keys():
  301. move_data["report_move_lines"] += move_lines_data[move_id]
  302. journals_taxes_data = {}
  303. if moves_data:
  304. journals_taxes_data = self._get_journal_tax_lines(wizard, moves_data)
  305. for journal_ledger_data in journal_ledgers_data:
  306. journal_id = journal_ledger_data["id"]
  307. journal_ledger_data["tax_lines"] = journals_taxes_data.get(journal_id, [])
  308. journal_totals = {}
  309. for move_id in move_lines_data.keys():
  310. for move_line_data in move_lines_data[move_id]:
  311. journal_id = move_line_data["journal_id"]
  312. if journal_id not in journal_totals.keys():
  313. journal_totals[journal_id] = {
  314. "debit": 0.0,
  315. "credit": 0.0,
  316. }
  317. for item in ["debit", "credit"]:
  318. journal_totals[journal_id][item] += move_line_data[item]
  319. for journal_ledger_data in journal_ledgers_data:
  320. journal_id = journal_ledger_data["id"]
  321. if journal_id in journal_moves_data.keys():
  322. journal_ledger_data["report_moves"] = journal_moves_data[journal_id]
  323. else:
  324. journal_ledger_data["report_moves"] = []
  325. if journal_id in journal_totals.keys():
  326. for item in ["debit", "credit"]:
  327. journal_ledger_data[item] += journal_totals[journal_id][item]
  328. return {
  329. "doc_ids": [wizard_id],
  330. "doc_model": "journal.ledger.report.wizard",
  331. "docs": self.env["journal.ledger.report.wizard"].browse(wizard_id),
  332. "group_option": data["group_option"],
  333. "foreign_currency": data["foreign_currency"],
  334. "with_account_name": data["with_account_name"],
  335. "company_name": company.display_name,
  336. "currency_name": company.currency_id.name,
  337. "date_from": data["date_from"],
  338. "date_to": data["date_to"],
  339. "move_target": data["move_target"],
  340. "account_ids_data": account_ids_data,
  341. "partner_ids_data": partner_ids_data,
  342. "currency_ids_data": currency_ids_data,
  343. "move_ids_data": move_ids_data,
  344. "tax_line_data": tax_line_ids_data,
  345. "move_line_ids_taxes_data": move_line_ids_taxes_data,
  346. "Journal_Ledgers": journal_ledgers_data,
  347. "Moves": moves_data,
  348. }