test_inventory.py 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522
  1. # -*- coding: utf-8 -*-
  2. # Part of Odoo. See LICENSE file for full copyright and licensing details.
  3. from datetime import date, datetime, timedelta
  4. from dateutil.relativedelta import relativedelta
  5. from odoo.exceptions import ValidationError
  6. from odoo.tests.common import Form, TransactionCase
  7. class TestInventory(TransactionCase):
  8. @classmethod
  9. def setUpClass(cls):
  10. super(TestInventory, cls).setUpClass()
  11. cls.stock_location = cls.env.ref('stock.stock_location_stock')
  12. cls.pack_location = cls.env.ref('stock.location_pack_zone')
  13. cls.pack_location.active = True
  14. cls.customer_location = cls.env.ref('stock.stock_location_customers')
  15. cls.uom_unit = cls.env.ref('uom.product_uom_unit')
  16. cls.product1 = cls.env['product.product'].create({
  17. 'name': 'Product A',
  18. 'type': 'product',
  19. 'categ_id': cls.env.ref('product.product_category_all').id,
  20. })
  21. cls.product2 = cls.env['product.product'].create({
  22. 'name': 'Product A',
  23. 'type': 'product',
  24. 'tracking': 'serial',
  25. 'categ_id': cls.env.ref('product.product_category_all').id,
  26. })
  27. def test_inventory_1(self):
  28. """ Check that making an inventory adjustment to remove all products from stock is working
  29. as expected.
  30. """
  31. # make some stock
  32. self.env['stock.quant']._update_available_quantity(self.product1, self.stock_location, 100)
  33. self.assertEqual(len(self.env['stock.quant']._gather(self.product1, self.stock_location)), 1.0)
  34. self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product1, self.stock_location), 100.0)
  35. # remove them with an inventory adjustment
  36. inventory_quant = self.env['stock.quant'].search([
  37. ('location_id', '=', self.stock_location.id),
  38. ('product_id', '=', self.product1.id),
  39. ])
  40. self.assertEqual(len(inventory_quant), 1)
  41. self.assertEqual(inventory_quant.quantity, 100)
  42. self.assertEqual(inventory_quant.inventory_quantity, 0)
  43. inventory_quant.action_apply_inventory()
  44. # check
  45. self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product1, self.stock_location), 0.0)
  46. self.assertEqual(sum(self.env['stock.quant']._gather(self.product1, self.stock_location).mapped('quantity')), 0.0)
  47. def test_inventory_2(self):
  48. """ Check that adding a tracked product through an inventory adjustment works as expected.
  49. """
  50. inventory_quant = self.env['stock.quant'].search([
  51. ('location_id', '=', self.stock_location.id),
  52. ('product_id', '=', self.product2.id)
  53. ])
  54. self.assertEqual(len(inventory_quant), 0)
  55. lot1 = self.env['stock.lot'].create({
  56. 'name': 'sn2',
  57. 'product_id': self.product2.id,
  58. 'company_id': self.env.company.id,
  59. })
  60. inventory_quant = self.env['stock.quant'].create({
  61. 'location_id': self.stock_location.id,
  62. 'product_id': self.product2.id,
  63. 'lot_id': lot1.id,
  64. 'inventory_quantity': 1
  65. })
  66. self.assertEqual(inventory_quant.quantity, 0)
  67. self.assertEqual(inventory_quant.inventory_diff_quantity, 1)
  68. inventory_quant.action_apply_inventory()
  69. # check
  70. self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product2, self.stock_location, lot_id=lot1), 1.0)
  71. self.assertEqual(len(self.env['stock.quant']._gather(self.product2, self.stock_location, lot_id=lot1)), 1.0)
  72. self.assertEqual(lot1.product_qty, 1.0)
  73. def test_inventory_3(self):
  74. """ Check that it's not possible to have multiple products with the same serial number through an
  75. inventory adjustment
  76. """
  77. inventory_quant = self.env['stock.quant'].search([
  78. ('location_id', '=', self.stock_location.id),
  79. ('product_id', '=', self.product2.id)
  80. ])
  81. self.assertEqual(len(inventory_quant), 0)
  82. lot1 = self.env['stock.lot'].create({
  83. 'name': 'sn2',
  84. 'product_id': self.product2.id,
  85. 'company_id': self.env.company.id,
  86. })
  87. inventory_quant = self.env['stock.quant'].create({
  88. 'location_id': self.stock_location.id,
  89. 'product_id': self.product2.id,
  90. 'lot_id': lot1.id,
  91. 'inventory_quantity': 2
  92. })
  93. self.assertEqual(len(inventory_quant), 1)
  94. self.assertEqual(inventory_quant.quantity, 0)
  95. with self.assertRaises(ValidationError):
  96. inventory_quant.action_apply_inventory()
  97. def test_inventory_4(self):
  98. """ Check that even if a product is tracked by serial number, it's possible to add an
  99. untracked one in an inventory adjustment.
  100. """
  101. quant_domain = [
  102. ('location_id', '=', self.stock_location.id),
  103. ('product_id', '=', self.product2.id)
  104. ]
  105. inventory_quants = self.env['stock.quant'].search(quant_domain)
  106. self.assertEqual(len(inventory_quants), 0)
  107. lot1 = self.env['stock.lot'].create({
  108. 'name': 'sn2',
  109. 'product_id': self.product2.id,
  110. 'company_id': self.env.company.id,
  111. })
  112. self.env['stock.quant'].create({
  113. 'location_id': self.stock_location.id,
  114. 'product_id': self.product2.id,
  115. 'lot_id': lot1.id,
  116. 'inventory_quantity': 1
  117. })
  118. inventory_quants = self.env['stock.quant'].search(quant_domain)
  119. self.assertEqual(len(inventory_quants), 1)
  120. self.assertEqual(inventory_quants.quantity, 0)
  121. self.env['stock.quant'].create({
  122. 'location_id': self.stock_location.id,
  123. 'product_id': self.product2.id,
  124. 'inventory_quantity': 10
  125. })
  126. inventory_quants = self.env['stock.quant'].search(quant_domain)
  127. self.assertEqual(len(inventory_quants), 2)
  128. stock_confirmation_action = inventory_quants.action_apply_inventory()
  129. stock_confirmation_wizard_form = Form(
  130. self.env['stock.track.confirmation'].with_context(
  131. **stock_confirmation_action['context'])
  132. )
  133. stock_confirmation_wizard = stock_confirmation_wizard_form.save()
  134. stock_confirmation_wizard.action_confirm()
  135. # check
  136. self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product2, self.stock_location, lot_id=lot1, strict=True), 11.0)
  137. self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product2, self.stock_location, strict=True), 10.0)
  138. self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product2, self.stock_location), 11.0)
  139. self.assertEqual(len(self.env['stock.quant']._gather(self.product2, self.stock_location, lot_id=lot1, strict=True).filtered(lambda q: q.lot_id)), 1.0)
  140. self.assertEqual(len(self.env['stock.quant']._gather(self.product2, self.stock_location, strict=True)), 1.0)
  141. self.assertEqual(len(self.env['stock.quant']._gather(self.product2, self.stock_location)), 2.0)
  142. def test_inventory_5(self):
  143. """ Check that assigning an owner works.
  144. """
  145. owner1 = self.env['res.partner'].create({'name': 'test_inventory_5'})
  146. inventory_quant = self.env['stock.quant'].create({
  147. 'location_id': self.stock_location.id,
  148. 'product_id': self.product1.id,
  149. 'inventory_quantity': 5,
  150. 'owner_id': owner1.id,
  151. })
  152. self.assertEqual(inventory_quant.quantity, 0)
  153. inventory_quant.action_apply_inventory()
  154. quant = self.env['stock.quant']._gather(self.product1, self.stock_location)
  155. self.assertEqual(len(quant), 1)
  156. self.assertEqual(quant.quantity, 5)
  157. self.assertEqual(quant.owner_id.id, owner1.id)
  158. def test_inventory_6(self):
  159. """ Test that for chained moves, making an inventory adjustment to reduce a quantity that
  160. has been reserved correctly frees the reservation. After that, add products to stock and check
  161. that they're used if the user encodes more than what's available through the chain
  162. """
  163. # add 10 products to stock
  164. inventory_quant = self.env['stock.quant'].create({
  165. 'location_id': self.stock_location.id,
  166. 'product_id': self.product1.id,
  167. 'inventory_quantity': 10,
  168. })
  169. inventory_quant.action_apply_inventory()
  170. self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product1, self.stock_location), 10.0)
  171. # Make a chain of two moves, validate the first and check that 10 products are reserved
  172. # in the second one.
  173. move_stock_pack = self.env['stock.move'].create({
  174. 'name': 'test_link_2_1',
  175. 'location_id': self.stock_location.id,
  176. 'location_dest_id': self.pack_location.id,
  177. 'product_id': self.product1.id,
  178. 'product_uom': self.uom_unit.id,
  179. 'product_uom_qty': 10.0,
  180. })
  181. move_pack_cust = self.env['stock.move'].create({
  182. 'name': 'test_link_2_2',
  183. 'location_id': self.pack_location.id,
  184. 'location_dest_id': self.customer_location.id,
  185. 'product_id': self.product1.id,
  186. 'product_uom': self.uom_unit.id,
  187. 'product_uom_qty': 10.0,
  188. })
  189. move_stock_pack.write({'move_dest_ids': [(4, move_pack_cust.id, 0)]})
  190. move_pack_cust.write({'move_orig_ids': [(4, move_stock_pack.id, 0)]})
  191. (move_stock_pack + move_pack_cust)._action_confirm()
  192. move_stock_pack._action_assign()
  193. self.assertEqual(move_stock_pack.state, 'assigned')
  194. move_stock_pack.move_line_ids.qty_done = 10
  195. move_stock_pack._action_done()
  196. self.assertEqual(move_stock_pack.state, 'done')
  197. self.assertEqual(move_pack_cust.state, 'assigned')
  198. self.assertEqual(self.env['stock.quant']._gather(self.product1, self.pack_location).quantity, 10.0)
  199. self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product1, self.pack_location), 0.0)
  200. # Make an inventory adjustment and remove two products from the pack location. This should
  201. # free the reservation of the second move.
  202. inventory_quant = self.env['stock.quant'].search([
  203. ('location_id', '=', self.pack_location.id),
  204. ('product_id', '=', self.product1.id)
  205. ])
  206. inventory_quant.inventory_quantity = 8
  207. inventory_quant.action_apply_inventory()
  208. self.assertEqual(self.env['stock.quant']._gather(self.product1, self.pack_location).quantity, 8.0)
  209. self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product1, self.pack_location), 0)
  210. self.assertEqual(move_pack_cust.state, 'partially_available')
  211. self.assertEqual(move_pack_cust.reserved_availability, 8)
  212. # If the user tries to assign again, only 8 products are available and thus the reservation
  213. # state should not change.
  214. move_pack_cust._action_assign()
  215. self.assertEqual(move_pack_cust.state, 'partially_available')
  216. self.assertEqual(move_pack_cust.reserved_availability, 8)
  217. # Make a new inventory adjustment and add two new products.
  218. inventory_quant = self.env['stock.quant'].search([
  219. ('location_id', '=', self.pack_location.id),
  220. ('product_id', '=', self.product1.id)
  221. ])
  222. inventory_quant.inventory_quantity = 10
  223. inventory_quant.action_apply_inventory()
  224. self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product1, self.pack_location), 2)
  225. # Nothing should have changed for our pack move
  226. self.assertEqual(move_pack_cust.state, 'partially_available')
  227. self.assertEqual(move_pack_cust.reserved_availability, 8)
  228. # Running _action_assign will now find the new available quantity. Since the products
  229. # are not differentiated (no lot/pack/owner), even if the new available quantity is not directly
  230. # brought by the chain, the system will take them into account.
  231. move_pack_cust._action_assign()
  232. self.assertEqual(move_pack_cust.state, 'assigned')
  233. # move all the things
  234. move_pack_cust.move_line_ids.qty_done = 10
  235. move_stock_pack._action_done()
  236. self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product1, self.pack_location), 0)
  237. def test_inventory_7(self):
  238. """ Check that duplicated quants create a single inventory line.
  239. """
  240. owner1 = self.env['res.partner'].create({'name': 'test_inventory_7'})
  241. vals = {
  242. 'product_id': self.product1.id,
  243. 'product_uom_id': self.uom_unit.id,
  244. 'owner_id': owner1.id,
  245. 'location_id': self.stock_location.id,
  246. 'quantity': 1,
  247. }
  248. self.env['stock.quant'].create(vals)
  249. self.env['stock.quant'].create(dict(**vals, inventory_quantity=1))
  250. self.assertEqual(len(self.env['stock.quant']._gather(self.product1, self.stock_location)), 2.0)
  251. self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product1, self.stock_location), 2.0)
  252. self.env['stock.quant']._quant_tasks()
  253. inventory_quant = self.env['stock.quant'].search([
  254. ('location_id', '=', self.stock_location.id),
  255. ('product_id', '=', self.product1.id)
  256. ])
  257. self.assertEqual(len(inventory_quant), 1)
  258. self.assertEqual(inventory_quant.inventory_quantity, 1)
  259. self.assertEqual(inventory_quant.quantity, 2)
  260. def test_inventory_counted_quantity(self):
  261. """ Checks that inventory quants have a `inventory quantity` set to zero
  262. after an adjustment.
  263. """
  264. # Set product quantity to 42.
  265. inventory_quant = self.env['stock.quant'].create({
  266. 'product_id': self.product1.id,
  267. 'location_id': self.stock_location.id,
  268. 'inventory_quantity': 42,
  269. })
  270. # Applies the change, the quant must have a quantity of 42 and a inventory quantity to 0.
  271. inventory_quant.action_apply_inventory()
  272. self.assertEqual(len(inventory_quant), 1)
  273. self.assertEqual(inventory_quant.inventory_quantity, 0)
  274. self.assertEqual(inventory_quant.quantity, 42)
  275. # Checks we can write on `inventory_quantity_set` even if we write on
  276. # `inventory_quantity` at the same time.
  277. self.assertEqual(inventory_quant.inventory_quantity_set, False)
  278. inventory_quant.write({'inventory_quantity': 5})
  279. self.assertEqual(inventory_quant.inventory_quantity_set, True)
  280. inventory_quant.write({
  281. 'inventory_quantity': 12,
  282. 'inventory_quantity_set': False,
  283. })
  284. self.assertEqual(inventory_quant.inventory_quantity_set, False)
  285. def test_inventory_outdate_1(self):
  286. """ Checks that applying an inventory adjustment that is outdated due to
  287. its corresponding quant being modified after its inventory quantity is set
  288. opens a wizard. The wizard should warn about the conflict and its value should be
  289. corrected after user confirms the inventory quantity.
  290. """
  291. # Set initial quantity to 7
  292. self.env['stock.quant']._update_available_quantity(self.product1, self.stock_location, 7)
  293. inventory_quant = self.env['stock.quant'].search([
  294. ('location_id', '=', self.stock_location.id),
  295. ('product_id', '=', self.product1.id)
  296. ])
  297. # When a quant is created, it must not be marked as outdated
  298. # and its `inventory_quantity` must be equal to zero.
  299. self.assertEqual(inventory_quant.inventory_quantity, 0)
  300. inventory_quant.inventory_quantity = 5
  301. self.assertEqual(inventory_quant.inventory_diff_quantity, -2)
  302. # Deliver 3 units
  303. move_out = self.env['stock.move'].create({
  304. 'name': 'Outgoing move of 3 units',
  305. 'location_id': self.stock_location.id,
  306. 'location_dest_id': self.customer_location.id,
  307. 'product_id': self.product1.id,
  308. 'product_uom': self.uom_unit.id,
  309. 'product_uom_qty': 3.0,
  310. })
  311. move_out._action_confirm()
  312. move_out._action_assign()
  313. move_out.move_line_ids.qty_done = 3
  314. move_out._action_done()
  315. # Ensure that diff didn't change.
  316. self.assertEqual(inventory_quant.inventory_diff_quantity, -2)
  317. self.assertEqual(inventory_quant.inventory_quantity, 5)
  318. self.assertEqual(inventory_quant.quantity, 4)
  319. conflict_wizard_values = inventory_quant.action_apply_inventory()
  320. conflict_wizard_form = Form(self.env['stock.inventory.conflict'].with_context(conflict_wizard_values['context']))
  321. conflict_wizard = conflict_wizard_form.save()
  322. conflict_wizard.quant_to_fix_ids.inventory_quantity = 5
  323. conflict_wizard.action_keep_counted_quantity()
  324. self.assertEqual(inventory_quant.inventory_diff_quantity, 0)
  325. self.assertEqual(inventory_quant.inventory_quantity, 0)
  326. self.assertEqual(inventory_quant.quantity, 5)
  327. def test_inventory_outdate_2(self):
  328. """ Checks that an outdated inventory adjustment auto-corrects when
  329. changing its inventory quantity after its corresponding quant has been modified.
  330. """
  331. # Set initial quantity to 7
  332. vals = {
  333. 'product_id': self.product1.id,
  334. 'product_uom_id': self.uom_unit.id,
  335. 'location_id': self.stock_location.id,
  336. 'quantity': 7,
  337. 'inventory_quantity': 7
  338. }
  339. quant = self.env['stock.quant'].create(vals)
  340. # Decrease quant to 3 and inventory line is now outdated
  341. move_out = self.env['stock.move'].create({
  342. 'name': 'Outgoing move of 3 units',
  343. 'location_id': self.stock_location.id,
  344. 'location_dest_id': self.customer_location.id,
  345. 'product_id': self.product1.id,
  346. 'product_uom': self.uom_unit.id,
  347. 'product_uom_qty': 4.0,
  348. })
  349. move_out._action_confirm()
  350. move_out._action_assign()
  351. move_out.move_line_ids.qty_done = 4
  352. move_out._action_done()
  353. self.assertEqual(quant.inventory_quantity, 7)
  354. self.assertEqual(quant.inventory_diff_quantity, 0)
  355. # Refresh inventory line and quantity will recompute to 3
  356. quant.inventory_quantity = 3
  357. self.assertEqual(quant.inventory_quantity, 3)
  358. self.assertEqual(quant.inventory_diff_quantity, 0)
  359. def test_inventory_outdate_3(self):
  360. """ Checks that an inventory adjustment line without a difference
  361. doesn't change quant when validated.
  362. """
  363. # Set initial quantity to 10
  364. vals = {
  365. 'product_id': self.product1.id,
  366. 'product_uom_id': self.uom_unit.id,
  367. 'location_id': self.stock_location.id,
  368. 'quantity': 10,
  369. }
  370. quant = self.env['stock.quant'].create(vals)
  371. quant.inventory_quantity = 10
  372. quant.action_apply_inventory()
  373. self.assertEqual(quant.quantity, 10)
  374. self.assertEqual(quant.inventory_quantity, 0)
  375. def test_inventory_dont_outdate_1(self):
  376. """ Checks that inventory adjustment line isn't marked as outdated when
  377. a non-corresponding quant is created.
  378. """
  379. # Set initial quantity to 7 and create inventory adjustment for product1
  380. inventory_quant = self.env['stock.quant'].create({
  381. 'product_id': self.product1.id,
  382. 'product_uom_id': self.uom_unit.id,
  383. 'location_id': self.stock_location.id,
  384. 'quantity': 7,
  385. 'inventory_quantity': 5
  386. })
  387. # Create quant for product3
  388. product3 = self.env['product.product'].create({
  389. 'name': 'Product C',
  390. 'type': 'product',
  391. 'categ_id': self.env.ref('product.product_category_all').id,
  392. })
  393. self.env['stock.quant'].create({
  394. 'product_id': product3.id,
  395. 'product_uom_id': self.uom_unit.id,
  396. 'location_id': self.stock_location.id,
  397. 'inventory_quantity': 22,
  398. 'reserved_quantity': 0,
  399. })
  400. inventory_quant.action_apply_inventory()
  401. # Expect action apply do not return a wizard
  402. self.assertEqual(inventory_quant.quantity, 5)
  403. def test_cyclic_inventory(self):
  404. """ Check that locations with and without cyclic inventory set has its inventory
  405. dates auto-generate and apply relevant dates.
  406. """
  407. grp_multi_loc = self.env.ref('stock.group_stock_multi_locations')
  408. self.env.user.write({'groups_id': [(4, grp_multi_loc.id)]})
  409. now = datetime.now()
  410. today = now.date()
  411. new_loc = self.env['stock.location'].create({
  412. 'name': 'New Cyclic Inv Location',
  413. 'usage': 'internal',
  414. 'location_id': self.stock_location.id,
  415. })
  416. existing_loc2 = self.env['stock.location'].create({
  417. 'name': 'Pre-existing Cyclic Inv Location',
  418. 'usage': 'internal',
  419. 'location_id': self.stock_location.id,
  420. 'last_inventory_date': now - timedelta(days=5),
  421. })
  422. no_cyclic_loc = self.env['stock.location'].create({
  423. 'name': 'No Cyclic Inv Location',
  424. 'usage': 'internal',
  425. 'location_id': self.stock_location.id,
  426. })
  427. no_cyclic_loc.company_id.write({'annual_inventory_day': str(today.day), 'annual_inventory_month': str(today.month)})
  428. new_loc_form = Form(new_loc)
  429. new_loc_form.cyclic_inventory_frequency = 2
  430. new_loc = new_loc_form.save()
  431. # check next_inventory_date is correctly calculated
  432. existing_loc2_form = Form(existing_loc2)
  433. existing_loc2_form.cyclic_inventory_frequency = 2
  434. existing_loc2 = existing_loc2_form.save()
  435. # next_inventory_date = today + cyclic_inventory_frequency
  436. self.assertEqual(new_loc.next_inventory_date, today + timedelta(days=2))
  437. # previous inventory done + cyclic_inventory_frequency < today => next_inventory_date = tomorrow
  438. self.assertEqual(existing_loc2.next_inventory_date, today + timedelta(days=1))
  439. # check that cyclic inventories are correctly autogenerated
  440. self.env['stock.quant']._update_available_quantity(self.product1, new_loc, 5)
  441. self.env['stock.quant']._update_available_quantity(self.product1, existing_loc2, 5)
  442. self.env['stock.quant']._update_available_quantity(self.product1, no_cyclic_loc, 5)
  443. # cyclic inventory locations should auto-assign their next inventory date to their quants
  444. quant_new_loc = self.env['stock.quant'].search([('location_id', '=', new_loc.id)])
  445. quant_existing_loc = self.env['stock.quant'].search([('location_id', '=', existing_loc2.id)])
  446. self.assertEqual(quant_new_loc.inventory_date, new_loc.next_inventory_date)
  447. self.assertEqual(quant_existing_loc.inventory_date, existing_loc2.next_inventory_date)
  448. # quant without a cyclic inventory location should default to the company's annual inventory date
  449. quant_non_cyclic_loc = self.env['stock.quant'].search([('location_id', '=', no_cyclic_loc.id)])
  450. self.assertEqual(quant_non_cyclic_loc.inventory_date.month, int(no_cyclic_loc.company_id.annual_inventory_month))
  451. self.assertEqual(quant_non_cyclic_loc.inventory_date.day, no_cyclic_loc.company_id.annual_inventory_day)
  452. quant_new_loc.inventory_quantity = 10
  453. (quant_new_loc | quant_existing_loc | quant_non_cyclic_loc).action_apply_inventory()
  454. # check location's last inventory dates + their quants next inventory dates
  455. self.assertEqual(new_loc.last_inventory_date, date.today())
  456. self.assertEqual(existing_loc2.last_inventory_date, date.today())
  457. self.assertEqual(no_cyclic_loc.last_inventory_date, date.today())
  458. self.assertEqual(new_loc.next_inventory_date, date.today() + timedelta(days=2))
  459. self.assertEqual(existing_loc2.next_inventory_date, date.today() + timedelta(days=2))
  460. self.assertEqual(quant_new_loc.inventory_date, date.today() + timedelta(days=2))
  461. self.assertEqual(quant_existing_loc.inventory_date, date.today() + timedelta(days=2))
  462. self.assertEqual(quant_non_cyclic_loc.inventory_date, date.today() + relativedelta(years=1))