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.

803 lines
32 KiB

  1. # © 2016 Julien Coux (Camptocamp)
  2. # Copyright 2020 ForgeFlow S.L. (https://www.forgeflow.com)
  3. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
  4. import calendar
  5. import datetime
  6. import operator
  7. from odoo import _, api, models
  8. class GeneralLedgerReport(models.AbstractModel):
  9. _name = "report.account_financial_report.general_ledger"
  10. _description = "General Ledger Report"
  11. def _get_accounts_data(self, account_ids):
  12. accounts = self.env["account.account"].browse(account_ids)
  13. accounts_data = {}
  14. for account in accounts:
  15. accounts_data.update(
  16. {
  17. account.id: {
  18. "id": account.id,
  19. "code": account.code,
  20. "name": account.name,
  21. "group_id": account.group_id.id,
  22. "currency_id": account.currency_id or False,
  23. "currency_name": account.currency_id.name,
  24. "centralized": account.centralized,
  25. }
  26. }
  27. )
  28. return accounts_data
  29. def _get_journals_data(self, journals_ids):
  30. journals = self.env["account.journal"].browse(journals_ids)
  31. journals_data = {}
  32. for journal in journals:
  33. journals_data.update({journal.id: {"id": journal.id, "code": journal.code}})
  34. return journals_data
  35. def _get_tags_data(self, tags_ids):
  36. tags = self.env["account.analytic.tag"].browse(tags_ids)
  37. tags_data = {}
  38. for tag in tags:
  39. tags_data.update({tag.id: {"name": tag.name}})
  40. return tags_data
  41. def _get_taxes_data(self, taxes_ids):
  42. taxes = self.env["account.tax"].browse(taxes_ids)
  43. taxes_data = {}
  44. for tax in taxes:
  45. taxes_data.update(
  46. {
  47. tax.id: {
  48. "id": tax.id,
  49. "amount": tax.amount,
  50. "amount_type": tax.amount_type,
  51. "display_name": tax.display_name,
  52. }
  53. }
  54. )
  55. if tax.amount_type == "percent" or tax.amount_type == "division":
  56. taxes_data[tax.id]["string"] = "%"
  57. else:
  58. taxes_data[tax.id]["string"] = ""
  59. taxes_data[tax.id]["tax_name"] = (
  60. tax.display_name
  61. + " ("
  62. + str(tax.amount)
  63. + taxes_data[tax.id]["string"]
  64. + ")"
  65. )
  66. return taxes_data
  67. def _get_acc_prt_accounts_ids(self, company_id):
  68. accounts_domain = [
  69. ("company_id", "=", company_id),
  70. ("internal_type", "in", ["receivable", "payable"]),
  71. ]
  72. acc_prt_accounts = self.env["account.account"].search(accounts_domain)
  73. return acc_prt_accounts.ids
  74. def _get_initial_balances_bs_ml_domain(
  75. self, account_ids, company_id, date_from, base_domain, acc_prt=False
  76. ):
  77. accounts_domain = [
  78. ("company_id", "=", company_id),
  79. ("user_type_id.include_initial_balance", "=", True),
  80. ]
  81. if account_ids:
  82. accounts_domain += [("id", "in", account_ids)]
  83. domain = []
  84. domain += base_domain
  85. domain += [("date", "<", date_from)]
  86. accounts = self.env["account.account"].search(accounts_domain)
  87. domain += [("account_id", "in", accounts.ids)]
  88. if acc_prt:
  89. domain += [("account_id.internal_type", "in", ["receivable", "payable"])]
  90. return domain
  91. def _get_initial_balances_pl_ml_domain(
  92. self, account_ids, company_id, date_from, fy_start_date, base_domain
  93. ):
  94. accounts_domain = [
  95. ("company_id", "=", company_id),
  96. ("user_type_id.include_initial_balance", "=", False),
  97. ]
  98. if account_ids:
  99. accounts_domain += [("id", "in", account_ids)]
  100. domain = []
  101. domain += base_domain
  102. domain += [("date", "<", date_from), ("date", ">=", fy_start_date)]
  103. accounts = self.env["account.account"].search(accounts_domain)
  104. domain += [("account_id", "in", accounts.ids)]
  105. return domain
  106. def _get_accounts_initial_balance(self, initial_domain_bs, initial_domain_pl):
  107. gl_initial_acc_bs = self.env["account.move.line"].read_group(
  108. domain=initial_domain_bs,
  109. fields=["account_id", "debit", "credit", "balance", "amount_currency"],
  110. groupby=["account_id"],
  111. )
  112. gl_initial_acc_pl = self.env["account.move.line"].read_group(
  113. domain=initial_domain_pl,
  114. fields=["account_id", "debit", "credit", "balance", "amount_currency"],
  115. groupby=["account_id"],
  116. )
  117. gl_initial_acc = gl_initial_acc_bs + gl_initial_acc_pl
  118. return gl_initial_acc
  119. def _get_initial_balance_fy_pl_ml_domain(
  120. self, account_ids, company_id, fy_start_date, base_domain
  121. ):
  122. accounts_domain = [
  123. ("company_id", "=", company_id),
  124. ("user_type_id.include_initial_balance", "=", False),
  125. ]
  126. if account_ids:
  127. accounts_domain += [("id", "in", account_ids)]
  128. domain = []
  129. domain += base_domain
  130. domain += [("date", "<", fy_start_date)]
  131. accounts = self.env["account.account"].search(accounts_domain)
  132. domain += [("account_id", "in", accounts.ids)]
  133. return domain
  134. def _get_pl_initial_balance(
  135. self, account_ids, company_id, fy_start_date, foreign_currency, base_domain
  136. ):
  137. domain = self._get_initial_balance_fy_pl_ml_domain(
  138. account_ids, company_id, fy_start_date, base_domain
  139. )
  140. initial_balances = self.env["account.move.line"].read_group(
  141. domain=domain,
  142. fields=["account_id", "debit", "credit", "balance", "amount_currency"],
  143. groupby=["account_id"],
  144. )
  145. pl_initial_balance = {
  146. "debit": 0.0,
  147. "credit": 0.0,
  148. "balance": 0.0,
  149. "bal_curr": 0.0,
  150. }
  151. for initial_balance in initial_balances:
  152. pl_initial_balance["debit"] += initial_balance["debit"]
  153. pl_initial_balance["credit"] += initial_balance["credit"]
  154. pl_initial_balance["balance"] += initial_balance["balance"]
  155. pl_initial_balance["bal_curr"] += initial_balance["amount_currency"]
  156. return pl_initial_balance
  157. def _get_initial_balance_data(
  158. self,
  159. account_ids,
  160. partner_ids,
  161. company_id,
  162. date_from,
  163. foreign_currency,
  164. only_posted_moves,
  165. hide_account_at_0,
  166. unaffected_earnings_account,
  167. fy_start_date,
  168. analytic_tag_ids,
  169. cost_center_ids,
  170. ):
  171. base_domain = []
  172. if company_id:
  173. base_domain += [("company_id", "=", company_id)]
  174. if partner_ids:
  175. base_domain += [("partner_id", "in", partner_ids)]
  176. if only_posted_moves:
  177. base_domain += [("move_id.state", "=", "posted")]
  178. if analytic_tag_ids:
  179. base_domain += [("analytic_tag_ids", "in", analytic_tag_ids)]
  180. if cost_center_ids:
  181. base_domain += [("analytic_account_id", "in", cost_center_ids)]
  182. initial_domain_bs = self._get_initial_balances_bs_ml_domain(
  183. account_ids, company_id, date_from, base_domain
  184. )
  185. initial_domain_pl = self._get_initial_balances_pl_ml_domain(
  186. account_ids, company_id, date_from, fy_start_date, base_domain
  187. )
  188. gl_initial_acc = self._get_accounts_initial_balance(
  189. initial_domain_bs, initial_domain_pl
  190. )
  191. initial_domain_acc_prt = self._get_initial_balances_bs_ml_domain(
  192. account_ids, company_id, date_from, base_domain, acc_prt=True
  193. )
  194. gl_initial_acc_prt = self.env["account.move.line"].read_group(
  195. domain=initial_domain_acc_prt,
  196. fields=[
  197. "account_id",
  198. "partner_id",
  199. "debit",
  200. "credit",
  201. "balance",
  202. "amount_currency",
  203. ],
  204. groupby=["account_id", "partner_id"],
  205. lazy=False,
  206. )
  207. gen_ld_data = {}
  208. for gl in gl_initial_acc:
  209. acc_id = gl["account_id"][0]
  210. gen_ld_data[acc_id] = {}
  211. gen_ld_data[acc_id]["id"] = acc_id
  212. gen_ld_data[acc_id]["partners"] = False
  213. gen_ld_data[acc_id]["init_bal"] = {}
  214. gen_ld_data[acc_id]["init_bal"]["credit"] = gl["credit"]
  215. gen_ld_data[acc_id]["init_bal"]["debit"] = gl["debit"]
  216. gen_ld_data[acc_id]["init_bal"]["balance"] = gl["balance"]
  217. gen_ld_data[acc_id]["fin_bal"] = {}
  218. gen_ld_data[acc_id]["fin_bal"]["credit"] = gl["credit"]
  219. gen_ld_data[acc_id]["fin_bal"]["debit"] = gl["debit"]
  220. gen_ld_data[acc_id]["fin_bal"]["balance"] = gl["balance"]
  221. gen_ld_data[acc_id]["init_bal"]["bal_curr"] = gl["amount_currency"]
  222. gen_ld_data[acc_id]["fin_bal"]["bal_curr"] = gl["amount_currency"]
  223. partners_data = {}
  224. partners_ids = set()
  225. if gl_initial_acc_prt:
  226. for gl in gl_initial_acc_prt:
  227. if not gl["partner_id"]:
  228. prt_id = 0
  229. prt_name = "Missing Partner"
  230. else:
  231. prt_id = gl["partner_id"][0]
  232. prt_name = gl["partner_id"][1]
  233. prt_name = prt_name._value
  234. if prt_id not in partners_ids:
  235. partners_ids.add(prt_id)
  236. partners_data.update({prt_id: {"id": prt_id, "name": prt_name}})
  237. acc_id = gl["account_id"][0]
  238. gen_ld_data[acc_id][prt_id] = {}
  239. gen_ld_data[acc_id][prt_id]["id"] = prt_id
  240. gen_ld_data[acc_id]["partners"] = True
  241. gen_ld_data[acc_id][prt_id]["init_bal"] = {}
  242. gen_ld_data[acc_id][prt_id]["init_bal"]["credit"] = gl["credit"]
  243. gen_ld_data[acc_id][prt_id]["init_bal"]["debit"] = gl["debit"]
  244. gen_ld_data[acc_id][prt_id]["init_bal"]["balance"] = gl["balance"]
  245. gen_ld_data[acc_id][prt_id]["fin_bal"] = {}
  246. gen_ld_data[acc_id][prt_id]["fin_bal"]["credit"] = gl["credit"]
  247. gen_ld_data[acc_id][prt_id]["fin_bal"]["debit"] = gl["debit"]
  248. gen_ld_data[acc_id][prt_id]["fin_bal"]["balance"] = gl["balance"]
  249. gen_ld_data[acc_id][prt_id]["init_bal"]["bal_curr"] = gl[
  250. "amount_currency"
  251. ]
  252. gen_ld_data[acc_id][prt_id]["fin_bal"]["bal_curr"] = gl[
  253. "amount_currency"
  254. ]
  255. accounts_ids = list(gen_ld_data.keys())
  256. unaffected_id = unaffected_earnings_account
  257. if unaffected_id not in accounts_ids:
  258. accounts_ids.append(unaffected_id)
  259. self._initialize_account(gen_ld_data, unaffected_id, foreign_currency)
  260. pl_initial_balance = self._get_pl_initial_balance(
  261. account_ids, company_id, fy_start_date, foreign_currency, base_domain
  262. )
  263. gen_ld_data[unaffected_id]["init_bal"]["debit"] += pl_initial_balance["debit"]
  264. gen_ld_data[unaffected_id]["init_bal"]["credit"] += pl_initial_balance["credit"]
  265. gen_ld_data[unaffected_id]["init_bal"]["balance"] += pl_initial_balance[
  266. "balance"
  267. ]
  268. gen_ld_data[unaffected_id]["fin_bal"]["debit"] += pl_initial_balance["debit"]
  269. gen_ld_data[unaffected_id]["fin_bal"]["credit"] += pl_initial_balance["credit"]
  270. gen_ld_data[unaffected_id]["fin_bal"]["balance"] += pl_initial_balance[
  271. "balance"
  272. ]
  273. if foreign_currency:
  274. gen_ld_data[unaffected_id]["init_bal"]["bal_curr"] += pl_initial_balance[
  275. "bal_curr"
  276. ]
  277. gen_ld_data[unaffected_id]["fin_bal"]["bal_curr"] += pl_initial_balance[
  278. "bal_curr"
  279. ]
  280. return gen_ld_data, partners_data, partner_ids
  281. @api.model
  282. def _get_move_line_data(self, move_line):
  283. move_line_data = {
  284. "id": move_line["id"],
  285. "date": move_line["date"],
  286. "entry": move_line["move_id"][1],
  287. "entry_id": move_line["move_id"][0],
  288. "journal_id": move_line["journal_id"][0],
  289. "account_id": move_line["account_id"][0],
  290. "partner_id": move_line["partner_id"][0]
  291. if move_line["partner_id"]
  292. else False,
  293. "partner_name": move_line["partner_id"][1]
  294. if move_line["partner_id"]
  295. else "",
  296. "ref": "" if not move_line["ref"] else move_line["ref"],
  297. "name": "" if not move_line["name"] else move_line["name"],
  298. "tax_ids": move_line["tax_ids"],
  299. "debit": move_line["debit"],
  300. "credit": move_line["credit"],
  301. "balance": move_line["balance"],
  302. "bal_curr": move_line["amount_currency"],
  303. "rec_id": move_line["full_reconcile_id"][0]
  304. if move_line["full_reconcile_id"]
  305. else False,
  306. "rec_name": move_line["full_reconcile_id"][1]
  307. if move_line["full_reconcile_id"]
  308. else "",
  309. "tag_ids": move_line["analytic_tag_ids"],
  310. "currency_id": move_line["currency_id"],
  311. "analytic_account": move_line["analytic_account_id"][1]
  312. if move_line["analytic_account_id"]
  313. else "",
  314. "analytic_account_id": move_line["analytic_account_id"][0]
  315. if move_line["analytic_account_id"]
  316. else False,
  317. }
  318. if (
  319. move_line_data["ref"] == move_line_data["name"]
  320. or move_line_data["ref"] == ""
  321. ):
  322. ref_label = move_line_data["name"]
  323. elif move_line_data["name"] == "":
  324. ref_label = move_line_data["ref"]
  325. else:
  326. ref_label = move_line_data["ref"] + str(" - ") + move_line_data["name"]
  327. move_line_data.update({"ref_label": ref_label})
  328. return move_line_data
  329. @api.model
  330. def _get_period_domain(
  331. self,
  332. account_ids,
  333. partner_ids,
  334. company_id,
  335. only_posted_moves,
  336. date_to,
  337. date_from,
  338. analytic_tag_ids,
  339. cost_center_ids,
  340. ):
  341. domain = [
  342. ("display_type", "=", False),
  343. ("date", ">=", date_from),
  344. ("date", "<=", date_to),
  345. ]
  346. if account_ids:
  347. domain += [("account_id", "in", account_ids)]
  348. if company_id:
  349. domain += [("company_id", "=", company_id)]
  350. if partner_ids:
  351. domain += [("partner_id", "in", partner_ids)]
  352. if only_posted_moves:
  353. domain += [("move_id.state", "=", "posted")]
  354. if analytic_tag_ids:
  355. domain += [("analytic_tag_ids", "in", analytic_tag_ids)]
  356. if cost_center_ids:
  357. domain += [("analytic_account_id", "in", cost_center_ids)]
  358. return domain
  359. @api.model
  360. def _initialize_partner(self, gen_ld_data, acc_id, prt_id, foreign_currency):
  361. gen_ld_data[acc_id]["partners"] = True
  362. gen_ld_data[acc_id][prt_id] = {}
  363. gen_ld_data[acc_id][prt_id]["id"] = prt_id
  364. gen_ld_data[acc_id][prt_id]["init_bal"] = {}
  365. gen_ld_data[acc_id][prt_id]["init_bal"]["balance"] = 0.0
  366. gen_ld_data[acc_id][prt_id]["init_bal"]["credit"] = 0.0
  367. gen_ld_data[acc_id][prt_id]["init_bal"]["debit"] = 0.0
  368. gen_ld_data[acc_id][prt_id]["fin_bal"] = {}
  369. gen_ld_data[acc_id][prt_id]["fin_bal"]["credit"] = 0.0
  370. gen_ld_data[acc_id][prt_id]["fin_bal"]["debit"] = 0.0
  371. gen_ld_data[acc_id][prt_id]["fin_bal"]["balance"] = 0.0
  372. if foreign_currency:
  373. gen_ld_data[acc_id][prt_id]["init_bal"]["bal_curr"] = 0.0
  374. gen_ld_data[acc_id][prt_id]["fin_bal"]["bal_curr"] = 0.0
  375. return gen_ld_data
  376. def _initialize_account(self, gen_ld_data, acc_id, foreign_currency):
  377. gen_ld_data[acc_id] = {}
  378. gen_ld_data[acc_id]["id"] = acc_id
  379. gen_ld_data[acc_id]["partners"] = False
  380. gen_ld_data[acc_id]["init_bal"] = {}
  381. gen_ld_data[acc_id]["init_bal"]["balance"] = 0.0
  382. gen_ld_data[acc_id]["init_bal"]["credit"] = 0.0
  383. gen_ld_data[acc_id]["init_bal"]["debit"] = 0.0
  384. gen_ld_data[acc_id]["fin_bal"] = {}
  385. gen_ld_data[acc_id]["fin_bal"]["credit"] = 0.0
  386. gen_ld_data[acc_id]["fin_bal"]["debit"] = 0.0
  387. gen_ld_data[acc_id]["fin_bal"]["balance"] = 0.0
  388. if foreign_currency:
  389. gen_ld_data[acc_id]["init_bal"]["bal_curr"] = 0.0
  390. gen_ld_data[acc_id]["fin_bal"]["bal_curr"] = 0.0
  391. return gen_ld_data
  392. def _get_reconciled_after_date_to_ids(self, full_reconcile_ids, date_to):
  393. full_reconcile_ids = list(full_reconcile_ids)
  394. domain = [
  395. ("max_date", ">", date_to),
  396. ("full_reconcile_id", "in", full_reconcile_ids),
  397. ]
  398. fields = ["full_reconcile_id"]
  399. reconciled_after_date_to = self.env["account.partial.reconcile"].search_read(
  400. domain=domain, fields=fields
  401. )
  402. rec_after_date_to_ids = list(
  403. map(operator.itemgetter("full_reconcile_id"), reconciled_after_date_to)
  404. )
  405. rec_after_date_to_ids = [i[0] for i in rec_after_date_to_ids]
  406. return rec_after_date_to_ids
  407. def _get_period_ml_data(
  408. self,
  409. account_ids,
  410. partner_ids,
  411. company_id,
  412. foreign_currency,
  413. only_posted_moves,
  414. hide_account_at_0,
  415. date_from,
  416. date_to,
  417. partners_data,
  418. gen_ld_data,
  419. partners_ids,
  420. centralize,
  421. analytic_tag_ids,
  422. cost_center_ids,
  423. ):
  424. domain = self._get_period_domain(
  425. account_ids,
  426. partner_ids,
  427. company_id,
  428. only_posted_moves,
  429. date_to,
  430. date_from,
  431. analytic_tag_ids,
  432. cost_center_ids,
  433. )
  434. ml_fields = [
  435. "id",
  436. "name",
  437. "date",
  438. "move_id",
  439. "journal_id",
  440. "account_id",
  441. "partner_id",
  442. "debit",
  443. "credit",
  444. "balance",
  445. "currency_id",
  446. "full_reconcile_id",
  447. "tax_ids",
  448. "analytic_tag_ids",
  449. "amount_currency",
  450. "ref",
  451. "name",
  452. "analytic_account_id",
  453. ]
  454. move_lines = self.env["account.move.line"].search_read(
  455. domain=domain, fields=ml_fields
  456. )
  457. journal_ids = set()
  458. full_reconcile_ids = set()
  459. taxes_ids = set()
  460. tags_ids = set()
  461. full_reconcile_data = {}
  462. acc_prt_account_ids = self._get_acc_prt_accounts_ids(company_id)
  463. for move_line in move_lines:
  464. journal_ids.add(move_line["journal_id"][0])
  465. for tax_id in move_line["tax_ids"]:
  466. taxes_ids.add(tax_id)
  467. for analytic_tag_id in move_line["analytic_tag_ids"]:
  468. tags_ids.add(analytic_tag_id)
  469. if move_line["full_reconcile_id"]:
  470. rec_id = move_line["full_reconcile_id"][0]
  471. if rec_id not in full_reconcile_ids:
  472. full_reconcile_data.update(
  473. {
  474. rec_id: {
  475. "id": rec_id,
  476. "name": move_line["full_reconcile_id"][1],
  477. }
  478. }
  479. )
  480. full_reconcile_ids.add(rec_id)
  481. acc_id = move_line["account_id"][0]
  482. ml_id = move_line["id"]
  483. if move_line["partner_id"]:
  484. prt_id = move_line["partner_id"][0]
  485. partner_name = move_line["partner_id"][1]
  486. if acc_id not in gen_ld_data.keys():
  487. gen_ld_data = self._initialize_account(
  488. gen_ld_data, acc_id, foreign_currency
  489. )
  490. if acc_id in acc_prt_account_ids:
  491. if not move_line["partner_id"]:
  492. prt_id = 0
  493. partner_name = "Missing Partner"
  494. partners_ids.append(prt_id)
  495. partners_data.update({prt_id: {"id": prt_id, "name": partner_name}})
  496. if prt_id not in gen_ld_data[acc_id]:
  497. gen_ld_data = self._initialize_partner(
  498. gen_ld_data, acc_id, prt_id, foreign_currency
  499. )
  500. gen_ld_data[acc_id][prt_id][ml_id] = self._get_move_line_data(move_line)
  501. gen_ld_data[acc_id][prt_id]["fin_bal"]["credit"] += move_line["credit"]
  502. gen_ld_data[acc_id][prt_id]["fin_bal"]["debit"] += move_line["debit"]
  503. gen_ld_data[acc_id][prt_id]["fin_bal"]["balance"] += move_line[
  504. "balance"
  505. ]
  506. if foreign_currency:
  507. gen_ld_data[acc_id][prt_id]["fin_bal"]["bal_curr"] += move_line[
  508. "amount_currency"
  509. ]
  510. else:
  511. gen_ld_data[acc_id][ml_id] = self._get_move_line_data(move_line)
  512. gen_ld_data[acc_id]["fin_bal"]["credit"] += move_line["credit"]
  513. gen_ld_data[acc_id]["fin_bal"]["debit"] += move_line["debit"]
  514. gen_ld_data[acc_id]["fin_bal"]["balance"] += move_line["balance"]
  515. if foreign_currency:
  516. gen_ld_data[acc_id]["fin_bal"]["bal_curr"] += move_line[
  517. "amount_currency"
  518. ]
  519. journals_data = self._get_journals_data(list(journal_ids))
  520. accounts_data = self._get_accounts_data(gen_ld_data.keys())
  521. taxes_data = self._get_taxes_data(list(taxes_ids))
  522. tags_data = self._get_tags_data(list(tags_ids))
  523. rec_after_date_to_ids = self._get_reconciled_after_date_to_ids(
  524. full_reconcile_data.keys(), date_to
  525. )
  526. return (
  527. gen_ld_data,
  528. accounts_data,
  529. partners_data,
  530. journals_data,
  531. full_reconcile_data,
  532. taxes_data,
  533. tags_data,
  534. rec_after_date_to_ids,
  535. )
  536. @api.model
  537. def _recalculate_cumul_balance(
  538. self, move_lines, last_cumul_balance, rec_after_date_to_ids
  539. ):
  540. for move_line in move_lines:
  541. move_line["balance"] += last_cumul_balance
  542. last_cumul_balance = move_line["balance"]
  543. if move_line["rec_id"] in rec_after_date_to_ids:
  544. move_line["rec_name"] = "(" + _("future") + ") " + move_line["rec_name"]
  545. return move_lines
  546. @api.model
  547. def _create_general_ledger(
  548. self, gen_led_data, accounts_data, show_partner_details, rec_after_date_to_ids
  549. ):
  550. general_ledger = []
  551. for acc_id in gen_led_data.keys():
  552. account = {}
  553. account.update(
  554. {
  555. "code": accounts_data[acc_id]["code"],
  556. "name": accounts_data[acc_id]["name"],
  557. "type": "account",
  558. "currency_id": accounts_data[acc_id]["currency_id"],
  559. "centralized": accounts_data[acc_id]["centralized"],
  560. }
  561. )
  562. if not gen_led_data[acc_id]["partners"]:
  563. move_lines = []
  564. for ml_id in gen_led_data[acc_id].keys():
  565. if not isinstance(ml_id, int):
  566. account.update({ml_id: gen_led_data[acc_id][ml_id]})
  567. else:
  568. move_lines += [gen_led_data[acc_id][ml_id]]
  569. move_lines = sorted(move_lines, key=lambda k: (k["date"]))
  570. move_lines = self._recalculate_cumul_balance(
  571. move_lines,
  572. gen_led_data[acc_id]["init_bal"]["balance"],
  573. rec_after_date_to_ids,
  574. )
  575. account.update({"move_lines": move_lines})
  576. else:
  577. if show_partner_details:
  578. list_partner = []
  579. for prt_id in gen_led_data[acc_id].keys():
  580. partner = {}
  581. move_lines = []
  582. if not isinstance(prt_id, int):
  583. account.update({prt_id: gen_led_data[acc_id][prt_id]})
  584. else:
  585. for ml_id in gen_led_data[acc_id][prt_id].keys():
  586. if not isinstance(ml_id, int):
  587. partner.update(
  588. {ml_id: gen_led_data[acc_id][prt_id][ml_id]}
  589. )
  590. else:
  591. move_lines += [gen_led_data[acc_id][prt_id][ml_id]]
  592. move_lines = sorted(move_lines, key=lambda k: (k["date"]))
  593. move_lines = self._recalculate_cumul_balance(
  594. move_lines,
  595. gen_led_data[acc_id][prt_id]["init_bal"]["balance"],
  596. rec_after_date_to_ids,
  597. )
  598. partner.update({"move_lines": move_lines})
  599. list_partner += [partner]
  600. account.update({"list_partner": list_partner})
  601. else:
  602. move_lines = []
  603. for prt_id in gen_led_data[acc_id].keys():
  604. if not isinstance(prt_id, int):
  605. account.update({prt_id: gen_led_data[acc_id][prt_id]})
  606. else:
  607. for ml_id in gen_led_data[acc_id][prt_id].keys():
  608. if isinstance(ml_id, int):
  609. move_lines += [gen_led_data[acc_id][prt_id][ml_id]]
  610. move_lines = sorted(move_lines, key=lambda k: (k["date"]))
  611. move_lines = self._recalculate_cumul_balance(
  612. move_lines,
  613. gen_led_data[acc_id]["init_bal"]["balance"],
  614. rec_after_date_to_ids,
  615. )
  616. account.update({"move_lines": move_lines, "partners": False})
  617. general_ledger += [account]
  618. return general_ledger
  619. @api.model
  620. def _calculate_centralization(self, centralized_ml, move_line, date_to):
  621. jnl_id = move_line["journal_id"]
  622. month = move_line["date"].month
  623. if jnl_id not in centralized_ml.keys():
  624. centralized_ml[jnl_id] = {}
  625. if month not in centralized_ml[jnl_id].keys():
  626. centralized_ml[jnl_id][month] = {}
  627. last_day_month = calendar.monthrange(move_line["date"].year, month)
  628. date = datetime.date(move_line["date"].year, month, last_day_month[1])
  629. if date > date_to:
  630. date = date_to
  631. centralized_ml[jnl_id][month].update(
  632. {
  633. "journal_id": jnl_id,
  634. "ref_label": "Centralized entries",
  635. "date": date,
  636. "debit": 0.0,
  637. "credit": 0.0,
  638. "balance": 0.0,
  639. "bal_curr": 0.0,
  640. "partner_id": False,
  641. "rec_id": 0,
  642. "entry_id": False,
  643. "tax_ids": [],
  644. "full_reconcile_id": False,
  645. "id": False,
  646. "tag_ids": False,
  647. "currency_id": False,
  648. "analytic_account_id": False,
  649. }
  650. )
  651. centralized_ml[jnl_id][month]["debit"] += move_line["debit"]
  652. centralized_ml[jnl_id][month]["credit"] += move_line["credit"]
  653. centralized_ml[jnl_id][month]["balance"] += (
  654. move_line["debit"] - move_line["credit"]
  655. )
  656. centralized_ml[jnl_id][month]["bal_curr"] += move_line["bal_curr"]
  657. return centralized_ml
  658. @api.model
  659. def _get_centralized_ml(self, account, date_to):
  660. centralized_ml = {}
  661. if isinstance(date_to, str):
  662. date_to = datetime.datetime.strptime(date_to, "%Y-%m-%d").date()
  663. if account["partners"]:
  664. for partner in account["list_partner"]:
  665. for move_line in partner["move_lines"]:
  666. centralized_ml = self._calculate_centralization(
  667. centralized_ml, move_line, date_to,
  668. )
  669. else:
  670. for move_line in account["move_lines"]:
  671. centralized_ml = self._calculate_centralization(
  672. centralized_ml, move_line, date_to,
  673. )
  674. list_centralized_ml = []
  675. for jnl_id in centralized_ml.keys():
  676. list_centralized_ml += list(centralized_ml[jnl_id].values())
  677. return list_centralized_ml
  678. def _get_report_values(self, docids, data):
  679. wizard_id = data["wizard_id"]
  680. company = self.env["res.company"].browse(data["company_id"])
  681. company_id = data["company_id"]
  682. date_to = data["date_to"]
  683. date_from = data["date_from"]
  684. partner_ids = data["partner_ids"]
  685. if not partner_ids:
  686. filter_partner_ids = False
  687. else:
  688. filter_partner_ids = True
  689. account_ids = data["account_ids"]
  690. analytic_tag_ids = data["analytic_tag_ids"]
  691. cost_center_ids = data["cost_center_ids"]
  692. show_partner_details = data["show_partner_details"]
  693. hide_account_at_0 = data["hide_account_at_0"]
  694. foreign_currency = data["foreign_currency"]
  695. only_posted_moves = data["only_posted_moves"]
  696. unaffected_earnings_account = data["unaffected_earnings_account"]
  697. fy_start_date = data["fy_start_date"]
  698. gen_ld_data, partners_data, partners_ids = self._get_initial_balance_data(
  699. account_ids,
  700. partner_ids,
  701. company_id,
  702. date_from,
  703. foreign_currency,
  704. only_posted_moves,
  705. hide_account_at_0,
  706. unaffected_earnings_account,
  707. fy_start_date,
  708. analytic_tag_ids,
  709. cost_center_ids,
  710. )
  711. centralize = data["centralize"]
  712. (
  713. gen_ld_data,
  714. accounts_data,
  715. partners_data,
  716. journals_data,
  717. full_reconcile_data,
  718. taxes_data,
  719. tags_data,
  720. rec_after_date_to_ids,
  721. ) = self._get_period_ml_data(
  722. account_ids,
  723. partner_ids,
  724. company_id,
  725. foreign_currency,
  726. only_posted_moves,
  727. hide_account_at_0,
  728. date_from,
  729. date_to,
  730. partners_data,
  731. gen_ld_data,
  732. partners_ids,
  733. centralize,
  734. analytic_tag_ids,
  735. cost_center_ids,
  736. )
  737. general_ledger = self._create_general_ledger(
  738. gen_ld_data, accounts_data, show_partner_details, rec_after_date_to_ids
  739. )
  740. if centralize:
  741. for account in general_ledger:
  742. if account["centralized"]:
  743. centralized_ml = self._get_centralized_ml(account, date_to)
  744. account["move_lines"] = centralized_ml
  745. account["move_lines"] = self._recalculate_cumul_balance(
  746. account["move_lines"],
  747. gen_ld_data[account["id"]]["init_bal"]["balance"],
  748. rec_after_date_to_ids,
  749. )
  750. if account["partners"]:
  751. account["partners"] = False
  752. del account["list_partner"]
  753. general_ledger = sorted(general_ledger, key=lambda k: k["code"])
  754. return {
  755. "doc_ids": [wizard_id],
  756. "doc_model": "general.ledger.report.wizard",
  757. "docs": self.env["general.ledger.report.wizard"].browse(wizard_id),
  758. "foreign_currency": data["foreign_currency"],
  759. "company_name": company.display_name,
  760. "company_currency": company.currency_id,
  761. "currency_name": company.currency_id.name,
  762. "date_from": data["date_from"],
  763. "date_to": data["date_to"],
  764. "only_posted_moves": data["only_posted_moves"],
  765. "hide_account_at_0": data["hide_account_at_0"],
  766. "show_analytic_tags": data["show_analytic_tags"],
  767. "show_cost_center": data["show_cost_center"],
  768. "general_ledger": general_ledger,
  769. "accounts_data": accounts_data,
  770. "partners_data": partners_data,
  771. "journals_data": journals_data,
  772. "full_reconcile_data": full_reconcile_data,
  773. "taxes_data": taxes_data,
  774. "centralize": centralize,
  775. "tags_data": tags_data,
  776. "filter_partner_ids": filter_partner_ids,
  777. }