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.

323 lines
13 KiB

  1. # Author: Julien Coux
  2. # Copyright 2016 Camptocamp SA
  3. # Copyright 2021 Tecnativa - João Marques
  4. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
  5. from odoo import _, models
  6. class TrialBalanceXslx(models.AbstractModel):
  7. _name = "report.a_f_r.report_trial_balance_xlsx"
  8. _description = "Trial Balance XLSX Report"
  9. _inherit = "report.account_financial_report.abstract_report_xlsx"
  10. def _get_report_name(self, report, data=False):
  11. company_id = data.get("company_id", False)
  12. report_name = _("Trial Balance")
  13. if company_id:
  14. company = self.env["res.company"].browse(company_id)
  15. suffix = " - {} - {}".format(company.name, company.currency_id.name)
  16. report_name = report_name + suffix
  17. return report_name
  18. def _get_report_columns(self, report):
  19. if not report.show_partner_details:
  20. res = {
  21. 0: {"header": _("Code"), "field": "code", "width": 10},
  22. 1: {"header": _("Account"), "field": "name", "width": 60},
  23. 2: {
  24. "header": _("Initial balance"),
  25. "field": "initial_balance",
  26. "type": "amount",
  27. "width": 14,
  28. },
  29. 3: {
  30. "header": _("Debit"),
  31. "field": "debit",
  32. "type": "amount",
  33. "width": 14,
  34. },
  35. 4: {
  36. "header": _("Credit"),
  37. "field": "credit",
  38. "type": "amount",
  39. "width": 14,
  40. },
  41. 5: {
  42. "header": _("Period balance"),
  43. "field": "balance",
  44. "type": "amount",
  45. "width": 14,
  46. },
  47. 6: {
  48. "header": _("Ending balance"),
  49. "field": "ending_balance",
  50. "type": "amount",
  51. "width": 14,
  52. },
  53. }
  54. if report.foreign_currency:
  55. foreign_currency = {
  56. 7: {
  57. "header": _("Cur."),
  58. "field": "currency_id",
  59. "field_currency_balance": "currency_id",
  60. "type": "many2one",
  61. "width": 7,
  62. },
  63. 8: {
  64. "header": _("Initial balance"),
  65. "field": "initial_currency_balance",
  66. "type": "amount_currency",
  67. "width": 14,
  68. },
  69. 9: {
  70. "header": _("Ending balance"),
  71. "field": "ending_currency_balance",
  72. "type": "amount_currency",
  73. "width": 14,
  74. },
  75. }
  76. res = {**res, **foreign_currency}
  77. return res
  78. else:
  79. res = {
  80. 0: {"header": _("Partner"), "field": "name", "width": 70},
  81. 1: {
  82. "header": _("Initial balance"),
  83. "field": "initial_balance",
  84. "type": "amount",
  85. "width": 14,
  86. },
  87. 2: {
  88. "header": _("Debit"),
  89. "field": "debit",
  90. "type": "amount",
  91. "width": 14,
  92. },
  93. 3: {
  94. "header": _("Credit"),
  95. "field": "credit",
  96. "type": "amount",
  97. "width": 14,
  98. },
  99. 4: {
  100. "header": _("Period balance"),
  101. "field": "balance",
  102. "type": "amount",
  103. "width": 14,
  104. },
  105. 5: {
  106. "header": _("Ending balance"),
  107. "field": "ending_balance",
  108. "type": "amount",
  109. "width": 14,
  110. },
  111. }
  112. if report.foreign_currency:
  113. foreign_currency = {
  114. 6: {
  115. "header": _("Cur."),
  116. "field": "currency_id",
  117. "field_currency_balance": "currency_id",
  118. "type": "many2one",
  119. "width": 7,
  120. },
  121. 7: {
  122. "header": _("Initial balance"),
  123. "field": "initial_currency_balance",
  124. "type": "amount_currency",
  125. "width": 14,
  126. },
  127. 8: {
  128. "header": _("Ending balance"),
  129. "field": "ending_currency_balance",
  130. "type": "amount_currency",
  131. "width": 14,
  132. },
  133. }
  134. res = {**res, **foreign_currency}
  135. return res
  136. def _get_report_filters(self, report):
  137. return [
  138. [
  139. _("Date range filter"),
  140. _("From: %s To: %s") % (report.date_from, report.date_to),
  141. ],
  142. [
  143. _("Target moves filter"),
  144. _("All posted entries")
  145. if report.target_move == "posted"
  146. else _("All entries"),
  147. ],
  148. [
  149. _("Account at 0 filter"),
  150. _("Hide") if report.hide_account_at_0 else _("Show"),
  151. ],
  152. [
  153. _("Show foreign currency"),
  154. _("Yes") if report.foreign_currency else _("No"),
  155. ],
  156. [
  157. _("Limit hierarchy levels"),
  158. _("Level %s" % report.show_hierarchy_level)
  159. if report.limit_hierarchy_level
  160. else _("No limit"),
  161. ],
  162. ]
  163. def _get_col_count_filter_name(self):
  164. return 2
  165. def _get_col_count_filter_value(self):
  166. return 3
  167. def _generate_report_content(self, workbook, report, data, report_data):
  168. res_data = self.env[
  169. "report.account_financial_report.trial_balance"
  170. ]._get_report_values(report, data)
  171. trial_balance = res_data["trial_balance"]
  172. total_amount = res_data["total_amount"]
  173. partners_data = res_data["partners_data"]
  174. accounts_data = res_data["accounts_data"]
  175. hierarchy_on = res_data["hierarchy_on"]
  176. show_partner_details = res_data["show_partner_details"]
  177. show_hierarchy_level = res_data["show_hierarchy_level"]
  178. foreign_currency = res_data["foreign_currency"]
  179. limit_hierarchy_level = res_data["limit_hierarchy_level"]
  180. if not show_partner_details:
  181. # Display array header for account lines
  182. self.write_array_header(report_data)
  183. # For each account
  184. if not show_partner_details:
  185. for balance in trial_balance:
  186. if hierarchy_on == "relation":
  187. if limit_hierarchy_level:
  188. if show_hierarchy_level > balance["level"]:
  189. # Display account lines
  190. self.write_line_from_dict(balance, report_data)
  191. else:
  192. self.write_line_from_dict(balance, report_data)
  193. elif hierarchy_on == "computed":
  194. if balance["type"] == "account_type":
  195. if limit_hierarchy_level:
  196. if show_hierarchy_level > balance["level"]:
  197. # Display account lines
  198. self.write_line_from_dict(balance, report_data)
  199. else:
  200. self.write_line_from_dict(balance, report_data)
  201. else:
  202. self.write_line_from_dict(balance, report_data)
  203. else:
  204. for account_id in total_amount:
  205. # Write account title
  206. self.write_array_title(
  207. accounts_data[account_id]["code"]
  208. + "- "
  209. + accounts_data[account_id]["name"],
  210. report_data,
  211. )
  212. # Display array header for partner lines
  213. self.write_array_header(report_data)
  214. # For each partner
  215. for partner_id in total_amount[account_id]:
  216. if isinstance(partner_id, int):
  217. # Display partner lines
  218. self.write_line_from_dict_order(
  219. total_amount[account_id][partner_id],
  220. partners_data[partner_id],
  221. report_data,
  222. )
  223. # Display account footer line
  224. accounts_data[account_id].update(
  225. {
  226. "initial_balance": total_amount[account_id]["initial_balance"],
  227. "credit": total_amount[account_id]["credit"],
  228. "debit": total_amount[account_id]["debit"],
  229. "balance": total_amount[account_id]["balance"],
  230. "ending_balance": total_amount[account_id]["ending_balance"],
  231. }
  232. )
  233. if foreign_currency:
  234. accounts_data[account_id].update(
  235. {
  236. "initial_currency_balance": total_amount[account_id][
  237. "initial_currency_balance"
  238. ],
  239. "ending_currency_balance": total_amount[account_id][
  240. "ending_currency_balance"
  241. ],
  242. }
  243. )
  244. self.write_account_footer(
  245. accounts_data[account_id],
  246. accounts_data[account_id]["code"]
  247. + "- "
  248. + accounts_data[account_id]["name"],
  249. report_data,
  250. )
  251. # Line break
  252. report_data["row_pos"] += 2
  253. def write_line_from_dict_order(self, total_amount, partner_data, report_data):
  254. total_amount.update({"name": str(partner_data["name"])})
  255. self.write_line_from_dict(total_amount, report_data)
  256. def write_line(self, line_object, type_object, report_data):
  257. """Write a line on current line using all defined columns field name.
  258. Columns are defined with `_get_report_columns` method.
  259. """
  260. if type_object == "partner":
  261. line_object.currency_id = line_object.report_account_id.currency_id
  262. elif type_object == "account":
  263. line_object.currency_id = line_object.currency_id
  264. super(TrialBalanceXslx, self).write_line(line_object, report_data)
  265. def write_account_footer(self, account, name_value, report_data):
  266. """Specific function to write account footer for Trial Balance"""
  267. format_amt = self._get_currency_amt_header_format_dict(account, report_data)
  268. for col_pos, column in report_data["columns"].items():
  269. if column["field"] == "name":
  270. value = name_value
  271. else:
  272. value = account[column["field"]]
  273. cell_type = column.get("type", "string")
  274. if cell_type == "string":
  275. report_data["sheet"].write_string(
  276. report_data["row_pos"],
  277. col_pos,
  278. value or "",
  279. report_data["formats"]["format_header_left"],
  280. )
  281. elif cell_type == "amount":
  282. report_data["sheet"].write_number(
  283. report_data["row_pos"],
  284. col_pos,
  285. float(value),
  286. report_data["formats"]["format_header_amount"],
  287. )
  288. elif cell_type == "many2one" and account["currency_id"]:
  289. report_data["sheet"].write_string(
  290. report_data["row_pos"],
  291. col_pos,
  292. value.name or "",
  293. report_data["formats"]["format_header_right"],
  294. )
  295. elif cell_type == "amount_currency" and account["currency_id"]:
  296. report_data["sheet"].write_number(
  297. report_data["row_pos"], col_pos, float(value), format_amt
  298. )
  299. else:
  300. report_data["sheet"].write_string(
  301. report_data["row_pos"],
  302. col_pos,
  303. "",
  304. report_data["formats"]["format_header_right"],
  305. )
  306. report_data["row_pos"] += 1