test_purchase_requisition.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. # -*- coding: utf-8 -*-
  2. # Part of Odoo. See LICENSE file for full copyright and licensing details.
  3. from odoo.addons.purchase_requisition.tests.common import TestPurchaseRequisitionCommon
  4. from odoo import Command, fields
  5. from odoo.tests import Form
  6. from datetime import timedelta
  7. from odoo.tests.common import tagged
  8. @tagged('post_install', '-at_install')
  9. class TestPurchaseRequisition(TestPurchaseRequisitionCommon):
  10. def test_00_purchase_requisition_users(self):
  11. self.assertTrue(self.user_purchase_requisition_manager, 'Manager Should be created')
  12. self.assertTrue(self.user_purchase_requisition_user, 'User Should be created')
  13. def test_01_cancel_purchase_requisition(self):
  14. self.bo_requisition.with_user(self.user_purchase_requisition_user).action_cancel()
  15. # Check requisition after cancelled.
  16. self.assertEqual(self.bo_requisition.state, 'cancel', 'Requisition should be in cancelled state.')
  17. # I reset requisition as "New".
  18. self.bo_requisition.with_user(self.user_purchase_requisition_user).action_draft()
  19. # I duplicate requisition.
  20. self.bo_requisition.with_user(self.user_purchase_requisition_user).copy()
  21. def test_02_purchase_requisition(self):
  22. price_product09 = 34
  23. price_product13 = 62
  24. quantity = 26
  25. # Create a pruchase requisition with type blanket order and two product
  26. line1 = (0, 0, {'product_id': self.product_09.id, 'product_qty': quantity, 'product_uom_id': self.product_uom_id.id, 'price_unit': price_product09})
  27. line2 = (0, 0, {'product_id': self.product_13.id, 'product_qty': quantity, 'product_uom_id': self.product_uom_id.id, 'price_unit': price_product13})
  28. requisition_type = self.env['purchase.requisition.type'].create({
  29. 'name': 'Blanket test',
  30. 'quantity_copy': 'none'
  31. })
  32. requisition_blanket = self.env['purchase.requisition'].create({
  33. 'line_ids': [line1, line2],
  34. 'type_id': requisition_type.id,
  35. 'vendor_id': self.res_partner_1.id,
  36. })
  37. # confirm the requisition
  38. requisition_blanket.action_in_progress()
  39. # Check for both product that the new supplier info(purchase.requisition.vendor_id) is added to the purchase tab
  40. # and check the quantity
  41. seller_partner1 = self.res_partner_1
  42. supplierinfo09 = self.env['product.supplierinfo'].search([
  43. ('partner_id', '=', seller_partner1.id),
  44. ('product_id', '=', self.product_09.id),
  45. ('purchase_requisition_id', '=', requisition_blanket.id),
  46. ])
  47. self.assertEqual(supplierinfo09.partner_id, seller_partner1, 'The supplierinfo is not correct')
  48. self.assertEqual(supplierinfo09.price, price_product09, 'The supplierinfo is not correct')
  49. supplierinfo13 = self.env['product.supplierinfo'].search([
  50. ('partner_id', '=', seller_partner1.id),
  51. ('product_id', '=', self.product_13.id),
  52. ('purchase_requisition_id', '=', requisition_blanket.id),
  53. ])
  54. self.assertEqual(supplierinfo13.partner_id, seller_partner1, 'The supplierinfo is not correct')
  55. self.assertEqual(supplierinfo13.price, price_product13, 'The supplierinfo is not correct')
  56. # Put the requisition in done Status
  57. requisition_blanket.action_in_progress()
  58. requisition_blanket.action_done()
  59. self.assertFalse(self.env['product.supplierinfo'].search([('id', '=', supplierinfo09.id)]), 'The supplier info should be removed')
  60. self.assertFalse(self.env['product.supplierinfo'].search([('id', '=', supplierinfo13.id)]), 'The supplier info should be removed')
  61. def test_03_blanket_order_rfq(self):
  62. """ Create a blanket order + an RFQ for it """
  63. requisition_type = self.env['purchase.requisition.type'].create({
  64. 'name': 'Blanket test',
  65. 'quantity_copy': 'none'
  66. })
  67. bo_form = Form(self.env['purchase.requisition'])
  68. bo_form.vendor_id = self.res_partner_1
  69. bo_form.type_id = requisition_type
  70. with bo_form.line_ids.new() as line:
  71. line.product_id = self.product_09
  72. line.product_qty = 5.0
  73. line.price_unit = 21
  74. bo = bo_form.save()
  75. bo.action_in_progress()
  76. # lazy reproduction of clicking on "New Quotation" act_window button
  77. po_form = Form(self.env['purchase.order'].with_context({"default_requisition_id": bo.id, "default_user_id": False}))
  78. po = po_form.save()
  79. self.assertEqual(po.order_line.price_unit, bo.line_ids.price_unit, 'The blanket order unit price should have been copied to purchase order')
  80. self.assertEqual(po.partner_id, bo.vendor_id, 'The blanket order vendor should have been copied to purchase order')
  81. po_form = Form(po)
  82. po_form.order_line.remove(0)
  83. with po_form.order_line.new() as line:
  84. line.product_id = self.product_09
  85. line.product_qty = 5.0
  86. po = po_form.save()
  87. po.button_confirm()
  88. self.assertEqual(po.order_line.price_unit, bo.line_ids.price_unit, 'The blanket order unit price should still be copied to purchase order')
  89. self.assertEqual(po.state, "purchase")
  90. def test_06_purchase_requisition(self):
  91. """ Create a blanket order for a product and a vendor already linked via
  92. a supplier info"""
  93. product = self.env['product.product'].create({
  94. 'name': 'test6',
  95. })
  96. product2 = self.env['product.product'].create({
  97. 'name': 'test6',
  98. })
  99. vendor = self.env['res.partner'].create({
  100. 'name': 'vendor6',
  101. })
  102. supplier_info = self.env['product.supplierinfo'].create({
  103. 'product_id': product.id,
  104. 'partner_id': vendor.id,
  105. })
  106. # create an empty blanket order
  107. requisition_type = self.env['purchase.requisition.type'].create({
  108. 'name': 'Blanket test',
  109. 'quantity_copy': 'none'
  110. })
  111. line1 = (0, 0, {
  112. 'product_id': product2.id,
  113. 'product_uom_id': product2.uom_po_id.id,
  114. 'price_unit': 41,
  115. 'product_qty': 10,
  116. })
  117. requisition_blanket = self.env['purchase.requisition'].create({
  118. 'line_ids': [line1],
  119. 'type_id': requisition_type.id,
  120. 'vendor_id': vendor.id,
  121. })
  122. requisition_blanket.action_in_progress()
  123. self.env['purchase.requisition.line'].create({
  124. 'product_id': product.id,
  125. 'product_qty': 14.0,
  126. 'requisition_id': requisition_blanket.id,
  127. 'price_unit': 10,
  128. })
  129. new_si = self.env['product.supplierinfo'].search([
  130. ('product_id', '=', product.id),
  131. ('partner_id', '=', vendor.id)
  132. ]) - supplier_info
  133. self.assertEqual(new_si.purchase_requisition_id, requisition_blanket, 'the blanket order is not linked to the supplier info')
  134. def test_07_alternative_purchases_wizards(self):
  135. """Directly link POs to each other as 'Alternatives': check that wizards and
  136. their flows correctly work."""
  137. orig_po = self.env['purchase.order'].create({
  138. 'partner_id': self.res_partner_1.id,
  139. })
  140. unit_price = 50
  141. po_form = Form(orig_po)
  142. with po_form.order_line.new() as line:
  143. line.product_id = self.product_09
  144. line.product_qty = 5.0
  145. line.price_unit = unit_price
  146. line.product_uom = self.env.ref('uom.product_uom_dozen')
  147. with po_form.order_line.new() as line:
  148. line.display_type = "line_section"
  149. line.name = "Products"
  150. with po_form.order_line.new() as line:
  151. line.display_type = 'line_note'
  152. line.name = 'note1'
  153. po_form.save()
  154. # first flow: check that creating an alt PO correctly auto-links both POs to each other
  155. action = orig_po.action_create_alternative()
  156. alt_po_wiz = Form(self.env['purchase.requisition.create.alternative'].with_context(**action['context']))
  157. alt_po_wiz.partner_id = self.res_partner_1
  158. alt_po_wiz.copy_products = True
  159. alt_po_wiz = alt_po_wiz.save()
  160. alt_po_wiz.action_create_alternative()
  161. self.assertEqual(len(orig_po.alternative_po_ids), 2, "Original PO should be auto-linked to itself and newly created PO")
  162. # check alt po was created with correct values
  163. alt_po_1 = orig_po.alternative_po_ids.filtered(lambda po: po.id != orig_po.id)
  164. self.assertEqual(len(alt_po_1.order_line), 3)
  165. self.assertEqual(orig_po.order_line[0].product_id, alt_po_1.order_line[0].product_id, "Alternative PO should have copied the product to purchase from original PO")
  166. self.assertEqual(orig_po.order_line[0].product_qty, alt_po_1.order_line[0].product_qty, "Alternative PO should have copied the qty to purchase from original PO")
  167. self.assertEqual(orig_po.order_line[0].product_uom, alt_po_1.order_line[0].product_uom, "Alternative PO should have copied the product unit of measure from original PO")
  168. self.assertEqual((orig_po.order_line[1].display_type, orig_po.order_line[1].name), (alt_po_1.order_line[1].display_type, alt_po_1.order_line[1].name))
  169. self.assertEqual((orig_po.order_line[2].display_type, orig_po.order_line[2].name), (alt_po_1.order_line[2].display_type, alt_po_1.order_line[2].name))
  170. self.assertEqual(len(alt_po_1.alternative_po_ids), 2, "Newly created PO should be auto-linked to itself and original PO")
  171. # check compare POLs correctly calcs best date/price PO lines: orig_po.date_planned = best & alt_po.price = best
  172. alt_po_1.order_line[0].date_planned += timedelta(days=1)
  173. alt_po_1.order_line[0].price_unit = unit_price - 10
  174. action = orig_po.action_compare_alternative_lines()
  175. best_price_ids, best_date_ids, best_price_unit_ids = orig_po.get_tender_best_lines()
  176. best_price_pol = self.env['purchase.order.line'].browse(best_price_ids)
  177. best_date_pol = self.env['purchase.order.line'].browse(best_date_ids)
  178. best_unit_price_pol = self.env['purchase.order.line'].browse(best_price_unit_ids)
  179. self.assertEqual(best_price_pol.order_id.id, alt_po_1.id, "Best price PO line was not correctly calculated")
  180. self.assertEqual(best_date_pol.order_id.id, orig_po.id, "Best date PO line was not correctly calculated")
  181. self.assertEqual(best_unit_price_pol.order_id.id, alt_po_1.id, "Best unit price PO line was not correctly calculated")
  182. # second flow: create extra alt PO, check that all 3 POs are correctly auto-linked
  183. action = orig_po.action_create_alternative()
  184. alt_po_wiz = Form(self.env['purchase.requisition.create.alternative'].with_context(**action['context']))
  185. alt_po_wiz.partner_id = self.res_partner_1
  186. alt_po_wiz.copy_products = True
  187. alt_po_wiz = alt_po_wiz.save()
  188. alt_po_wiz.action_create_alternative()
  189. self.assertEqual(len(orig_po.alternative_po_ids), 3, "Original PO should be auto-linked to newly created alternative PO")
  190. self.assertEqual(len(alt_po_1.alternative_po_ids), 3, "Alternative PO should be auto-linked to newly created alternative PO")
  191. alt_po_2 = orig_po.alternative_po_ids.filtered(lambda po: po.id not in [alt_po_1.id, orig_po.id])
  192. self.assertEqual(len(alt_po_2.alternative_po_ids), 3, "All alternative POs should be auto-linked to each other")
  193. # third flow: confirm one of the POs when alt POs are a mix of confirmed + RFQs
  194. alt_po_2.write({'state': 'purchase'})
  195. action = orig_po.button_confirm()
  196. warning_wiz = Form(self.env['purchase.requisition.alternative.warning'].with_context(**action['context']))
  197. warning_wiz = warning_wiz.save()
  198. self.assertEqual(warning_wiz.alternative_po_count, 1, "POs not in a RFQ status should not be listed as possible to cancel")
  199. warning_wiz.action_cancel_alternatives()
  200. self.assertEqual(alt_po_1.state, 'cancel', "Alternative PO should have been cancelled")
  201. self.assertEqual(orig_po.state, 'purchase', "Original PO should have been confirmed")
  202. def test_08_purchases_multi_linkages(self):
  203. """Directly link POs to each other as 'Alternatives': check linking/unlinking
  204. POs that are already linked correctly work."""
  205. pos = []
  206. for _ in range(5):
  207. pos += self.env['purchase.order'].create({
  208. 'partner_id': self.res_partner_1.id,
  209. }).ids
  210. pos = self.env['purchase.order'].browse(pos)
  211. po_1, po_2, po_3, po_4, po_5 = pos
  212. po_1.alternative_po_ids |= po_2
  213. po_3.alternative_po_ids |= po_4
  214. groups = self.env['purchase.order.group'].search([('order_ids', 'in', pos.ids)])
  215. self.assertEqual(len(po_1.alternative_po_ids), 2, "PO1 and PO2 should only be linked to each other")
  216. self.assertEqual(len(po_3.alternative_po_ids), 2, "PO3 and PO4 should only be linked to each other")
  217. self.assertEqual(len(groups), 2, "There should only be 2 groups: (PO1,PO2) and (PO3,PO4)")
  218. # link non-linked PO to already linked PO
  219. po_5.alternative_po_ids |= po_4
  220. groups = self.env['purchase.order.group'].search([('order_ids', 'in', pos.ids)])
  221. self.assertEqual(len(po_3.alternative_po_ids), 3, "PO3 should now be linked to PO4 and PO5")
  222. self.assertEqual(len(po_4.alternative_po_ids), 3, "PO4 should now be linked to PO3 and PO5")
  223. self.assertEqual(len(po_5.alternative_po_ids), 3, "PO5 should now be linked to PO3 and PO4")
  224. self.assertEqual(len(groups), 2, "There should only be 2 groups: (PO1,PO2) and (PO3,PO4,PO5)")
  225. # link already linked PO to already linked PO
  226. po_5.alternative_po_ids |= po_1
  227. groups = self.env['purchase.order.group'].search([('order_ids', 'in', pos.ids)])
  228. self.assertEqual(len(po_1.alternative_po_ids), 5, "All 5 POs should be linked to each other now")
  229. self.assertEqual(len(groups), 1, "There should only be 1 group containing all 5 POs (other group should have auto-deleted")
  230. # remove all links, make sure group auto-deletes
  231. (pos - po_5).alternative_po_ids = [Command.clear()]
  232. groups = self.env['purchase.order.group'].search([('order_ids', 'in', pos.ids)])
  233. self.assertEqual(len(po_5.alternative_po_ids), 0, "Last PO should auto unlink from itself since group should have auto-deleted")
  234. self.assertEqual(len(groups), 0, "The group should have auto-deleted")
  235. def test_09_alternative_po_line_price_unit(self):
  236. """Checks PO line's `price_unit` is keep even if a line from an
  237. alternative is chosen and thus the PO line's quantity was set to 0. """
  238. # Creates a first Purchase Order.
  239. po_form = Form(self.env['purchase.order'])
  240. po_form.partner_id = self.res_partner_1
  241. with po_form.order_line.new() as line:
  242. line.product_id = self.product_09
  243. line.product_qty = 1
  244. line.price_unit = 16
  245. po_1 = po_form.save()
  246. # Creates an alternative PO.
  247. action = po_1.action_create_alternative()
  248. alt_po_wizard_form = Form(self.env['purchase.requisition.create.alternative'].with_context(**action['context']))
  249. alt_po_wizard_form.partner_id = self.res_partner_1
  250. alt_po_wizard_form.copy_products = True
  251. alt_po_wizard = alt_po_wizard_form.save()
  252. alt_po_wizard.action_create_alternative()
  253. # Set a lower price on the alternative and choses this PO line.
  254. po_2 = po_1.alternative_po_ids - po_1
  255. po_2.order_line.price_unit = 12
  256. po_2.order_line.action_choose()
  257. self.assertEqual(
  258. po_1.order_line.product_uom_qty, 0,
  259. "Line's quantity from the original PO should be reset to 0")
  260. self.assertEqual(
  261. po_1.order_line.price_unit, 16,
  262. "Line's unit price from the original PO shouldn't be changed")
  263. def test_10_alternative_po_line_price_unit_different_uom(self):
  264. """ Check that the uom is copied in the alternative PO, and the "unit_price"
  265. is calculated according to this uom and not that of the product """
  266. # Creates a first Purchase Order.
  267. po_form = Form(self.env['purchase.order'])
  268. self.product_09.standard_price = 10
  269. po_form.partner_id = self.res_partner_1
  270. with po_form.order_line.new() as line:
  271. line.product_id = self.product_09
  272. line.product_qty = 1
  273. line.product_uom = self.env.ref('uom.product_uom_dozen')
  274. po_1 = po_form.save()
  275. self.assertEqual(po_1.order_line[0].price_unit, 120)
  276. # Creates an alternative PO.
  277. action = po_1.action_create_alternative()
  278. alt_po_wizard_form = Form(self.env['purchase.requisition.create.alternative'].with_context(**action['context']))
  279. alt_po_wizard_form.partner_id = self.res_partner_1
  280. alt_po_wizard_form.copy_products = True
  281. alt_po_wizard = alt_po_wizard_form.save()
  282. alt_po_wizard.action_create_alternative()
  283. po_2 = po_1.alternative_po_ids - po_1
  284. self.assertEqual(po_2.order_line[0].product_uom, po_1.order_line[0].product_uom)
  285. self.assertEqual(po_2.order_line[0].price_unit, 120)
  286. def test_11_alternative_po_from_po_with_requisition_id(self):
  287. """Create a purchase order from a blanket order, then check that the alternative purchase order
  288. can be created and that the requisition_id is not set on it.
  289. """
  290. # create an empty blanket order
  291. requisition_type = self.env['purchase.requisition.type'].create({
  292. 'name': 'Blanket test',
  293. 'quantity_copy': 'none'
  294. })
  295. line1 = (0, 0, {
  296. 'product_id': self.product_13.id,
  297. 'product_uom_id': self.product_13.uom_po_id.id,
  298. 'price_unit': 41,
  299. 'product_qty': 10,
  300. })
  301. requisition_blanket = self.env['purchase.requisition'].create({
  302. 'line_ids': [line1],
  303. 'type_id': requisition_type.id,
  304. 'vendor_id': self.res_partner_1.id,
  305. })
  306. requisition_blanket.action_in_progress()
  307. # lazy reproduction of clicking on "New Quotation" act_window button
  308. po_form = Form(self.env['purchase.order'].with_context({"default_requisition_id": requisition_blanket.id, "default_user_id": False}))
  309. po_1 = po_form.save()
  310. po_1.button_confirm()
  311. self.assertTrue(po_1.requisition_id, "The requisition_id should be set in the purchase order")
  312. # Creates an alternative PO.
  313. action = po_1.action_create_alternative()
  314. alt_po_wizard_form = Form(self.env['purchase.requisition.create.alternative'].with_context(**action['context']))
  315. alt_po_wizard_form.partner_id = self.res_partner_1
  316. alt_po_wizard_form.copy_products = True
  317. alt_po_wizard = alt_po_wizard_form.save()
  318. alt_po_wizard.action_create_alternative()
  319. po_2 = po_1.alternative_po_ids - po_1
  320. self.assertFalse(po_2.requisition_id, "The requisition_id should not be set in the alternative purchase order")
  321. def test_12_alternative_po_line_different_currency(self):
  322. """ Check alternative PO with different currency is compared correctly"""
  323. currency_eur = self.env.ref("base.EUR")
  324. currency_usd = self.env.ref("base.USD")
  325. (currency_usd | currency_eur).active = True
  326. # 1 USD = 0.5 EUR
  327. self.env['res.currency.rate'].create([{
  328. 'name': fields.Datetime.today(),
  329. 'currency_id': self.env.ref('base.USD').id,
  330. 'rate': 1,
  331. }, {
  332. 'name': fields.Datetime.today(),
  333. 'currency_id': self.env.ref('base.EUR').id,
  334. 'rate': 0.5,
  335. }])
  336. vendor_usd = self.env["res.partner"].create({
  337. "name": "Supplier A",
  338. })
  339. vendor_eur = self.env["res.partner"].create({
  340. "name": "Supplier B",
  341. })
  342. product = self.env['product.product'].create({
  343. 'name': 'Product',
  344. 'seller_ids': [(0, 0, {
  345. 'partner_id': vendor_usd.id,
  346. 'price': 100,
  347. 'currency_id': currency_usd.id,
  348. }), (0, 0, {
  349. 'partner_id': vendor_eur.id,
  350. 'price': 80,
  351. 'currency_id': currency_eur.id,
  352. })]
  353. })
  354. po_form = Form(self.env['purchase.order'])
  355. po_form.partner_id = vendor_eur
  356. po_form.currency_id = currency_eur
  357. with po_form.order_line.new() as line:
  358. line.product_id = product
  359. line.product_qty = 1
  360. po_orig = po_form.save()
  361. self.assertEqual(po_orig.order_line.price_unit, 80)
  362. self.assertEqual(po_orig.currency_id, currency_eur)
  363. # Creates an alternative PO
  364. action = po_orig.action_create_alternative()
  365. alt_po_wizard_form = Form(self.env['purchase.requisition.create.alternative'].with_context(**action['context']))
  366. alt_po_wizard_form.partner_id = vendor_usd
  367. alt_po_wizard_form.copy_products = True
  368. alt_po_wizard = alt_po_wizard_form.save()
  369. alt_po_wizard.action_create_alternative()
  370. po_alt = po_orig.alternative_po_ids - po_orig
  371. # Ensure that the currency in the alternative purchase order is set to USD
  372. # because, in some case, the company's default currency is EUR.
  373. self.assertEqual(po_alt.currency_id, currency_usd)
  374. self.assertEqual(po_alt.order_line.price_unit, 100)
  375. # po_alt has cheaper price_unit/price_subtotal after conversion USD -> EUR
  376. # 80 / 0.5 = 160 USD > 100 EUR
  377. best_price_ids, best_date_ids, best_price_unit_ids = po_orig.get_tender_best_lines()
  378. self.assertEqual(len(best_price_ids), 1)
  379. # Equal dates
  380. self.assertEqual(len(best_date_ids), 2)
  381. self.assertEqual(len(best_price_unit_ids), 1)
  382. # alt_po is cheaper than orig_po
  383. self.assertEqual(best_price_ids[0], po_alt.order_line.id)
  384. self.assertEqual(best_price_unit_ids[0], po_alt.order_line.id)
  385. def test_alternative_po_with_multiple_price_list(self):
  386. vendor_a = self.env["res.partner"].create({
  387. "name": "Supplier A",
  388. })
  389. vendor_b = self.env["res.partner"].create({
  390. "name": "Supplier B",
  391. })
  392. product = self.env['product.product'].create({
  393. 'name': 'Product',
  394. 'seller_ids': [(0, 0, {
  395. 'partner_id': vendor_a.id,
  396. 'price': 5,
  397. }), (0, 0, {
  398. 'partner_id': vendor_b.id,
  399. 'price': 4,
  400. 'min_qty': 10,
  401. }), (0, 0, {
  402. 'partner_id': vendor_b.id,
  403. 'price': 6,
  404. 'min_qty': 1,
  405. }),
  406. ]
  407. })
  408. po_form = Form(self.env['purchase.order'])
  409. po_form.partner_id = vendor_a
  410. with po_form.order_line.new() as line:
  411. line.product_id = product
  412. line.product_qty = 100
  413. po_orig = po_form.save()
  414. self.assertEqual(po_orig.order_line.price_unit, 5)
  415. # Creates an alternative PO
  416. action = po_orig.action_create_alternative()
  417. alt_po_wizard_form = Form(self.env['purchase.requisition.create.alternative'].with_context(**action['context']))
  418. alt_po_wizard_form.partner_id = vendor_b
  419. alt_po_wizard_form.copy_products = True
  420. alt_po_wizard = alt_po_wizard_form.save()
  421. alt_po_wizard.action_create_alternative()
  422. po_alt = po_orig.alternative_po_ids - po_orig
  423. self.assertEqual(po_alt.order_line.price_unit, 4)