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.

407 lines
14 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. import logging
  5. from odoo.tests import common
  6. from odoo.tools import test_reports
  7. _logger = logging.getLogger(__name__)
  8. class AbstractTest(common.TransactionCase):
  9. """Common technical tests for all reports."""
  10. at_install = False
  11. post_install = True
  12. accounts = {}
  13. def with_context(self, *args, **kwargs):
  14. context = dict(args[0] if args else self.env.context, **kwargs)
  15. self.env = self.env(context=context)
  16. return self
  17. def _chart_template_create(self):
  18. transfer_account_id = self.env['account.account.template'].create({
  19. 'code': '000',
  20. 'name': 'Liquidity Transfers',
  21. 'reconcile': True,
  22. 'user_type_id': self.ref(
  23. "account.data_account_type_current_assets"),
  24. })
  25. self.chart = self.env['account.chart.template'].create({
  26. 'name': 'Test COA',
  27. 'code_digits': 4,
  28. 'bank_account_code_prefix': 1014,
  29. 'cash_account_code_prefix': 1014,
  30. 'currency_id': self.ref('base.USD'),
  31. 'transfer_account_id': transfer_account_id.id,
  32. })
  33. transfer_account_id.update({
  34. 'chart_template_id': self.chart.id,
  35. })
  36. self.env['ir.model.data'].create({
  37. 'res_id': transfer_account_id.id,
  38. 'model': transfer_account_id._name,
  39. 'name': 'Liquidity Transfers',
  40. })
  41. act = self.env['account.account.template'].create({
  42. 'code': '001',
  43. 'name': 'Expenses',
  44. 'user_type_id': self.ref("account.data_account_type_expenses"),
  45. 'chart_template_id': self.chart.id,
  46. 'reconcile': True,
  47. })
  48. self.env['ir.model.data'].create({
  49. 'res_id': act.id,
  50. 'model': act._name,
  51. 'name': 'expenses',
  52. })
  53. act = self.env['account.account.template'].create({
  54. 'code': '002',
  55. 'name': 'Product Sales',
  56. 'user_type_id': self.ref("account.data_account_type_revenue"),
  57. 'chart_template_id': self.chart.id,
  58. 'reconcile': True,
  59. })
  60. self.env['ir.model.data'].create({
  61. 'res_id': act.id,
  62. 'model': act._name,
  63. 'name': 'sales',
  64. })
  65. act = self.env['account.account.template'].create({
  66. 'code': '003',
  67. 'name': 'Account Receivable',
  68. 'user_type_id': self.ref("account.data_account_type_receivable"),
  69. 'chart_template_id': self.chart.id,
  70. 'reconcile': True,
  71. })
  72. self.env['ir.model.data'].create({
  73. 'res_id': act.id,
  74. 'model': act._name,
  75. 'name': 'receivable',
  76. })
  77. act = self.env['account.account.template'].create({
  78. 'code': '004',
  79. 'name': 'Account Payable',
  80. 'user_type_id': self.ref("account.data_account_type_payable"),
  81. 'chart_template_id': self.chart.id,
  82. 'reconcile': True,
  83. })
  84. self.env['ir.model.data'].create({
  85. 'res_id': act.id,
  86. 'model': act._name,
  87. 'name': 'payable',
  88. })
  89. def _add_chart_of_accounts(self):
  90. self.company = self.env['res.company'].create({
  91. 'name': 'Spanish test company',
  92. 'external_report_layout': 'standard',
  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_02_generation_report_html(self):
  225. """Check if report HTML is correctly generated"""
  226. # Check if returned report action is correct
  227. report_type = 'qweb-html'
  228. report_action = self.report.print_report(report_type)
  229. self.assertDictContainsSubset(
  230. {
  231. 'type': 'ir.actions.report',
  232. 'report_name': self.qweb_report_name,
  233. 'report_type': 'qweb-html',
  234. },
  235. report_action
  236. )
  237. # Check if report template is correct
  238. report = self.env['ir.actions.report'].search(
  239. [('report_name', '=', self.qweb_report_name),
  240. ('report_type', '=', report_type)], limit=1)
  241. self.assertEqual(report.report_type, 'qweb-html')
  242. rep = report.render(self.report.ids, {})
  243. self.assertTrue(self.report_title.encode('utf8') in rep[0])
  244. self.assertTrue(
  245. self.report.account_ids[0].name.encode('utf8') in rep[0]
  246. )
  247. def test_04_compute_data(self):
  248. """Check that the SQL queries work with all filters options"""
  249. for filters in [{}] + self.additional_filters:
  250. current_filter = self.base_filters.copy()
  251. current_filter.update(filters)
  252. report = self.model.create(current_filter)
  253. report.compute_data_for_report()
  254. self.assertGreaterEqual(len(report.account_ids), 1)
  255. # Same filters with only one account
  256. current_filter = self.base_filters.copy()
  257. current_filter.update(filters)
  258. current_filter.update({
  259. 'filter_account_ids':
  260. [(6, 0, report.account_ids[0].account_id.ids)],
  261. })
  262. report2 = self.model.create(current_filter)
  263. report2.compute_data_for_report()
  264. self.assertEqual(len(report2.account_ids), 1)
  265. self.assertEqual(report2.account_ids.name,
  266. report.account_ids[0].name)
  267. if self._partner_test_is_possible(filters):
  268. # Same filters with only one partner
  269. report_partner_ids = report.account_ids.mapped('partner_ids')
  270. partner_ids = report_partner_ids.mapped('partner_id')
  271. current_filter = self.base_filters.copy()
  272. current_filter.update(filters)
  273. current_filter.update({
  274. 'filter_partner_ids': [(6, 0, partner_ids[0].ids)],
  275. })
  276. report3 = self.model.create(current_filter)
  277. report3.compute_data_for_report()
  278. self.assertGreaterEqual(len(report3.account_ids), 1)
  279. report_partner_ids3 = report3.account_ids.mapped('partner_ids')
  280. partner_ids3 = report_partner_ids3.mapped('partner_id')
  281. self.assertEqual(len(partner_ids3), 1)
  282. self.assertEqual(
  283. partner_ids3.name,
  284. partner_ids[0].name
  285. )
  286. # Same filters with only one partner and one account
  287. report_partner_ids = report3.account_ids.mapped('partner_ids')
  288. report_account_id = report_partner_ids.filtered(
  289. lambda p: p.partner_id
  290. )[0].report_account_id
  291. current_filter = self.base_filters.copy()
  292. current_filter.update(filters)
  293. current_filter.update({
  294. 'filter_account_ids':
  295. [(6, 0, report_account_id.account_id.ids)],
  296. 'filter_partner_ids': [(6, 0, partner_ids[0].ids)],
  297. })
  298. report4 = self.model.create(current_filter)
  299. report4.compute_data_for_report()
  300. self.assertEqual(len(report4.account_ids), 1)
  301. self.assertEqual(report4.account_ids.name,
  302. report_account_id.account_id.name)
  303. report_partner_ids4 = report4.account_ids.mapped('partner_ids')
  304. partner_ids4 = report_partner_ids4.mapped('partner_id')
  305. self.assertEqual(len(partner_ids4), 1)
  306. self.assertEqual(
  307. partner_ids4.name,
  308. partner_ids[0].name
  309. )
  310. def _partner_test_is_possible(self, filters):
  311. """
  312. :return:
  313. a boolean to indicate if partner test is possible
  314. with current filters
  315. """
  316. return True
  317. def _getReportModel(self):
  318. """
  319. :return: the report model name
  320. """
  321. raise NotImplementedError()
  322. def _getQwebReportName(self):
  323. """
  324. :return: the qweb report name
  325. """
  326. raise NotImplementedError()
  327. def _getXlsxReportName(self):
  328. """
  329. :return: the xlsx report name
  330. """
  331. raise NotImplementedError()
  332. def _getXlsxReportActionName(self):
  333. """
  334. :return: the xlsx report action name
  335. """
  336. raise NotImplementedError()
  337. def _getReportTitle(self):
  338. """
  339. :return: the report title displayed into the report
  340. """
  341. raise NotImplementedError()
  342. def _getBaseFilters(self):
  343. """
  344. :return: the minimum required filters to generate report
  345. """
  346. raise NotImplementedError()
  347. def _getAdditionalFiltersToBeTested(self):
  348. """
  349. :return: the additional filters to generate report variants
  350. """
  351. raise NotImplementedError()