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.

379 lines
13 KiB

  1. # -*- coding: utf-8 -*-
  2. # Author: Julien Coux
  3. # Copyright 2016 Camptocamp SA
  4. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
  5. import logging
  6. from odoo.tests import common
  7. from odoo.tools import test_reports
  8. _logger = logging.getLogger(__name__)
  9. class AbstractTest(common.TransactionCase):
  10. """Common technical tests for all reports."""
  11. at_install = False
  12. post_install = True
  13. accounts = {}
  14. def with_context(self, *args, **kwargs):
  15. context = dict(args[0] if args else self.env.context, **kwargs)
  16. self.env = self.env(context=context)
  17. return self
  18. def _chart_template_create(self):
  19. transfer_account_id = self.env['account.account.template'].create({
  20. 'code': '000',
  21. 'name': 'Liquidity Transfers',
  22. 'reconcile': True,
  23. 'user_type_id': self.ref(
  24. "account.data_account_type_current_assets"),
  25. })
  26. self.chart = self.env['account.chart.template'].create({
  27. 'name': 'Test COA',
  28. 'code_digits': 4,
  29. 'bank_account_code_prefix': 1014,
  30. 'cash_account_code_prefix': 1014,
  31. 'currency_id': self.ref('base.USD'),
  32. 'transfer_account_id': transfer_account_id.id,
  33. })
  34. transfer_account_id.update({
  35. 'chart_template_id': self.chart.id,
  36. })
  37. self.env['ir.model.data'].create({
  38. 'res_id': transfer_account_id.id,
  39. 'model': transfer_account_id._name,
  40. 'name': 'Liquidity Transfers',
  41. })
  42. act = self.env['account.account.template'].create({
  43. 'code': '001',
  44. 'name': 'Expenses',
  45. 'user_type_id': self.ref("account.data_account_type_expenses"),
  46. 'chart_template_id': self.chart.id,
  47. 'reconcile': True,
  48. })
  49. self.env['ir.model.data'].create({
  50. 'res_id': act.id,
  51. 'model': act._name,
  52. 'name': 'expenses',
  53. })
  54. act = self.env['account.account.template'].create({
  55. 'code': '002',
  56. 'name': 'Product Sales',
  57. 'user_type_id': self.ref("account.data_account_type_revenue"),
  58. 'chart_template_id': self.chart.id,
  59. 'reconcile': True,
  60. })
  61. self.env['ir.model.data'].create({
  62. 'res_id': act.id,
  63. 'model': act._name,
  64. 'name': 'sales',
  65. })
  66. act = self.env['account.account.template'].create({
  67. 'code': '003',
  68. 'name': 'Account Receivable',
  69. 'user_type_id': self.ref("account.data_account_type_receivable"),
  70. 'chart_template_id': self.chart.id,
  71. 'reconcile': True,
  72. })
  73. self.env['ir.model.data'].create({
  74. 'res_id': act.id,
  75. 'model': act._name,
  76. 'name': 'receivable',
  77. })
  78. act = self.env['account.account.template'].create({
  79. 'code': '004',
  80. 'name': 'Account Payable',
  81. 'user_type_id': self.ref("account.data_account_type_payable"),
  82. 'chart_template_id': self.chart.id,
  83. 'reconcile': True,
  84. })
  85. self.env['ir.model.data'].create({
  86. 'res_id': act.id,
  87. 'model': act._name,
  88. 'name': 'payable',
  89. })
  90. def _add_chart_of_accounts(self):
  91. self.company = self.env['res.company'].create({
  92. 'name': 'Spanish test company',
  93. })
  94. self.env.ref('base.group_multi_company').write({
  95. 'users': [(4, self.env.uid)],
  96. })
  97. self.env.user.write({
  98. 'company_ids': [(4, self.company.id)],
  99. 'company_id': self.company.id,
  100. })
  101. self.with_context(
  102. company_id=self.company.id, force_company=self.company.id)
  103. wizard = self.env['wizard.multi.charts.accounts'].create({
  104. 'company_id': self.company.id,
  105. 'chart_template_id': self.chart.id,
  106. 'code_digits': 4,
  107. 'currency_id': self.ref('base.USD'),
  108. 'transfer_account_id': self.chart.transfer_account_id.id,
  109. })
  110. wizard.onchange_chart_template_id()
  111. wizard.execute()
  112. self.revenue = self.env['account.account'].search(
  113. [('user_type_id', '=', self.ref(
  114. "account.data_account_type_revenue"))], limit=1)
  115. self.expense = self.env['account.account'].search(
  116. [('user_type_id', '=', self.ref(
  117. "account.data_account_type_expenses"))], limit=1)
  118. self.receivable = self.env['account.account'].search(
  119. [('user_type_id', '=', self.ref(
  120. "account.data_account_type_receivable"))], limit=1)
  121. self.payable = self.env['account.account'].search(
  122. [('user_type_id', '=', self.ref(
  123. "account.data_account_type_payable"))], limit=1)
  124. return True
  125. def _journals_create(self):
  126. self.journal_sale = self.env['account.journal'].create({
  127. 'company_id': self.company.id,
  128. 'name': 'Test journal for sale',
  129. 'type': 'sale',
  130. 'code': 'TSALE',
  131. 'default_debit_account_id': self.revenue.id,
  132. 'default_credit_account_id': self.revenue.id,
  133. })
  134. self.journal_purchase = self.env['account.journal'].create({
  135. 'company_id': self.company.id,
  136. 'name': 'Test journal for purchase',
  137. 'type': 'purchase',
  138. 'code': 'TPUR',
  139. 'default_debit_account_id': self.expense.id,
  140. 'default_credit_account_id': self.expense.id,
  141. })
  142. return True
  143. def _invoice_create(self):
  144. self.partner = self.env['res.partner'].create({
  145. 'name': 'Test partner',
  146. 'company_id': self.company.id,
  147. 'property_account_receivable_id': self.receivable.id,
  148. 'property_account_payable_id': self.payable.id,
  149. })
  150. # customer invoice
  151. customer_invoice_lines = [(0, False, {
  152. 'name': 'Test description #1',
  153. 'account_id': self.revenue.id,
  154. 'quantity': 1.0,
  155. 'price_unit': 100.0,
  156. }), (0, False, {
  157. 'name': 'Test description #2',
  158. 'account_id': self.revenue.id,
  159. 'quantity': 2.0,
  160. 'price_unit': 25.0,
  161. })]
  162. self.invoice_out = self.env['account.invoice'].create({
  163. 'partner_id': self.partner.id,
  164. 'type': 'out_invoice',
  165. 'invoice_line_ids': customer_invoice_lines,
  166. 'account_id': self.partner.property_account_receivable_id.id,
  167. 'journal_id': self.journal_sale.id,
  168. })
  169. self.invoice_out.action_invoice_open()
  170. # vendor bill
  171. vendor_invoice_lines = [(0, False, {
  172. 'name': 'Test description #1',
  173. 'account_id': self.revenue.id,
  174. 'quantity': 1.0,
  175. 'price_unit': 100.0,
  176. }), (0, False, {
  177. 'name': 'Test description #2',
  178. 'account_id': self.revenue.id,
  179. 'quantity': 2.0,
  180. 'price_unit': 25.0,
  181. })]
  182. self.invoice_in = self.env['account.invoice'].create({
  183. 'partner_id': self.partner.id,
  184. 'type': 'in_invoice',
  185. 'invoice_line_ids': vendor_invoice_lines,
  186. 'account_id': self.partner.property_account_payable_id.id,
  187. 'journal_id': self.journal_purchase.id,
  188. })
  189. self.invoice_in.action_invoice_open()
  190. def setUp(self):
  191. super(AbstractTest, self).setUp()
  192. self.with_context()
  193. self._chart_template_create()
  194. self._add_chart_of_accounts()
  195. self._journals_create()
  196. self._invoice_create()
  197. self.model = self._getReportModel()
  198. self.qweb_report_name = self._getQwebReportName()
  199. self.xlsx_report_name = self._getXlsxReportName()
  200. self.xlsx_action_name = self._getXlsxReportActionName()
  201. self.report_title = self._getReportTitle()
  202. self.base_filters = self._getBaseFilters()
  203. self.additional_filters = self._getAdditionalFiltersToBeTested()
  204. self.report = self.model.create(self.base_filters)
  205. self.report.compute_data_for_report()
  206. def test_html(self):
  207. test_reports.try_report(self.env.cr, self.env.uid,
  208. self.qweb_report_name,
  209. [self.report.id],
  210. report_type='qweb-html')
  211. def test_qweb(self):
  212. test_reports.try_report(self.env.cr, self.env.uid,
  213. self.qweb_report_name,
  214. [self.report.id],
  215. report_type='qweb-pdf')
  216. def test_xlsx(self):
  217. test_reports.try_report(self.env.cr, self.env.uid,
  218. self.xlsx_report_name,
  219. [self.report.id],
  220. report_type='xlsx')
  221. def test_print(self):
  222. self.report.print_report('qweb')
  223. self.report.print_report('xlsx')
  224. def test_04_compute_data(self):
  225. """Check that the SQL queries work with all filters options"""
  226. for filters in [{}] + self.additional_filters:
  227. current_filter = self.base_filters.copy()
  228. current_filter.update(filters)
  229. report = self.model.create(current_filter)
  230. report.compute_data_for_report()
  231. self.assertGreaterEqual(len(report.account_ids), 1)
  232. # Same filters with only one account
  233. current_filter = self.base_filters.copy()
  234. current_filter.update(filters)
  235. current_filter.update({
  236. 'filter_account_ids':
  237. [(6, 0, report.account_ids[0].account_id.ids)],
  238. })
  239. report2 = self.model.create(current_filter)
  240. report2.compute_data_for_report()
  241. self.assertGreaterEqual(len(report2.account_ids), 1)
  242. self.assertEqual(report2.account_ids[0].name,
  243. report.account_ids[0].name)
  244. if self._partner_test_is_possible(filters):
  245. # Same filters with only one partner
  246. report_partner_ids = report.account_ids.mapped('partner_ids')
  247. partner_ids = report_partner_ids.mapped('partner_id')
  248. current_filter = self.base_filters.copy()
  249. current_filter.update(filters)
  250. current_filter.update({
  251. 'filter_partner_ids': [(6, 0, partner_ids[0].ids)],
  252. })
  253. report3 = self.model.create(current_filter)
  254. report3.compute_data_for_report()
  255. self.assertGreaterEqual(len(report3.account_ids), 1)
  256. report_partner_ids3 = report3.account_ids.mapped('partner_ids')
  257. partner_ids3 = report_partner_ids3.mapped('partner_id')
  258. self.assertEqual(len(partner_ids3), 1)
  259. self.assertEqual(
  260. partner_ids3.name,
  261. partner_ids[0].name
  262. )
  263. # Same filters with only one partner and one account
  264. report_partner_ids = report3.account_ids.mapped('partner_ids')
  265. report_account_id = report_partner_ids.filtered(
  266. lambda p: p.partner_id
  267. )[0].report_account_id
  268. current_filter = self.base_filters.copy()
  269. current_filter.update(filters)
  270. current_filter.update({
  271. 'filter_account_ids':
  272. [(6, 0, report_account_id.account_id.ids)],
  273. 'filter_partner_ids': [(6, 0, partner_ids[0].ids)],
  274. })
  275. report4 = self.model.create(current_filter)
  276. report4.compute_data_for_report()
  277. self.assertEqual(len(report4.account_ids), 1)
  278. self.assertEqual(report4.account_ids.name,
  279. report_account_id.account_id.name)
  280. report_partner_ids4 = report4.account_ids.mapped('partner_ids')
  281. partner_ids4 = report_partner_ids4.mapped('partner_id')
  282. self.assertEqual(len(partner_ids4), 1)
  283. self.assertEqual(
  284. partner_ids4.name,
  285. partner_ids[0].name
  286. )
  287. def _partner_test_is_possible(self, filters):
  288. """
  289. :return:
  290. a boolean to indicate if partner test is possible
  291. with current filters
  292. """
  293. return True
  294. def _getReportModel(self):
  295. """
  296. :return: the report model name
  297. """
  298. raise NotImplementedError()
  299. def _getQwebReportName(self):
  300. """
  301. :return: the qweb report name
  302. """
  303. raise NotImplementedError()
  304. def _getXlsxReportName(self):
  305. """
  306. :return: the xlsx report name
  307. """
  308. raise NotImplementedError()
  309. def _getXlsxReportActionName(self):
  310. """
  311. :return: the xlsx report action name
  312. """
  313. raise NotImplementedError()
  314. def _getReportTitle(self):
  315. """
  316. :return: the report title displayed into the report
  317. """
  318. raise NotImplementedError()
  319. def _getBaseFilters(self):
  320. """
  321. :return: the minimum required filters to generate report
  322. """
  323. raise NotImplementedError()
  324. def _getAdditionalFiltersToBeTested(self):
  325. """
  326. :return: the additional filters to generate report variants
  327. """
  328. raise NotImplementedError()