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.

399 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_code_prefix': '000',
  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. })
  93. self.env.ref('base.group_multi_company').write({
  94. 'users': [(4, self.env.uid)],
  95. })
  96. self.env.user.write({
  97. 'company_ids': [(4, self.company.id)],
  98. 'company_id': self.company.id,
  99. })
  100. self.with_context(
  101. company_id=self.company.id, force_company=self.company.id)
  102. self.chart.try_loading_for_current_company()
  103. self.revenue = self.env['account.account'].search(
  104. [('user_type_id', '=', self.ref(
  105. "account.data_account_type_revenue"))], limit=1)
  106. self.expense = self.env['account.account'].search(
  107. [('user_type_id', '=', self.ref(
  108. "account.data_account_type_expenses"))], limit=1)
  109. self.receivable = self.env['account.account'].search(
  110. [('user_type_id', '=', self.ref(
  111. "account.data_account_type_receivable"))], limit=1)
  112. self.payable = self.env['account.account'].search(
  113. [('user_type_id', '=', self.ref(
  114. "account.data_account_type_payable"))], limit=1)
  115. return True
  116. def _journals_create(self):
  117. self.journal_sale = self.env['account.journal'].create({
  118. 'company_id': self.company.id,
  119. 'name': 'Test journal for sale',
  120. 'type': 'sale',
  121. 'code': 'TSALE',
  122. 'default_debit_account_id': self.revenue.id,
  123. 'default_credit_account_id': self.revenue.id,
  124. })
  125. self.journal_purchase = self.env['account.journal'].create({
  126. 'company_id': self.company.id,
  127. 'name': 'Test journal for purchase',
  128. 'type': 'purchase',
  129. 'code': 'TPUR',
  130. 'default_debit_account_id': self.expense.id,
  131. 'default_credit_account_id': self.expense.id,
  132. })
  133. return True
  134. def _invoice_create(self):
  135. self.partner = self.env['res.partner'].create({
  136. 'name': 'Test partner',
  137. 'company_id': self.company.id,
  138. 'property_account_receivable_id': self.receivable.id,
  139. 'property_account_payable_id': self.payable.id,
  140. })
  141. # customer invoice
  142. customer_invoice_lines = [(0, False, {
  143. 'name': 'Test description #1',
  144. 'account_id': self.revenue.id,
  145. 'quantity': 1.0,
  146. 'price_unit': 100.0,
  147. }), (0, False, {
  148. 'name': 'Test description #2',
  149. 'account_id': self.revenue.id,
  150. 'quantity': 2.0,
  151. 'price_unit': 25.0,
  152. })]
  153. self.invoice_out = self.env['account.invoice'].create({
  154. 'partner_id': self.partner.id,
  155. 'type': 'out_invoice',
  156. 'invoice_line_ids': customer_invoice_lines,
  157. 'account_id': self.partner.property_account_receivable_id.id,
  158. 'journal_id': self.journal_sale.id,
  159. })
  160. self.invoice_out.action_invoice_open()
  161. # vendor bill
  162. vendor_invoice_lines = [(0, False, {
  163. 'name': 'Test description #1',
  164. 'account_id': self.revenue.id,
  165. 'quantity': 1.0,
  166. 'price_unit': 100.0,
  167. }), (0, False, {
  168. 'name': 'Test description #2',
  169. 'account_id': self.revenue.id,
  170. 'quantity': 2.0,
  171. 'price_unit': 25.0,
  172. })]
  173. self.invoice_in = self.env['account.invoice'].create({
  174. 'partner_id': self.partner.id,
  175. 'type': 'in_invoice',
  176. 'invoice_line_ids': vendor_invoice_lines,
  177. 'account_id': self.partner.property_account_payable_id.id,
  178. 'journal_id': self.journal_purchase.id,
  179. })
  180. self.invoice_in.action_invoice_open()
  181. def setUp(self):
  182. super(AbstractTest, self).setUp()
  183. self.with_context()
  184. self._chart_template_create()
  185. self._add_chart_of_accounts()
  186. self._journals_create()
  187. self._invoice_create()
  188. self.model = self._getReportModel()
  189. self.qweb_report_name = self._getQwebReportName()
  190. self.xlsx_report_name = self._getXlsxReportName()
  191. self.xlsx_action_name = self._getXlsxReportActionName()
  192. self.report_title = self._getReportTitle()
  193. self.base_filters = self._getBaseFilters()
  194. self.additional_filters = self._getAdditionalFiltersToBeTested()
  195. self.report = self.model.create(self.base_filters)
  196. self.report.compute_data_for_report()
  197. def test_html(self):
  198. test_reports.try_report(self.env.cr, self.env.uid,
  199. self.qweb_report_name,
  200. [self.report.id],
  201. report_type='qweb-html')
  202. def test_qweb(self):
  203. test_reports.try_report(self.env.cr, self.env.uid,
  204. self.qweb_report_name,
  205. [self.report.id],
  206. report_type='qweb-pdf')
  207. def test_xlsx(self):
  208. test_reports.try_report(self.env.cr, self.env.uid,
  209. self.xlsx_report_name,
  210. [self.report.id],
  211. report_type='xlsx')
  212. def test_print(self):
  213. self.report.print_report('qweb')
  214. self.report.print_report('xlsx')
  215. def test_02_generation_report_html(self):
  216. """Check if report HTML is correctly generated"""
  217. # Check if returned report action is correct
  218. report_type = 'qweb-html'
  219. report_action = self.report.print_report(report_type)
  220. self.assertDictContainsSubset(
  221. {
  222. 'type': 'ir.actions.report',
  223. 'report_name': self.qweb_report_name,
  224. 'report_type': 'qweb-html',
  225. },
  226. report_action
  227. )
  228. # Check if report template is correct
  229. report = self.env['ir.actions.report'].search(
  230. [('report_name', '=', self.qweb_report_name),
  231. ('report_type', '=', report_type)], limit=1)
  232. self.assertEqual(report.report_type, 'qweb-html')
  233. rep = report.render(self.report.ids, {})
  234. self.assertTrue(self.report_title.encode('utf8') in rep[0])
  235. self.assertTrue(
  236. self.report.account_ids[0].name.encode('utf8') in rep[0]
  237. )
  238. def test_04_compute_data(self):
  239. """Check that the SQL queries work with all filters options"""
  240. for filters in [{}] + self.additional_filters:
  241. current_filter = self.base_filters.copy()
  242. current_filter.update(filters)
  243. report = self.model.create(current_filter)
  244. report.compute_data_for_report()
  245. self.assertGreaterEqual(len(report.account_ids), 1)
  246. # Same filters with only one account
  247. current_filter = self.base_filters.copy()
  248. current_filter.update(filters)
  249. report_accounts = report.account_ids.filtered('account_id')
  250. current_filter.update({
  251. 'filter_account_ids':
  252. [(6, 0, report_accounts[0].account_id.ids)],
  253. })
  254. report2 = self.model.create(current_filter)
  255. report2.compute_data_for_report()
  256. self.assertEqual(len(report2.account_ids), 1)
  257. self.assertEqual(report2.account_ids.name,
  258. report_accounts[0].name)
  259. if self._partner_test_is_possible(filters):
  260. # Same filters with only one partner
  261. report_partner_ids = report.account_ids.mapped('partner_ids')
  262. partner_ids = report_partner_ids.mapped('partner_id')
  263. current_filter = self.base_filters.copy()
  264. current_filter.update(filters)
  265. current_filter.update({
  266. 'filter_partner_ids': [(6, 0, partner_ids[0].ids)],
  267. })
  268. report3 = self.model.create(current_filter)
  269. report3.compute_data_for_report()
  270. self.assertGreaterEqual(len(report3.account_ids), 1)
  271. report_partner_ids3 = report3.account_ids.mapped('partner_ids')
  272. partner_ids3 = report_partner_ids3.mapped('partner_id')
  273. self.assertEqual(len(partner_ids3), 1)
  274. self.assertEqual(
  275. partner_ids3.name,
  276. partner_ids[0].name
  277. )
  278. # Same filters with only one partner and one account
  279. report_partner_ids = report3.account_ids.mapped('partner_ids')
  280. report_account_id = report_partner_ids.filtered(
  281. lambda p: p.partner_id
  282. )[0].report_account_id
  283. current_filter = self.base_filters.copy()
  284. current_filter.update(filters)
  285. current_filter.update({
  286. 'filter_account_ids':
  287. [(6, 0, report_account_id.account_id.ids)],
  288. 'filter_partner_ids': [(6, 0, partner_ids[0].ids)],
  289. })
  290. report4 = self.model.create(current_filter)
  291. report4.compute_data_for_report()
  292. self.assertEqual(len(report4.account_ids), 1)
  293. self.assertEqual(report4.account_ids.name,
  294. report_account_id.account_id.name)
  295. report_partner_ids4 = report4.account_ids.mapped('partner_ids')
  296. partner_ids4 = report_partner_ids4.mapped('partner_id')
  297. self.assertEqual(len(partner_ids4), 1)
  298. self.assertEqual(
  299. partner_ids4.name,
  300. partner_ids[0].name
  301. )
  302. def _partner_test_is_possible(self, filters):
  303. """
  304. :return:
  305. a boolean to indicate if partner test is possible
  306. with current filters
  307. """
  308. return True
  309. def _getReportModel(self):
  310. """
  311. :return: the report model name
  312. """
  313. raise NotImplementedError()
  314. def _getQwebReportName(self):
  315. """
  316. :return: the qweb report name
  317. """
  318. raise NotImplementedError()
  319. def _getXlsxReportName(self):
  320. """
  321. :return: the xlsx report name
  322. """
  323. raise NotImplementedError()
  324. def _getXlsxReportActionName(self):
  325. """
  326. :return: the xlsx report action name
  327. """
  328. raise NotImplementedError()
  329. def _getReportTitle(self):
  330. """
  331. :return: the report title displayed into the report
  332. """
  333. raise NotImplementedError()
  334. def _getBaseFilters(self):
  335. """
  336. :return: the minimum required filters to generate report
  337. """
  338. raise NotImplementedError()
  339. def _getAdditionalFiltersToBeTested(self):
  340. """
  341. :return: the additional filters to generate report variants
  342. """
  343. raise NotImplementedError()