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.

329 lines
13 KiB

  1. # Copyright 2017 LasLabs Inc.
  2. # Copyright 2018 ACSONE SA/NV
  3. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
  4. from dateutil.relativedelta import relativedelta
  5. from odoo.tests.common import TransactionCase
  6. from odoo.exceptions import ValidationError
  7. from odoo.fields import Date
  8. class TestSaleOrder(TransactionCase):
  9. def setUp(self):
  10. super(TestSaleOrder, self).setUp()
  11. self.product1 = self.env.ref('product.product_product_1')
  12. self.product2 = self.env.ref('product.product_product_2')
  13. self.sale = self.env.ref('sale.sale_order_2')
  14. self.contract_template1 = self.env['contract.template'].create(
  15. {'name': 'Template 1'}
  16. )
  17. self.contract_template2 = self.env['contract.template'].create(
  18. {
  19. 'name': 'Template 2',
  20. 'contract_line_ids': [
  21. (
  22. 0,
  23. 0,
  24. {
  25. 'product_id': self.product2.id,
  26. 'name': 'Services from #START# to #END#',
  27. 'quantity': 1,
  28. 'uom_id': self.product2.uom_id.id,
  29. 'price_unit': 100,
  30. 'discount': 50,
  31. 'recurring_rule_type': 'yearly',
  32. 'recurring_interval': 1,
  33. },
  34. )
  35. ],
  36. }
  37. )
  38. self.product1.write(
  39. {
  40. 'is_contract': True,
  41. 'default_qty': 12,
  42. 'recurring_rule_type': "monthlylastday",
  43. 'recurring_invoicing_type': "post-paid",
  44. 'contract_template_id': self.contract_template1.id,
  45. }
  46. )
  47. self.product2.write(
  48. {
  49. 'is_contract': True,
  50. 'contract_template_id': self.contract_template2.id,
  51. }
  52. )
  53. self.order_line1 = self.sale.order_line.filtered(
  54. lambda l: l.product_id == self.product1
  55. )
  56. self.order_line1.date_start = '2018-01-01'
  57. self.order_line1.product_uom_qty = 12
  58. pricelist = self.sale.partner_id.property_product_pricelist.id
  59. self.contract = self.env["contract.contract"].create(
  60. {
  61. "name": "Test Contract 2",
  62. "partner_id": self.sale.partner_id.id,
  63. "pricelist_id": pricelist,
  64. "contract_type": "sale",
  65. "contract_template_id": self.contract_template1.id,
  66. "contract_line_ids": [
  67. (
  68. 0,
  69. 0,
  70. {
  71. "product_id": self.product1.id,
  72. "name": "Services from #START# to #END#",
  73. "quantity": 1,
  74. "uom_id": self.product1.uom_id.id,
  75. "price_unit": 100,
  76. "discount": 50,
  77. "recurring_rule_type": "monthly",
  78. "recurring_interval": 1,
  79. "date_start": "2016-02-15",
  80. "recurring_next_date": "2016-02-29",
  81. },
  82. )
  83. ],
  84. }
  85. )
  86. self.contract_line = self.contract.contract_line_ids[0]
  87. def test_compute_is_contract(self):
  88. """Sale Order should have is_contract true if one of its lines is
  89. contract"""
  90. self.assertTrue(self.sale.is_contract)
  91. def test_action_confirm(self):
  92. """ It should create a contract for each contract template used in
  93. order_line """
  94. self.order_line1.onchange_product()
  95. self.sale.action_confirm()
  96. contracts = self.sale.order_line.mapped('contract_id')
  97. self.assertEqual(len(contracts), 2)
  98. self.assertEqual(
  99. self.order_line1.contract_id.contract_template_id,
  100. self.contract_template1,
  101. )
  102. contract_line = self.order_line1.contract_id.contract_line_ids
  103. self.assertEqual(contract_line.date_start, Date.to_date('2018-01-01'))
  104. self.assertEqual(contract_line.date_end, Date.to_date('2018-12-31'))
  105. self.assertEqual(
  106. contract_line.recurring_next_date, Date.to_date('2018-01-31')
  107. )
  108. def test_contract_company(self):
  109. """
  110. contract company must be the sale order company and not the user one
  111. """
  112. self.assertTrue(self.sale.company_id)
  113. other_company = self.env['res.company'].create(
  114. {'name': 'other company', 'parent_id': self.sale.company_id.id}
  115. )
  116. self.sale.company_id = other_company
  117. self.sale.action_confirm()
  118. contracts = self.sale.order_line.mapped('contract_id')
  119. self.assertEqual(contracts.mapped('company_id'), other_company)
  120. def test_sale_order_invoice_status(self):
  121. """
  122. sale line linked to contracts must not be invoiced from sale order
  123. """
  124. self.sale.action_confirm()
  125. self.assertEqual(self.order_line1.invoice_status, 'no')
  126. invoice = self.order_line1.contract_id.recurring_create_invoice()
  127. self.assertTrue(invoice)
  128. self.assertEqual(self.order_line1.invoice_qty, 1)
  129. self.assertEqual(self.order_line1.qty_to_invoice, 0)
  130. def test_action_confirm_without_contract_creation(self):
  131. """ It should create a contract for each contract template used in
  132. order_line """
  133. self.sale.company_id.create_contract_at_sale_order_confirmation = False
  134. self.order_line1.onchange_product()
  135. self.sale.action_confirm()
  136. self.assertEqual(len(self.sale.order_line.mapped('contract_id')), 0)
  137. self.assertTrue(self.sale.need_contract_creation)
  138. self.sale.action_create_contract()
  139. self.assertEqual(len(self.sale.order_line.mapped('contract_id')), 2)
  140. self.assertFalse(self.sale.need_contract_creation)
  141. self.assertEqual(
  142. self.order_line1.contract_id.contract_template_id,
  143. self.contract_template1,
  144. )
  145. contract_line = self.order_line1.contract_id.contract_line_ids
  146. self.assertEqual(contract_line.date_start, Date.to_date('2018-01-01'))
  147. self.assertEqual(contract_line.date_end, Date.to_date('2018-12-31'))
  148. self.assertEqual(
  149. contract_line.recurring_next_date, Date.to_date('2018-01-31')
  150. )
  151. def test_sale_contract_count(self):
  152. """It should count contracts as many different contract template used
  153. in order_line"""
  154. self.order_line1.onchange_product()
  155. self.sale.action_confirm()
  156. self.assertEqual(self.sale.contract_count, 2)
  157. def test_onchange_product(self):
  158. """ It should get recurrence invoicing info to the sale line from
  159. its product """
  160. self.order_line1.onchange_product()
  161. self.assertEqual(
  162. self.order_line1.recurring_rule_type,
  163. self.product1.recurring_rule_type,
  164. )
  165. self.assertEqual(
  166. self.order_line1.recurring_invoicing_type,
  167. self.product1.recurring_invoicing_type,
  168. )
  169. self.assertEqual(self.order_line1.date_end, Date.to_date('2018-12-31'))
  170. def test_check_contract_sale_partner(self):
  171. """Can't link order line to a partner contract different then the
  172. order one"""
  173. contract2 = self.env['contract.contract'].create(
  174. {
  175. 'name': 'Contract',
  176. 'contract_template_id': self.contract_template2.id,
  177. 'partner_id': self.sale.partner_id.id,
  178. }
  179. )
  180. with self.assertRaises(ValidationError):
  181. self.order_line1.contract_id = contract2
  182. def test_check_contract_sale_contract_template(self):
  183. """Can't link order line to a contract with different contract
  184. template then the product one"""
  185. contract1 = self.env['contract.contract'].create(
  186. {
  187. 'name': 'Contract',
  188. 'partner_id': self.env.user.partner_id.id,
  189. 'contract_template_id': self.contract_template1.id,
  190. }
  191. )
  192. with self.assertRaises(ValidationError):
  193. self.order_line1.contract_id = contract1
  194. def test_no_contract_proudct(self):
  195. """it should create contract for only product contract"""
  196. self.product1.is_contract = False
  197. self.sale.action_confirm()
  198. self.assertFalse(self.order_line1.contract_id)
  199. def test_sale_order_line_invoice_status(self):
  200. """Sale order line for contract product should have nothing to
  201. invoice as status"""
  202. self.order_line1.onchange_product()
  203. self.sale.action_confirm()
  204. self.assertEqual(self.order_line1.invoice_status, 'no')
  205. def test_sale_order_invoice_status(self):
  206. """Sale order with only contract product should have nothing to
  207. invoice status directtly"""
  208. self.sale.order_line.filtered(
  209. lambda line: not line.product_id.is_contract
  210. ).unlink()
  211. self.order_line1.onchange_product()
  212. self.sale.action_confirm()
  213. self.assertEqual(self.sale.invoice_status, 'no')
  214. def test_sale_order_create_invoice(self):
  215. """Should not invoice contract product on sale order create invoice"""
  216. self.product2.is_contract = False
  217. self.product2.invoice_policy = 'order'
  218. self.order_line1.onchange_product()
  219. self.sale.action_confirm()
  220. self.sale.action_invoice_create()
  221. self.assertEqual(len(self.sale.invoice_ids), 1)
  222. invoice_line = self.sale.invoice_ids.invoice_line_ids.filtered(
  223. lambda line: line.product_id.is_contract
  224. )
  225. self.assertEqual(len(invoice_line), 0)
  226. def test_link_contract_invoice_to_sale_order(self):
  227. """It should link contract invoice to sale order"""
  228. self.order_line1.onchange_product()
  229. self.sale.action_confirm()
  230. invoice = self.order_line1.contract_id.recurring_create_invoice()
  231. self.assertTrue(invoice in self.sale.invoice_ids)
  232. def test_contract_upsell(self):
  233. """Should stop contract line at sale order line start date"""
  234. self.order_line1.contract_id = self.contract
  235. self.order_line1.contract_line_id = self.contract_line
  236. self.contract_line.date_end = Date.today() + relativedelta(months=4)
  237. self.contract_line.is_auto_renew = True
  238. self.order_line1.date_start = "2018-06-01"
  239. self.order_line1.onchange_product()
  240. self.sale.action_confirm()
  241. self.assertEqual(
  242. self.contract_line.date_end, Date.to_date("2018-05-31")
  243. )
  244. self.assertFalse(self.contract_line.is_auto_renew)
  245. new_contract_line = self.env['contract.line'].search(
  246. [('sale_order_line_id', '=', self.order_line1.id)]
  247. )
  248. self.assertEqual(
  249. self.contract_line.successor_contract_line_id, new_contract_line
  250. )
  251. self.assertEqual(
  252. new_contract_line.predecessor_contract_line_id, self.contract_line
  253. )
  254. def test_contract_upsell_2(self):
  255. """Should stop contract line at sale order line start date"""
  256. self.order_line1.contract_id = self.contract
  257. self.order_line1.contract_line_id = self.contract_line
  258. self.contract_line.write(
  259. {
  260. 'date_start': "2018-06-01",
  261. 'recurring_next_date': "2018-06-01",
  262. 'date_end': False,
  263. }
  264. )
  265. self.order_line1.date_start = "2018-06-01"
  266. self.order_line1.onchange_product()
  267. self.sale.action_confirm()
  268. self.assertFalse(self.contract_line.date_end)
  269. self.assertTrue(self.contract_line.is_canceled)
  270. def test_onchange_product_id_recurring_info(self):
  271. self.product2.write(
  272. {
  273. 'recurring_rule_type': 'monthly',
  274. 'recurring_invoicing_type': 'pre-paid',
  275. 'is_auto_renew': True,
  276. 'default_qty': 12,
  277. 'termination_notice_interval': '6',
  278. 'termination_notice_rule_type': 'weekly',
  279. }
  280. )
  281. self.contract_line.write(
  282. {
  283. 'date_start': Date.today(),
  284. 'date_end': Date.today() + relativedelta(years=1),
  285. 'recurring_next_date': Date.today(),
  286. 'product_id': self.product2.id,
  287. }
  288. )
  289. self.contract_line._onchange_product_id_recurring_info()
  290. self.assertEqual(self.contract_line.recurring_rule_type, 'monthly')
  291. self.assertEqual(
  292. self.contract_line.recurring_invoicing_type, 'pre-paid'
  293. )
  294. self.assertEqual(self.contract_line.recurring_interval, 1)
  295. self.assertEqual(self.contract_line.is_auto_renew, True)
  296. self.assertEqual(self.contract_line.auto_renew_interval, 12)
  297. self.assertEqual(self.contract_line.auto_renew_rule_type, 'monthly')
  298. self.assertEqual(self.contract_line.termination_notice_interval, 6)
  299. self.assertEqual(
  300. self.contract_line.termination_notice_rule_type, 'weekly'
  301. )
  302. def test_action_show_contracts(self):
  303. self.sale.action_confirm()
  304. action = self.sale.action_show_contracts()
  305. self.assertEqual(
  306. self.env['contract.contract'].search(action['domain']),
  307. self.sale.order_line.mapped('contract_id'),
  308. )