test_average_price.py 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. # -*- coding: utf-8 -*-
  2. # Part of Odoo. See LICENSE file for full copyright and licensing details.
  3. from odoo.addons.stock_account.tests.test_anglo_saxon_valuation_reconciliation_common import ValuationReconciliationTestCommon
  4. from odoo.tests import tagged, Form
  5. import time
  6. @tagged('-at_install', 'post_install')
  7. class TestAveragePrice(ValuationReconciliationTestCommon):
  8. def test_00_average_price(self):
  9. """ Testcase for average price computation"""
  10. res_partner_3 = self.env['res.partner'].create({
  11. 'name': 'Gemini Partner',
  12. })
  13. # Set a product as using average price.
  14. product_cable_management_box = self.env['product.product'].create({
  15. 'default_code': 'AVG',
  16. 'name': 'Average Ice Cream',
  17. 'type': 'product',
  18. 'categ_id': self.stock_account_product_categ.id,
  19. 'list_price': 100.0,
  20. 'standard_price': 60.0,
  21. 'uom_id': self.env.ref('uom.product_uom_kgm').id,
  22. 'uom_po_id': self.env.ref('uom.product_uom_kgm').id,
  23. 'supplier_taxes_id': [],
  24. 'description': 'FIFO Ice Cream',
  25. })
  26. product_cable_management_box.categ_id.property_cost_method = 'average'
  27. # I create a draft Purchase Order for first incoming shipment for 10 pieces at 60€
  28. purchase_order_1 = self.env['purchase.order'].create({
  29. 'partner_id': res_partner_3.id,
  30. 'order_line': [(0, 0, {
  31. 'name': 'Average Ice Cream',
  32. 'product_id': product_cable_management_box.id,
  33. 'product_qty': 10.0,
  34. 'product_uom': self.env.ref('uom.product_uom_kgm').id,
  35. 'price_unit': 60.0,
  36. 'date_planned': time.strftime('%Y-%m-%d'),
  37. })]
  38. })
  39. # Confirm the first purchase order
  40. purchase_order_1.button_confirm()
  41. # Check the "Approved" status of purchase order 1
  42. self.assertEqual(purchase_order_1.state, 'purchase', "Wrong state of purchase order!")
  43. # Process the reception of purchase order 1
  44. picking = purchase_order_1.picking_ids[0]
  45. res = picking.button_validate()
  46. Form(self.env[res['res_model']].with_context(res['context'])).save().process()
  47. # Check the average_price of the product (average icecream).
  48. self.assertEqual(product_cable_management_box.qty_available, 10.0, 'Wrong quantity in stock after first reception')
  49. self.assertEqual(product_cable_management_box.standard_price, 60.0, 'Standard price should be the price of the first reception!')
  50. # I create a draft Purchase Order for second incoming shipment for 30 pieces at 80€
  51. purchase_order_2 = self.env['purchase.order'].create({
  52. 'partner_id': res_partner_3.id,
  53. 'order_line': [(0, 0, {
  54. 'name': product_cable_management_box.name,
  55. 'product_id': product_cable_management_box.id,
  56. 'product_qty': 30.0,
  57. 'product_uom': self.env.ref('uom.product_uom_kgm').id,
  58. 'price_unit': 80.0,
  59. 'date_planned': time.strftime('%Y-%m-%d'),
  60. })]
  61. })
  62. # Confirm the second purchase order
  63. purchase_order_2.button_confirm()
  64. # Process the reception of purchase order 2
  65. picking = purchase_order_2.picking_ids[0]
  66. res = picking.button_validate()
  67. Form(self.env['stock.immediate.transfer'].with_context(res['context'])).save().process()
  68. # Check the standard price
  69. self.assertEqual(product_cable_management_box.standard_price, 75.0, 'After second reception, we should have an average price of 75.0 on the product')
  70. # Create picking to send some goods
  71. outgoing_shipment = self.env['stock.picking'].create({
  72. 'picking_type_id': self.company_data['default_warehouse'].out_type_id.id,
  73. 'location_id': self.company_data['default_warehouse'].lot_stock_id.id,
  74. 'location_dest_id': self.env.ref('stock.stock_location_customers').id,
  75. 'move_ids': [(0, 0, {
  76. 'name': 'outgoing_shipment_avg_move',
  77. 'product_id': product_cable_management_box.id,
  78. 'product_uom_qty': 20.0,
  79. 'product_uom': self.env.ref('uom.product_uom_kgm').id,
  80. 'location_id': self.company_data['default_warehouse'].lot_stock_id.id,
  81. 'location_dest_id': self.env.ref('stock.stock_location_customers').id})]
  82. })
  83. # Assign this outgoing shipment and process the delivery
  84. outgoing_shipment.action_assign()
  85. res = outgoing_shipment.button_validate()
  86. Form(self.env['stock.immediate.transfer'].with_context(res['context'])).save().process()
  87. # Check the average price (60 * 10 + 30 * 80) / 40 = 75.0€ did not change
  88. self.assertEqual(product_cable_management_box.standard_price, 75.0, 'Average price should not have changed with outgoing picking!')
  89. self.assertEqual(product_cable_management_box.qty_available, 20.0, 'Pieces were not picked correctly as the quantity on hand is wrong')
  90. # Make a new purchase order with 500 g Average Ice Cream at a price of 0.2€/g
  91. purchase_order_3 = self.env['purchase.order'].create({
  92. 'partner_id': res_partner_3.id,
  93. 'order_line': [(0, 0, {
  94. 'name': product_cable_management_box.name,
  95. 'product_id': product_cable_management_box.id,
  96. 'product_qty': 500.0,
  97. 'product_uom': self.ref('uom.product_uom_gram'),
  98. 'price_unit': 0.2,
  99. 'date_planned': time.strftime('%Y-%m-%d'),
  100. })]
  101. })
  102. # Confirm the first purchase order
  103. purchase_order_3.button_confirm()
  104. # Process the reception of purchase order 3 in grams
  105. picking = purchase_order_3.picking_ids[0]
  106. res = picking.button_validate()
  107. Form(self.env[res['res_model']].with_context(res['context'])).save().process()
  108. # Check price is (75.0 * 20 + 200*0.5) / 20.5 = 78.04878€
  109. self.assertEqual(product_cable_management_box.qty_available, 20.5, 'Reception of purchase order in grams leads to wrong quantity in stock')
  110. self.assertEqual(round(product_cable_management_box.standard_price, 2), 78.05,
  111. 'Standard price as average price of third reception with other UoM incorrect! Got %s instead of 78.05' % (round(product_cable_management_box.standard_price, 2)))
  112. def test_inventory_user_svl_access(self):
  113. """ Test to check if Inventory/User is able to validate a
  114. transfer when the product has been invoiced already """
  115. avco_product = self.env['product.product'].create({
  116. 'name': 'Average Ice Cream',
  117. 'type': 'product',
  118. 'categ_id': self.stock_account_product_categ.id,
  119. 'purchase_method': 'purchase',
  120. })
  121. avco_product.categ_id.property_cost_method = 'average'
  122. purchase_order = self.env['purchase.order'].create({
  123. 'partner_id': self.partner_a.id,
  124. 'order_line': [(0, 0, {
  125. 'product_id': avco_product.id,
  126. 'product_qty': 1.0,
  127. })]
  128. })
  129. purchase_order.button_confirm()
  130. purchase_order.action_create_invoice()
  131. bill = purchase_order.invoice_ids[0]
  132. bill.invoice_date = time.strftime('%Y-%m-%d')
  133. bill.invoice_line_ids[0].quantity = 1.0
  134. bill.action_post()
  135. self.assertEqual(purchase_order.order_line[0].qty_invoiced, 1.0, 'QTY invoiced should have been set to 1 on the purchase order line')
  136. picking = purchase_order.picking_ids[0]
  137. picking.action_set_quantities_to_reservation()
  138. # clear cash to ensure access rights verification
  139. self.env.invalidate_all()
  140. picking.with_user(self.res_users_stock_user).button_validate()
  141. self.assertEqual(picking.state, 'done', 'Transfer should be in the DONE state')