test_tax.py 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171
  1. # -*- coding: utf-8 -*-
  2. from odoo.addons.account.tests.common import AccountTestInvoicingCommon
  3. from odoo.tests import tagged
  4. class TestTaxCommon(AccountTestInvoicingCommon):
  5. @classmethod
  6. def setUpClass(cls, chart_template_ref=None):
  7. super().setUpClass(chart_template_ref=chart_template_ref)
  8. # Setup another company having a rounding of 1.0.
  9. cls.currency_data['currency'].rounding = 1.0
  10. cls.currency_no_decimal = cls.currency_data['currency']
  11. cls.company_data_2 = cls.setup_company_data('company_2', currency_id=cls.currency_no_decimal.id)
  12. cls.env.user.company_id = cls.company_data['company']
  13. cls.fixed_tax = cls.env['account.tax'].create({
  14. 'name': "Fixed tax",
  15. 'amount_type': 'fixed',
  16. 'amount': 10,
  17. 'sequence': 1,
  18. })
  19. cls.fixed_tax_bis = cls.env['account.tax'].create({
  20. 'name': "Fixed tax bis",
  21. 'amount_type': 'fixed',
  22. 'amount': 15,
  23. 'sequence': 2,
  24. })
  25. cls.percent_tax = cls.env['account.tax'].create({
  26. 'name': "Percent tax",
  27. 'amount_type': 'percent',
  28. 'amount': 10,
  29. 'sequence': 3,
  30. })
  31. cls.percent_tax_bis = cls.env['account.tax'].create({
  32. 'name': "Percent tax bis",
  33. 'amount_type': 'percent',
  34. 'amount': 10,
  35. 'sequence': 4,
  36. })
  37. cls.division_tax = cls.env['account.tax'].create({
  38. 'name': "Division tax",
  39. 'amount_type': 'division',
  40. 'amount': 10,
  41. 'sequence': 4,
  42. })
  43. cls.group_tax = cls.env['account.tax'].create({
  44. 'name': "Group tax",
  45. 'amount_type': 'group',
  46. 'amount': 0,
  47. 'sequence': 5,
  48. 'children_tax_ids': [
  49. (4, cls.fixed_tax.id, 0),
  50. (4, cls.percent_tax.id, 0)
  51. ]
  52. })
  53. cls.group_tax_bis = cls.env['account.tax'].create({
  54. 'name': "Group tax bis",
  55. 'amount_type': 'group',
  56. 'amount': 0,
  57. 'sequence': 6,
  58. 'children_tax_ids': [
  59. (4, cls.fixed_tax.id, 0),
  60. (4, cls.percent_tax.id, 0)
  61. ]
  62. })
  63. cls.group_tax_percent = cls.env['account.tax'].create({
  64. 'name': "Group tax percent",
  65. 'amount_type': 'group',
  66. 'amount': 0,
  67. 'sequence': 6,
  68. 'children_tax_ids': [
  69. (4, cls.percent_tax.id, 0),
  70. (4, cls.percent_tax_bis.id, 0)
  71. ]
  72. })
  73. cls.group_of_group_tax = cls.env['account.tax'].create({
  74. 'name': "Group of group tax",
  75. 'amount_type': 'group',
  76. 'amount': 0,
  77. 'sequence': 7,
  78. 'children_tax_ids': [
  79. (4, cls.group_tax.id, 0),
  80. (4, cls.group_tax_bis.id, 0)
  81. ]
  82. })
  83. cls.tax_with_no_account = cls.env['account.tax'].create({
  84. 'name': "Tax with no account",
  85. 'amount_type': 'fixed',
  86. 'amount': 0,
  87. 'sequence': 8,
  88. })
  89. some_account = cls.env['account.account'].search([], limit=1)
  90. cls.tax_with_account = cls.env['account.tax'].create({
  91. 'name': "Tax with account",
  92. 'amount_type': 'fixed',
  93. 'amount': 0,
  94. 'sequence': 8,
  95. 'invoice_repartition_line_ids': [
  96. (0, 0, {'repartition_type': 'base'}),
  97. (0, 0, {
  98. 'repartition_type': 'tax',
  99. 'account_id': some_account.id,
  100. }),
  101. ],
  102. 'refund_repartition_line_ids': [
  103. (0, 0, {'repartition_type': 'base'}),
  104. (0, 0, {
  105. 'repartition_type': 'tax',
  106. 'account_id': some_account.id,
  107. }),
  108. ],
  109. })
  110. cls.tax_0_percent = cls.env['account.tax'].with_company(cls.company_data['company']).create({
  111. 'name': "test_0_percent",
  112. 'amount_type': 'percent',
  113. 'amount': 0,
  114. })
  115. cls.tax_5_percent = cls.env['account.tax'].with_company(cls.company_data['company']).create({
  116. 'name': "test_5_percent",
  117. 'amount_type': 'percent',
  118. 'amount': 5,
  119. })
  120. cls.tax_8_percent = cls.env['account.tax'].with_company(cls.company_data['company']).create({
  121. 'name': "test_8_percent",
  122. 'amount_type': 'percent',
  123. 'amount': 8,
  124. })
  125. cls.tax_12_percent = cls.env['account.tax'].with_company(cls.company_data['company']).create({
  126. 'name': "test_12_percent",
  127. 'amount_type': 'percent',
  128. 'amount': 12,
  129. })
  130. cls.tax_19_percent = cls.env['account.tax'].with_company(cls.company_data_2['company']).create({
  131. 'name': "test_19_percent",
  132. 'amount_type': 'percent',
  133. 'amount': 19,
  134. })
  135. cls.tax_21_percent = cls.env['account.tax'].with_company(cls.company_data['company']).create({
  136. 'name': "test_21_percent",
  137. 'amount_type': 'percent',
  138. 'amount': 19,
  139. })
  140. cls.tax_21_percent = cls.env['account.tax'].with_company(cls.company_data['company']).create({
  141. 'name': "test_rounding_methods_2",
  142. 'amount_type': 'percent',
  143. 'amount': 21,
  144. })
  145. cls.bank_journal = cls.company_data['default_journal_bank']
  146. cls.bank_account = cls.bank_journal.default_account_id
  147. cls.expense_account = cls.company_data['default_account_expense']
  148. def _check_compute_all_results(self, total_included, total_excluded, taxes, res):
  149. self.assertAlmostEqual(res['total_included'], total_included)
  150. self.assertAlmostEqual(res['total_excluded'], total_excluded)
  151. for i in range(0, len(taxes)):
  152. self.assertAlmostEqual(res['taxes'][i]['base'], taxes[i][0])
  153. self.assertAlmostEqual(res['taxes'][i]['amount'], taxes[i][1])
  154. @tagged('post_install', '-at_install')
  155. class TestTax(TestTaxCommon):
  156. @classmethod
  157. def setUpClass(cls):
  158. super(TestTax, cls).setUpClass()
  159. def test_tax_group_of_group_tax(self):
  160. self.fixed_tax.include_base_amount = True
  161. res = self.group_of_group_tax.compute_all(200.0)
  162. self._check_compute_all_results(
  163. 263, # 'total_included'
  164. 200, # 'total_excluded'
  165. [
  166. # base , amount | seq | amount | incl | incl_base
  167. # ---------------------------------------------------
  168. (200.0, 10.0), # | 1 | 10 | | t
  169. (210.0, 21.0), # | 3 | 10% | |
  170. (210.0, 10.0), # | 1 | 10 | | t
  171. (220.0, 22.0), # | 3 | 10% | |
  172. # ---------------------------------------------------
  173. ],
  174. res
  175. )
  176. def test_tax_group(self):
  177. res = self.group_tax.compute_all(200.0)
  178. self._check_compute_all_results(
  179. 230, # 'total_included'
  180. 200, # 'total_excluded'
  181. [
  182. # base , amount | seq | amount | incl | incl_base
  183. # ---------------------------------------------------
  184. (200.0, 10.0), # | 1 | 10 | |
  185. (200.0, 20.0), # | 3 | 10% | |
  186. # ---------------------------------------------------
  187. ],
  188. res
  189. )
  190. def test_tax_group_percent(self):
  191. res = self.group_tax_percent.with_context({'force_price_include':True}).compute_all(100.0)
  192. self._check_compute_all_results(
  193. 100, # 'total_included'
  194. 83.33, # 'total_excluded'
  195. [
  196. # base , amount | seq | amount | incl | incl_base
  197. # ---------------------------------------------------
  198. (83.33, 8.33), # | 1 | 10% | |
  199. (83.33, 8.34), # | 2 | 10% | |
  200. # ---------------------------------------------------
  201. ],
  202. res
  203. )
  204. def test_tax_percent_division(self):
  205. self.division_tax.price_include = True
  206. self.division_tax.include_base_amount = True
  207. res_division = self.division_tax.compute_all(200.0)
  208. self._check_compute_all_results(
  209. 200, # 'total_included'
  210. 180, # 'total_excluded'
  211. [
  212. # base , amount | seq | amount | incl | incl_base
  213. # ---------------------------------------------------
  214. (180.0, 20.0), # | 4 | 10/ | t | t
  215. # ---------------------------------------------------
  216. ],
  217. res_division
  218. )
  219. self.percent_tax.price_include = False
  220. self.percent_tax.include_base_amount = False
  221. res_percent = self.percent_tax.compute_all(100.0)
  222. self._check_compute_all_results(
  223. 110, # 'total_included'
  224. 100, # 'total_excluded'
  225. [
  226. # base , amount | seq | amount | incl | incl_base
  227. # ---------------------------------------------------
  228. (100.0, 10.0), # | 3 | 10% | |
  229. # ---------------------------------------------------
  230. ],
  231. res_percent
  232. )
  233. self.division_tax.price_include = False
  234. self.division_tax.include_base_amount = False
  235. res_division = self.division_tax.compute_all(180.0)
  236. self._check_compute_all_results(
  237. 200, # 'total_included'
  238. 180, # 'total_excluded'
  239. [
  240. # base, amount | seq | amount | incl | incl_base
  241. # ---------------------------------------------------
  242. (180.0, 20.0), # | 4 | 10/ | |
  243. # ---------------------------------------------------
  244. ],
  245. res_division
  246. )
  247. self.percent_tax.price_include = True
  248. self.percent_tax.include_base_amount = True
  249. res_percent = self.percent_tax.compute_all(110.0)
  250. self._check_compute_all_results(
  251. 110, # 'total_included'
  252. 100, # 'total_excluded'
  253. [
  254. # base, amount | seq | amount | incl | incl_base
  255. # ---------------------------------------------------
  256. (100.0, 10.0), # | 3 | 10% | t | t
  257. # ---------------------------------------------------
  258. ],
  259. res_percent
  260. )
  261. self.percent_tax_bis.price_include = True
  262. self.percent_tax_bis.include_base_amount = True
  263. self.percent_tax_bis.amount = 21
  264. res_percent = self.percent_tax_bis.compute_all(7.0)
  265. self._check_compute_all_results(
  266. 7.0, # 'total_included'
  267. 5.79, # 'total_excluded'
  268. [
  269. # base , amount | seq | amount | incl | incl_base
  270. # ---------------------------------------------------
  271. (5.79, 1.21), # | 3 | 21% | t | t
  272. # ---------------------------------------------------
  273. ],
  274. res_percent
  275. )
  276. def test_tax_sequence_normalized_set(self):
  277. self.division_tax.sequence = 1
  278. self.fixed_tax.sequence = 2
  279. self.percent_tax.sequence = 3
  280. taxes_set = (self.group_tax | self.division_tax)
  281. res = taxes_set.compute_all(200.0)
  282. self._check_compute_all_results(
  283. 252.22, # 'total_included'
  284. 200, # 'total_excluded'
  285. [
  286. # base , amount | seq | amount | incl | incl_base
  287. # ---------------------------------------------------
  288. (200.0, 22.22), # | 1 | 10/ | |
  289. (200.0, 10.0), # | 2 | 10 | |
  290. (200.0, 20.0), # | 3 | 10% | |
  291. # ---------------------------------------------------
  292. ],
  293. res
  294. )
  295. def test_fixed_tax_include_base_amount(self):
  296. self.fixed_tax.include_base_amount = True
  297. res = self.group_tax.compute_all(200.0)
  298. self._check_compute_all_results(
  299. 231, # 'total_included'
  300. 200, # 'total_excluded'
  301. [
  302. # base , amount | seq | amount | incl | incl_base
  303. # ---------------------------------------------------
  304. (200.0, 10.0), # | 1 | 10 | | t
  305. (210.0, 21.0), # | 3 | 10% | |
  306. # ---------------------------------------------------
  307. ],
  308. res
  309. )
  310. self.fixed_tax.price_include = True
  311. self.fixed_tax.include_base_amount = False
  312. res = self.fixed_tax.compute_all(100.0, quantity=2.0)
  313. self._check_compute_all_results(
  314. 200, # 'total_included'
  315. 180, # 'total_excluded'
  316. [
  317. # base , amount | seq | amount | incl | incl_base
  318. # ---------------------------------------------------
  319. (180.0, 20.0), # | 1 | 20 | | t
  320. # ---------------------------------------------------
  321. ],
  322. res
  323. )
  324. def test_percent_tax_include_base_amount(self):
  325. self.percent_tax.price_include = True
  326. self.percent_tax.amount = 21.0
  327. res = self.percent_tax.compute_all(7.0)
  328. self._check_compute_all_results(
  329. 7.0, # 'total_included'
  330. 5.79, # 'total_excluded'
  331. [
  332. # base , amount | seq | amount | incl | incl_base
  333. # ---------------------------------------------------
  334. (5.79, 1.21), # | 3 | 21% | t |
  335. # ---------------------------------------------------
  336. ],
  337. res
  338. )
  339. self.percent_tax.price_include = True
  340. self.percent_tax.amount = 20.0
  341. res = self.percent_tax.compute_all(399.99)
  342. self._check_compute_all_results(
  343. 399.99, # 'total_included'
  344. 333.33, # 'total_excluded'
  345. [
  346. # base , amount | seq | amount | incl | incl_base
  347. # ---------------------------------------------------
  348. (333.33, 66.66), # | 3 | 20% | t |
  349. # ---------------------------------------------------
  350. ],
  351. res
  352. )
  353. def test_tax_decimals(self):
  354. """Test the rounding of taxes up to 6 decimals (maximum decimals places allowed for currencies)"""
  355. self.env.user.company_id.currency_id.rounding = 0.000001
  356. self.percent_tax.price_include = True
  357. self.percent_tax.amount = 21.0
  358. res = self.percent_tax.compute_all(7.0)
  359. self._check_compute_all_results(
  360. 7.0, # 'total_included'
  361. 5.785124, # 'total_excluded'
  362. [
  363. # base , amount | seq | amount | incl | incl_base
  364. # --------------------------------------------------------
  365. (5.785124, 1.214876), # | 3 | 21% | t |
  366. # --------------------------------------------------------
  367. ],
  368. res
  369. )
  370. self.percent_tax.price_include = True
  371. self.percent_tax.amount = 20.0
  372. res = self.percent_tax.compute_all(399.999999)
  373. self._check_compute_all_results(
  374. 399.999999, # 'total_included'
  375. 333.333333, # 'total_excluded'
  376. [
  377. # base , amount | seq | amount | incl | incl_base
  378. # -----------------------------------------------------------
  379. (333.333333, 66.666666), # | 3 | 20% | t |
  380. # -----------------------------------------------------------
  381. ],
  382. res
  383. )
  384. def test_advanced_taxes_computation_0(self):
  385. '''Test more advanced taxes computation (see issue 34471).'''
  386. tax_1 = self.env['account.tax'].create({
  387. 'name': 'test_advanced_taxes_computation_0_1',
  388. 'amount_type': 'percent',
  389. 'amount': 10,
  390. 'price_include': True,
  391. 'include_base_amount': True,
  392. 'sequence': 1,
  393. 'invoice_repartition_line_ids': [
  394. (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}),
  395. (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
  396. (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
  397. ],
  398. 'refund_repartition_line_ids': [
  399. (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}),
  400. (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
  401. (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
  402. ],
  403. })
  404. tax_2 = self.env['account.tax'].create({
  405. 'name': 'test_advanced_taxes_computation_0_2',
  406. 'amount_type': 'percent',
  407. 'amount': 10,
  408. 'sequence': 2,
  409. 'invoice_repartition_line_ids': [
  410. (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}),
  411. (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
  412. (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
  413. ],
  414. 'refund_repartition_line_ids': [
  415. (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}),
  416. (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
  417. (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
  418. ],
  419. })
  420. tax_3 = self.env['account.tax'].create({
  421. 'name': 'test_advanced_taxes_computation_0_3',
  422. 'amount_type': 'percent',
  423. 'amount': 10,
  424. 'price_include': True,
  425. 'sequence': 3,
  426. 'invoice_repartition_line_ids': [
  427. (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}),
  428. (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
  429. (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
  430. ],
  431. 'refund_repartition_line_ids': [
  432. (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}),
  433. (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
  434. (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
  435. ],
  436. })
  437. tax_4 = self.env['account.tax'].create({
  438. 'name': 'test_advanced_taxes_computation_0_4',
  439. 'amount_type': 'percent',
  440. 'amount': 10,
  441. 'sequence': 4,
  442. 'invoice_repartition_line_ids': [
  443. (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}),
  444. (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
  445. (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
  446. ],
  447. 'refund_repartition_line_ids': [
  448. (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}),
  449. (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
  450. (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
  451. ],
  452. })
  453. tax_5 = self.env['account.tax'].create({
  454. 'name': 'test_advanced_taxes_computation_0_5',
  455. 'amount_type': 'percent',
  456. 'amount': 10,
  457. 'price_include': True,
  458. 'sequence': 5,
  459. 'invoice_repartition_line_ids': [
  460. (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}),
  461. (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
  462. (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
  463. ],
  464. 'refund_repartition_line_ids': [
  465. (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}),
  466. (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
  467. (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
  468. ],
  469. })
  470. taxes = tax_1 + tax_2 + tax_3 + tax_4 + tax_5
  471. # Test with positive amount.
  472. self._check_compute_all_results(
  473. 154, # 'total_included'
  474. 100, # 'total_excluded'
  475. [
  476. # base , amount | seq | amount | incl | incl_base
  477. # ---------------------------------------------------
  478. (100.0, 5.0), # | 1 | 10% | t | t
  479. (100.0, 5.0), # | 1 | 10% | t | t
  480. (110.0, 5.5), # | 2 | 10% | |
  481. (110.0, 5.5), # | 2 | 10% | |
  482. (110.0, 5.5), # | 3 | 10% | t |
  483. (110.0, 5.5), # | 3 | 10% | t |
  484. (110.0, 5.5), # | 4 | 10% | |
  485. (110.0, 5.5), # | 4 | 10% | |
  486. (110.0, 5.5), # | 5 | 10% | t |
  487. (110.0, 5.5), # | 5 | 10% | t |
  488. # ---------------------------------------------------
  489. ],
  490. taxes.compute_all(132.0)
  491. )
  492. # Test with negative amount.
  493. self._check_compute_all_results(
  494. -154, # 'total_included'
  495. -100, # 'total_excluded'
  496. [
  497. # base , amount | seq | amount | incl | incl_base
  498. # ---------------------------------------------------
  499. (-100.0, -5.0), # | 1 | 10% | t | t
  500. (-100.0, -5.0), # | 1 | 10% | t | t
  501. (-110.0, -5.5), # | 2 | 10% | |
  502. (-110.0, -5.5), # | 2 | 10% | |
  503. (-110.0, -5.5), # | 3 | 10% | t |
  504. (-110.0, -5.5), # | 3 | 10% | t |
  505. (-110.0, -5.5), # | 4 | 10% | |
  506. (-110.0, -5.5), # | 4 | 10% | |
  507. (-110.0, -5.5), # | 5 | 10% | t |
  508. (-110.0, -5.5), # | 5 | 10% | t |
  509. # ---------------------------------------------------
  510. ],
  511. taxes.compute_all(-132.0)
  512. )
  513. def test_intracomm_taxes_computation_0(self):
  514. ''' Test usage of intracomm taxes having e.g.+100%, -100% as repartition lines. '''
  515. intracomm_tax = self.env['account.tax'].create({
  516. 'name': 'test_intracomm_taxes_computation_0_1',
  517. 'amount_type': 'percent',
  518. 'amount': 21,
  519. 'invoice_repartition_line_ids': [
  520. (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}),
  521. (0, 0, {'repartition_type': 'tax', 'factor_percent': 100.0}),
  522. (0, 0, {'repartition_type': 'tax', 'factor_percent': -100.0}),
  523. ],
  524. 'refund_repartition_line_ids': [
  525. (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}),
  526. (0, 0, {'repartition_type': 'tax', 'factor_percent': 100.0}),
  527. (0, 0, {'repartition_type': 'tax', 'factor_percent': -100.0}),
  528. ],
  529. })
  530. # Test with positive amount.
  531. self._check_compute_all_results(
  532. 100, # 'total_included'
  533. 100, # 'total_excluded'
  534. [
  535. # base , amount
  536. # ---------------
  537. (100.0, 21.0),
  538. (100.0, -21.0),
  539. # ---------------
  540. ],
  541. intracomm_tax.compute_all(100.0)
  542. )
  543. # Test with negative amount.
  544. self._check_compute_all_results(
  545. -100, # 'total_included'
  546. -100, # 'total_excluded'
  547. [
  548. # base , amount
  549. # ---------------
  550. (-100.0, -21.0),
  551. (-100.0, 21.0),
  552. # ---------------
  553. ],
  554. intracomm_tax.compute_all(-100.0)
  555. )
  556. def test_rounding_issues_0(self):
  557. ''' Test taxes having a complex setup of repartition lines. '''
  558. tax = self.env['account.tax'].create({
  559. 'name': 'test_rounding_issues_0',
  560. 'amount_type': 'percent',
  561. 'amount': 3,
  562. 'invoice_repartition_line_ids': [
  563. (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}),
  564. (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
  565. (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
  566. (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
  567. (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
  568. (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
  569. (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
  570. ],
  571. 'refund_repartition_line_ids': [
  572. (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}),
  573. (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
  574. (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
  575. (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
  576. (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
  577. (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
  578. (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
  579. ],
  580. })
  581. # Test with positive amount.
  582. self._check_compute_all_results(
  583. 1.09, # 'total_included'
  584. 1, # 'total_excluded'
  585. [
  586. # base , amount
  587. # ---------------
  588. (1.0, 0.01),
  589. (1.0, 0.01),
  590. (1.0, 0.01),
  591. (1.0, 0.02),
  592. (1.0, 0.02),
  593. (1.0, 0.02),
  594. # ---------------
  595. ],
  596. tax.compute_all(1.0)
  597. )
  598. # Test with negative amount.
  599. self._check_compute_all_results(
  600. -1.09, # 'total_included'
  601. -1, # 'total_excluded'
  602. [
  603. # base , amount
  604. # ---------------
  605. (-1.0, -0.01),
  606. (-1.0, -0.01),
  607. (-1.0, -0.01),
  608. (-1.0, -0.02),
  609. (-1.0, -0.02),
  610. (-1.0, -0.02),
  611. # ---------------
  612. ],
  613. tax.compute_all(-1.0)
  614. )
  615. def test_rounding_issues_1(self):
  616. ''' Test taxes having a complex setup of repartition lines. '''
  617. tax = self.env['account.tax'].create({
  618. 'name': 'test_advanced_taxes_repartition_lines_computation_1',
  619. 'amount_type': 'percent',
  620. 'amount': 3,
  621. 'invoice_repartition_line_ids': [
  622. (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}),
  623. (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
  624. (0, 0, {'repartition_type': 'tax', 'factor_percent': -50.0}),
  625. (0, 0, {'repartition_type': 'tax', 'factor_percent': 25.0}),
  626. (0, 0, {'repartition_type': 'tax', 'factor_percent': 25.0}),
  627. (0, 0, {'repartition_type': 'tax', 'factor_percent': -25.0}),
  628. (0, 0, {'repartition_type': 'tax', 'factor_percent': -25.0}),
  629. ],
  630. 'refund_repartition_line_ids': [
  631. (0, 0, {'repartition_type': 'base', 'factor_percent': 100.0}),
  632. (0, 0, {'repartition_type': 'tax', 'factor_percent': 50.0}),
  633. (0, 0, {'repartition_type': 'tax', 'factor_percent': -50.0}),
  634. (0, 0, {'repartition_type': 'tax', 'factor_percent': 25.0}),
  635. (0, 0, {'repartition_type': 'tax', 'factor_percent': 25.0}),
  636. (0, 0, {'repartition_type': 'tax', 'factor_percent': -25.0}),
  637. (0, 0, {'repartition_type': 'tax', 'factor_percent': -25.0}),
  638. ],
  639. })
  640. # Test with positive amount.
  641. self._check_compute_all_results(
  642. 1, # 'total_included'
  643. 1, # 'total_excluded'
  644. [
  645. # base , amount
  646. # ---------------
  647. (1.0, 0.02),
  648. (1.0, -0.02),
  649. (1.0, 0.01),
  650. (1.0, 0.01),
  651. (1.0, -0.01),
  652. (1.0, -0.01),
  653. # ---------------
  654. ],
  655. tax.compute_all(1.0)
  656. )
  657. # Test with negative amount.
  658. self._check_compute_all_results(
  659. -1, # 'total_included'
  660. -1, # 'total_excluded'
  661. [
  662. # base , amount
  663. # ---------------
  664. (-1.0, -0.02),
  665. (-1.0, 0.02),
  666. (-1.0, -0.01),
  667. (-1.0, -0.01),
  668. (-1.0, 0.01),
  669. (-1.0, 0.01),
  670. # ---------------
  671. ],
  672. tax.compute_all(-1.0)
  673. )
  674. def test_rounding_tax_excluded_round_per_line_01(self):
  675. ''' Test the rounding of a 19% price excluded tax in an invoice having 22689 and 9176 as lines.
  676. The decimal precision is set to zero.
  677. The computation must be similar to round(22689 * 0.19) + round(9176 * 0.19).
  678. '''
  679. self.tax_19_percent.company_id.currency_id.rounding = 1.0
  680. self.tax_19_percent.company_id.tax_calculation_rounding_method = 'round_per_line'
  681. res1 = self.tax_19_percent.compute_all(22689)
  682. self._check_compute_all_results(
  683. 27000, # 'total_included'
  684. 22689, # 'total_excluded'
  685. [
  686. # base, amount
  687. # ---------------
  688. (22689, 4311),
  689. # ---------------
  690. ],
  691. res1
  692. )
  693. res2 = self.tax_19_percent.compute_all(9176)
  694. self._check_compute_all_results(
  695. 10919, # 'total_included'
  696. 9176, # 'total_excluded'
  697. [
  698. # base , amount
  699. # ---------------
  700. (9176, 1743),
  701. # ---------------
  702. ],
  703. res2
  704. )
  705. def test_rounding_tax_excluded_round_globally(self):
  706. ''' Test the rounding of a 19% price excluded tax in an invoice having 22689 and 9176 as lines.
  707. The decimal precision is set to zero.
  708. The computation must be similar to round((22689 + 9176) * 0.19).
  709. '''
  710. self.tax_19_percent.company_id.tax_calculation_rounding_method = 'round_globally'
  711. res1 = self.tax_19_percent.compute_all(22689)
  712. self._check_compute_all_results(
  713. 27000, # 'total_included'
  714. 22689, # 'total_excluded'
  715. [
  716. # base, amount
  717. # ---------------
  718. (22689, 4310.91),
  719. # ---------------
  720. ],
  721. res1
  722. )
  723. res2 = self.tax_19_percent.compute_all(9176)
  724. self._check_compute_all_results(
  725. 10919, # 'total_included'
  726. 9176, # 'total_excluded'
  727. [
  728. # base , amount
  729. # ---------------
  730. (9176, 1743.44),
  731. # ---------------
  732. ],
  733. res2
  734. )
  735. def test_rounding_tax_included_round_per_line_01(self):
  736. ''' Test the rounding of a 19% price included tax in an invoice having 27000 and 10920 as lines.
  737. The decimal precision is set to zero.
  738. The computation must be similar to round(27000 / 1.19) + round(10920 / 1.19).
  739. '''
  740. self.tax_19_percent.price_include = True
  741. self.tax_19_percent.company_id.currency_id.rounding = 1.0
  742. self.tax_19_percent.company_id.tax_calculation_rounding_method = 'round_per_line'
  743. res1 = self.tax_19_percent.compute_all(27000)
  744. self._check_compute_all_results(
  745. 27000, # 'total_included'
  746. 22689, # 'total_excluded'
  747. [
  748. # base , amount
  749. # ---------------
  750. (22689, 4311),
  751. # ---------------
  752. ],
  753. res1
  754. )
  755. res2 = self.tax_19_percent.compute_all(10920)
  756. self._check_compute_all_results(
  757. 10920, # 'total_included'
  758. 9176, # 'total_excluded'
  759. [
  760. # base , amount
  761. # ---------------
  762. (9176, 1744),
  763. # ---------------
  764. ],
  765. res2
  766. )
  767. def test_rounding_tax_included_round_per_line_02(self):
  768. ''' Test the rounding of a 12% price included tax in an invoice having 52.50 as line.
  769. The decimal precision is set to 2.
  770. '''
  771. self.tax_12_percent.price_include = True
  772. self.tax_12_percent.company_id.currency_id.rounding = 0.01
  773. res1 = self.tax_12_percent.compute_all(52.50)
  774. self._check_compute_all_results(
  775. 52.50, # 'total_included'
  776. 46.88, # 'total_excluded'
  777. [
  778. # base , amount
  779. # -------------
  780. (46.88, 5.62),
  781. # -------------
  782. ],
  783. res1
  784. )
  785. def test_rounding_tax_included_round_per_line_03(self):
  786. ''' Test the rounding of a 8% and 0% price included tax in an invoice having 8 * 15.55 as line.
  787. The decimal precision is set to 2.
  788. '''
  789. self.tax_0_percent.company_id.currency_id.rounding = 0.01
  790. self.tax_0_percent.price_include = True
  791. self.tax_8_percent.price_include = True
  792. self.group_tax.children_tax_ids = [(6, 0, self.tax_0_percent.ids)]
  793. self.group_tax_bis.children_tax_ids = [(6, 0, self.tax_8_percent.ids)]
  794. res1 = (self.tax_8_percent | self.tax_0_percent).compute_all(15.55, quantity=8.0)
  795. self._check_compute_all_results(
  796. 124.40, # 'total_included'
  797. 115.19, # 'total_excluded'
  798. [
  799. # base , amount
  800. # -------------
  801. (115.19, 9.21),
  802. (115.19, 0.00),
  803. # -------------
  804. ],
  805. res1
  806. )
  807. res2 = (self.tax_0_percent | self.tax_8_percent).compute_all(15.55, quantity=8.0)
  808. self._check_compute_all_results(
  809. 124.40, # 'total_included'
  810. 115.19, # 'total_excluded'
  811. [
  812. # base , amount
  813. # -------------
  814. (115.19, 0.00),
  815. (115.19, 9.21),
  816. # -------------
  817. ],
  818. res2
  819. )
  820. def test_rounding_tax_included_round_per_line_04(self):
  821. ''' Test the rounding of a 5% price included tax.
  822. The decimal precision is set to 0.05.
  823. '''
  824. self.tax_5_percent.price_include = True
  825. self.tax_5_percent.company_id.currency_id.rounding = 0.05
  826. self.tax_5_percent.company_id.tax_calculation_rounding_method = 'round_per_line'
  827. res1 = self.tax_5_percent.compute_all(5)
  828. self._check_compute_all_results(
  829. 5, # 'total_included'
  830. 4.75, # 'total_excluded'
  831. [
  832. # base , amount
  833. # ---------------
  834. (4.75, 0.25),
  835. # ---------------
  836. ],
  837. res1
  838. )
  839. res2 = self.tax_5_percent.compute_all(10)
  840. self._check_compute_all_results(
  841. 10, # 'total_included'
  842. 9.5, # 'total_excluded'
  843. [
  844. # base , amount
  845. # ---------------
  846. (9.5, 0.5),
  847. # ---------------
  848. ],
  849. res2
  850. )
  851. res3 = self.tax_5_percent.compute_all(50)
  852. self._check_compute_all_results(
  853. 50, # 'total_included'
  854. 47.6, # 'total_excluded'
  855. [
  856. # base , amount
  857. # ---------------
  858. (47.6, 2.4),
  859. # ---------------
  860. ],
  861. res3
  862. )
  863. def test_rounding_tax_included_round_globally_01(self):
  864. ''' Test the rounding of a 19% price included tax in an invoice having 27000 and 10920 as lines.
  865. The decimal precision is set to zero.
  866. The computation must be similar to round((27000 + 10920) / 1.19).
  867. '''
  868. self.tax_19_percent.price_include = True
  869. self.tax_19_percent.company_id.tax_calculation_rounding_method = 'round_globally'
  870. res1 = self.tax_19_percent.compute_all(27000)
  871. self._check_compute_all_results(
  872. 27000, # 'total_included'
  873. 22689, # 'total_excluded'
  874. [
  875. # base , amount
  876. # ---------------
  877. (22689, 4311),
  878. # ---------------
  879. ],
  880. res1
  881. )
  882. res2 = self.tax_19_percent.compute_all(10920)
  883. self._check_compute_all_results(
  884. 10920, # 'total_included'
  885. 9176, # 'total_excluded'
  886. [
  887. # base , amount
  888. # ---------------
  889. (9176, 1744),
  890. # ---------------
  891. ],
  892. res2
  893. )
  894. def test_rounding_tax_included_round_globally_02(self):
  895. ''' Test the rounding of a 21% price included tax in an invoice having 11.90 and 2.80 as lines.
  896. The decimal precision is set to 2.
  897. '''
  898. self.tax_21_percent.price_include = True
  899. self.tax_21_percent.company_id.currency_id.rounding = 0.01
  900. self.tax_21_percent.company_id.tax_calculation_rounding_method = 'round_globally'
  901. res1 = self.tax_21_percent.compute_all(11.90)
  902. self._check_compute_all_results(
  903. 11.90, # 'total_included'
  904. 9.83, # 'total_excluded'
  905. [
  906. # base , amount
  907. # ---------------
  908. (9.83, 2.07),
  909. # ---------------
  910. ],
  911. res1
  912. )
  913. res2 = self.tax_21_percent.compute_all(2.80)
  914. self._check_compute_all_results(
  915. 2.80, # 'total_included'
  916. 2.31, # 'total_excluded'
  917. [
  918. # base , amount
  919. # ---------------
  920. (2.31, 0.49),
  921. # ---------------
  922. ],
  923. res2
  924. )
  925. def test_rounding_tax_included_round_globally_03(self):
  926. ''' Test the rounding of a 5% price included tax.
  927. The decimal precision is set to 0.05.
  928. '''
  929. self.tax_5_percent.price_include = True
  930. self.tax_5_percent.company_id.currency_id.rounding = 0.05
  931. self.tax_5_percent.company_id.tax_calculation_rounding_method = 'round_globally'
  932. res1 = self.tax_5_percent.compute_all(5)
  933. self._check_compute_all_results(
  934. 5, # 'total_included'
  935. 4.75, # 'total_excluded'
  936. [
  937. # base , amount
  938. # ---------------
  939. (4.75, 0.25),
  940. # ---------------
  941. ],
  942. res1
  943. )
  944. res2 = self.tax_5_percent.compute_all(10)
  945. self._check_compute_all_results(
  946. 10, # 'total_included'
  947. 9.5, # 'total_excluded'
  948. [
  949. # base , amount
  950. # ---------------
  951. (9.50, 0.50),
  952. # ---------------
  953. ],
  954. res2
  955. )
  956. res3 = self.tax_5_percent.compute_all(50)
  957. self._check_compute_all_results(
  958. 50, # 'total_included'
  959. 47.6, # 'total_excluded'
  960. [
  961. # base , amount
  962. # ---------------
  963. (47.60, 2.40),
  964. # ---------------
  965. ],
  966. res3
  967. )
  968. def test_is_base_affected(self):
  969. taxes = self.env['account.tax'].create([{
  970. 'name': 'test_is_base_affected%s' % i,
  971. 'amount_type': 'percent',
  972. 'amount': amount,
  973. 'include_base_amount': include_base_amount,
  974. 'is_base_affected': is_base_affected,
  975. 'sequence': i,
  976. } for i, amount, include_base_amount, is_base_affected in [
  977. (0, 6, True, True),
  978. (1, 6, True, False),
  979. (2, 10, False, True),
  980. ]])
  981. compute_all_results = taxes.compute_all(100.0)
  982. # Check the balance of the generated move lines
  983. self._check_compute_all_results(
  984. 123.2, # 'total_included'
  985. 100.0, # 'total_excluded'
  986. [
  987. # base, amount
  988. # -------------------------
  989. (100.0, 6.0),
  990. (100.0, 6.0),
  991. (112.0, 11.2),
  992. # -------------------------
  993. ],
  994. compute_all_results,
  995. )
  996. # Check the tax_ids on tax lines
  997. expected_tax_ids_list = [taxes[2].ids, taxes[2].ids, []]
  998. tax_ids_list = [tax_line['tax_ids'] for tax_line in compute_all_results['taxes']]
  999. self.assertEqual(tax_ids_list, expected_tax_ids_list, "Only a tax affected by previous taxes should have tax_ids set on its tax line when used after an 'include_base_amount' tax.")
  1000. def test_mixing_price_included_excluded_with_affect_base(self):
  1001. tax_10_fix = self.env['account.tax'].create({
  1002. 'name': "tax_10_fix",
  1003. 'amount_type': 'fixed',
  1004. 'amount': 10.0,
  1005. 'include_base_amount': True,
  1006. })
  1007. tax_21 = self.env['account.tax'].create({
  1008. 'name': "tax_21",
  1009. 'amount_type': 'percent',
  1010. 'amount': 21.0,
  1011. 'price_include': True,
  1012. 'include_base_amount': True,
  1013. })
  1014. self._check_compute_all_results(
  1015. 1222.1, # 'total_included'
  1016. 1000.0, # 'total_excluded'
  1017. [
  1018. # base , amount
  1019. # ---------------
  1020. (1000.0, 10.0),
  1021. (1010.0, 212.1),
  1022. # ---------------
  1023. ],
  1024. (tax_10_fix + tax_21).compute_all(1210),
  1025. )
  1026. def test_price_included_repartition_sum_0(self):
  1027. """ Tests the case where a tax with a non-zero value has a sum
  1028. of tax repartition factors of zero and is included in price. It
  1029. shouldn't behave in the same way as a 0% tax.
  1030. """
  1031. test_tax = self.env['account.tax'].create({
  1032. 'name': "Definitely not a 0% tax",
  1033. 'amount_type': 'percent',
  1034. 'amount': 42,
  1035. 'price_include': True,
  1036. 'invoice_repartition_line_ids': [
  1037. (0, 0, {'repartition_type': 'base'}),
  1038. (0, 0, {'repartition_type': 'tax'}),
  1039. (0, 0, {
  1040. 'factor_percent': -100,
  1041. 'repartition_type': 'tax',
  1042. }),
  1043. ],
  1044. 'refund_repartition_line_ids': [
  1045. (0, 0, {'repartition_type': 'base'}),
  1046. (0, 0, {'repartition_type': 'tax'}),
  1047. (0, 0, {
  1048. 'factor_percent': -100,
  1049. 'repartition_type': 'tax',
  1050. }),
  1051. ],
  1052. })
  1053. compute_all_res = test_tax.compute_all(100)
  1054. self._check_compute_all_results(
  1055. 100, # 'total_included'
  1056. 100, # 'total_excluded'
  1057. [
  1058. # base , amount
  1059. # ---------------
  1060. (100, 42),
  1061. (100, -42),
  1062. # ---------------
  1063. ],
  1064. compute_all_res
  1065. )
  1066. def test_parse_name_search(self):
  1067. list_ten_fixed_tax = self.env["account.tax"]
  1068. ten_fixed_tax = self.env["account.tax"].create(
  1069. {"name": "Ten Fixed tax", "amount_type": "fixed", "amount": 10}
  1070. )
  1071. list_ten_fixed_tax |= ten_fixed_tax
  1072. ten_fixed_tax_tix = self.env["account.tax"].create(
  1073. {"name": "Ten Fixed tax tix", "amount_type": "fixed", "amount": 10}
  1074. )
  1075. list_ten_fixed_tax |= ten_fixed_tax_tix
  1076. self.assertListEqual(
  1077. [x[0] for x in self.env["account.tax"].name_search("tix")],
  1078. list_ten_fixed_tax.ids,
  1079. )
  1080. self.assertListEqual(
  1081. [x[0] for x in self.env["account.tax"].name_search("\"tix\"")],
  1082. ten_fixed_tax_tix.ids,
  1083. )
  1084. self.assertListEqual(
  1085. [x[0] for x in self.env["account.tax"].name_search("Ten \"tix\"")],
  1086. ten_fixed_tax_tix.ids,
  1087. )