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.

305 lines
12 KiB

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