[MERGE] stock: picking: button_validate multi
preliminary work for - task 1938108 (which is adding a pre action done wizard) - task 1938656 (which is adding another pre action done wizard) - task 2069646 (which will rework all pre action done wizard to select to pickings to apply) closes odoo/odoo#39318 Signed-off-by: Simon Lejeune (sle) <sle@openerp.com>
This commit is contained in:
@@ -36,7 +36,6 @@ class StockPicking(models.Model):
|
||||
# -------------------------------------------------------------------------
|
||||
# Action methods
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def action_cancel(self):
|
||||
for picking in self:
|
||||
picking._get_subcontracted_productions()._action_cancel()
|
||||
|
||||
@@ -526,7 +526,7 @@ class TestSubcontractingFlows(TestMrpSubcontractingCommon):
|
||||
|
||||
picking_receipt.move_lines.quantity_done = 3
|
||||
backorder_wiz = picking_receipt.button_validate()
|
||||
backorder_wiz = self.env['stock.backorder.confirmation'].browse(backorder_wiz['res_id'])
|
||||
backorder_wiz = self.env[backorder_wiz['res_model']].browse(backorder_wiz['res_id']).with_context(backorder_wiz['context'])
|
||||
backorder_wiz.process()
|
||||
|
||||
backorder = self.env['stock.picking'].search([('backorder_id', '=', picking_receipt.id)])
|
||||
|
||||
@@ -265,8 +265,9 @@ class TestSaleMrpFlow(TransactionCase):
|
||||
move_lines.write({'quantity_done': qty_to_process})
|
||||
|
||||
# Create a backorder for the missing componenents
|
||||
backorder_wizard = self.env['stock.backorder.confirmation'].create({'pick_ids': [(4, po.picking_ids[0].id)]})
|
||||
backorder_wizard.process()
|
||||
pick = po.picking_ids[0]
|
||||
res = pick.button_validate()
|
||||
self.env[res['res_model']].browse(res['res_id']).with_context(res['context']).process()
|
||||
|
||||
# Check that a backorded is created
|
||||
self.assertEqual(len(po.picking_ids), 2)
|
||||
@@ -285,8 +286,8 @@ class TestSaleMrpFlow(TransactionCase):
|
||||
self._process_quantities(backorder_1.move_lines, qty_to_process)
|
||||
|
||||
# Create a backorder for the missing componenents
|
||||
backorder_wizard = self.env['stock.backorder.confirmation'].create({'pick_ids': [(4, backorder_1.id)]})
|
||||
backorder_wizard.process()
|
||||
res = backorder_1.button_validate()
|
||||
self.env[res['res_model']].browse(res['res_id']).with_context(res['context']).process()
|
||||
|
||||
# Only 1 kit_parent should be received at this point
|
||||
self.assertEqual(order_line.qty_received, 1)
|
||||
@@ -324,8 +325,8 @@ class TestSaleMrpFlow(TransactionCase):
|
||||
self._process_quantities(backorder_2.move_lines, qty_to_process)
|
||||
|
||||
# Create a backorder for the missing componenents
|
||||
backorder_wizard = self.env['stock.backorder.confirmation'].create({'pick_ids': [(4, backorder_2.id)]})
|
||||
backorder_wizard.process()
|
||||
res = backorder_2.button_validate()
|
||||
self.env[res['res_model']].browse(res['res_id']).with_context(res['context']).process()
|
||||
|
||||
# Check that x3 kit_parents are indeed received
|
||||
self.assertEqual(order_line.qty_received, 3)
|
||||
@@ -369,7 +370,7 @@ class TestSaleMrpFlow(TransactionCase):
|
||||
|
||||
# Process all components and validate the picking
|
||||
wiz_act = return_pick.button_validate()
|
||||
wiz = self.env[wiz_act['res_model']].browse(wiz_act['res_id'])
|
||||
wiz = self.env[wiz_act['res_model']].browse(wiz_act['res_id']).with_context(wiz_act['context'])
|
||||
wiz.process()
|
||||
|
||||
# Now quantity received should be 3 again
|
||||
@@ -391,8 +392,9 @@ class TestSaleMrpFlow(TransactionCase):
|
||||
'to_refund': True
|
||||
})
|
||||
|
||||
backorder_wizard = self.env['stock.backorder.confirmation'].create({'pick_ids': [(4, return_of_return_pick.id)]})
|
||||
backorder_wizard.process()
|
||||
wiz_act = return_of_return_pick.button_validate()
|
||||
wiz = self.env[wiz_act['res_model']].browse(wiz_act['res_id']).with_context(wiz_act['context'])
|
||||
wiz.process()
|
||||
|
||||
# As one of each component is missing, only 6 kit_parents should be received
|
||||
self.assertEqual(order_line.qty_received, 6)
|
||||
|
||||
@@ -53,7 +53,8 @@ class TestAveragePrice(TestPurchase):
|
||||
|
||||
# Process the reception of purchase order 1
|
||||
picking = purchase_order_1.picking_ids[0]
|
||||
self.env['stock.immediate.transfer'].create({'pick_ids': [(4, picking.id)]}).process()
|
||||
res = picking.button_validate()
|
||||
self.env[res['res_model']].browse(res['res_id']).with_context(res['context']).process()
|
||||
|
||||
# Check the average_price of the product (average icecream).
|
||||
self.assertEqual(product_cable_management_box.qty_available, 10.0, 'Wrong quantity in stock after first reception')
|
||||
@@ -76,7 +77,8 @@ class TestAveragePrice(TestPurchase):
|
||||
purchase_order_2.button_confirm()
|
||||
# Process the reception of purchase order 2
|
||||
picking = purchase_order_2.picking_ids[0]
|
||||
self.env['stock.immediate.transfer'].create({'pick_ids': [(4, picking.id)]}).process()
|
||||
res = picking.button_validate()
|
||||
self.env['stock.immediate.transfer'].browse(res['res_id']).with_context(res['context']).process()
|
||||
|
||||
# Check the standard price
|
||||
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')
|
||||
@@ -97,7 +99,8 @@ class TestAveragePrice(TestPurchase):
|
||||
|
||||
# Assign this outgoing shipment and process the delivery
|
||||
outgoing_shipment.action_assign()
|
||||
self.env['stock.immediate.transfer'].create({'pick_ids': [(4, outgoing_shipment.id)]}).process()
|
||||
res = outgoing_shipment.button_validate()
|
||||
self.env['stock.immediate.transfer'].browse(res['res_id']).with_context(res['context']).process()
|
||||
|
||||
# Check the average price (60 * 10 + 30 * 80) / 40 = 75.0€ did not change
|
||||
self.assertEqual(product_cable_management_box.standard_price, 75.0, 'Average price should not have changed with outgoing picking!')
|
||||
@@ -119,8 +122,10 @@ class TestAveragePrice(TestPurchase):
|
||||
# Confirm the first purchase order
|
||||
purchase_order_3.button_confirm()
|
||||
# Process the reception of purchase order 3 in grams
|
||||
|
||||
picking = purchase_order_3.picking_ids[0]
|
||||
self.env['stock.immediate.transfer'].create({'pick_ids': [(4, picking.id)]}).process()
|
||||
res = picking.button_validate()
|
||||
self.env[res['res_model']].browse(res['res_id']).with_context(res['context']).process()
|
||||
|
||||
# Check price is (75.0 * 20 + 200*0.5) / 20.5 = 78.04878€
|
||||
self.assertEqual(product_cable_management_box.qty_available, 20.5, 'Reception of purchase order in grams leads to wrong quantity in stock')
|
||||
|
||||
@@ -51,7 +51,8 @@ class TestFifoPrice(TestPurchase):
|
||||
|
||||
# Process the reception of purchase order 1 and set date
|
||||
picking = purchase_order_1.picking_ids[0]
|
||||
self.env['stock.immediate.transfer'].create({'pick_ids': [(4, picking.id)]}).process()
|
||||
res = picking.button_validate()
|
||||
self.env[res['res_model']].browse(res['res_id']).with_context(res['context']).process()
|
||||
|
||||
# Check the standard price of the product (fifo icecream), that should have not changed
|
||||
# because the standard price is supposed to be updated only when goods are going out of the stock
|
||||
@@ -75,7 +76,8 @@ class TestFifoPrice(TestPurchase):
|
||||
|
||||
# Process the reception of purchase order 2
|
||||
picking = purchase_order_2.picking_ids[0]
|
||||
self.env['stock.immediate.transfer'].create({'pick_ids': [(4, picking.id)]}).process()
|
||||
res = picking.button_validate()
|
||||
self.env[res['res_model']].browse(res['res_id']).with_context(res['context']).process()
|
||||
|
||||
# Check the standard price of the product, that should have not changed because the
|
||||
# standard price is supposed to be updated only when goods are going out of the stock
|
||||
@@ -101,7 +103,8 @@ class TestFifoPrice(TestPurchase):
|
||||
outgoing_shipment.action_assign()
|
||||
|
||||
# Process the delivery of the outgoing shipment
|
||||
self.env['stock.immediate.transfer'].create({'pick_ids': [(4, outgoing_shipment.id)]}).process()
|
||||
res = outgoing_shipment.button_validate()
|
||||
self.env[res['res_model']].browse(res['res_id']).with_context(res['context']).process()
|
||||
|
||||
# Check stock value became 1600 .
|
||||
self.assertEqual(product_cable_management_box.value_svl, 1600.0, 'Stock valuation should be 1600')
|
||||
@@ -125,7 +128,8 @@ class TestFifoPrice(TestPurchase):
|
||||
outgoing_shipment_uom.action_assign()
|
||||
|
||||
# Process the delivery of the outgoing shipment
|
||||
self.env['stock.immediate.transfer'].create({'pick_ids': [(4, outgoing_shipment_uom.id)]}).process()
|
||||
res = outgoing_shipment_uom.button_validate()
|
||||
self.env[res['res_model']].browse(res['res_id']).with_context(res['context']).process()
|
||||
|
||||
# Check stock valuation and qty in stock
|
||||
self.assertEqual(product_cable_management_box.value_svl, 1560.0, 'Stock valuation should be 1560')
|
||||
@@ -162,7 +166,8 @@ class TestFifoPrice(TestPurchase):
|
||||
purchase_order_usd.button_confirm()
|
||||
# Process the reception of purchase order with USD
|
||||
picking = purchase_order_usd.picking_ids[0]
|
||||
self.env['stock.immediate.transfer'].create({'pick_ids': [(4, picking.id)]}).process()
|
||||
res = picking.button_validate()
|
||||
self.env[res['res_model']].browse(res['res_id']).with_context(res['context']).process()
|
||||
|
||||
# Create delivery order of 49.5 kg
|
||||
outgoing_shipment_cur = self.env['stock.picking'].create({
|
||||
@@ -183,7 +188,8 @@ class TestFifoPrice(TestPurchase):
|
||||
outgoing_shipment_cur.action_assign()
|
||||
|
||||
# Process the delivery of the outgoing shipment
|
||||
self.env['stock.immediate.transfer'].create({'pick_ids': [(4, outgoing_shipment_cur.id)]}).process()
|
||||
res = outgoing_shipment_cur.button_validate()
|
||||
self.env[res['res_model']].browse(res['res_id']).with_context(res['context']).process()
|
||||
|
||||
# Do a delivery of an extra 10 kg
|
||||
outgoing_shipment_ret = self.env['stock.picking'].create({
|
||||
@@ -202,7 +208,8 @@ class TestFifoPrice(TestPurchase):
|
||||
|
||||
# I assign this outgoing shipment
|
||||
outgoing_shipment_ret.action_assign()
|
||||
self.env['stock.immediate.transfer'].create({'pick_ids': [(4, outgoing_shipment_ret.id)]}).process()
|
||||
res = outgoing_shipment_ret.button_validate()
|
||||
self.env[res['res_model']].browse(res['res_id']).with_context(res['context']).process()
|
||||
|
||||
# Check rounded price is 150.0 / 1.2834
|
||||
self.assertEqual(round(product_cable_management_box.qty_available), 0.0, 'Wrong quantity in stock after first reception.')
|
||||
@@ -291,7 +298,8 @@ class TestFifoPrice(TestPurchase):
|
||||
|
||||
# Process the reception of purchase order neg
|
||||
picking = purchase_order_neg.picking_ids[0]
|
||||
self.env['stock.immediate.transfer'].create({'pick_ids': [(4, picking.id)]}).process()
|
||||
res = picking.button_validate()
|
||||
self.env[res['res_model']].browse(res['res_id']).with_context(res['context']).process()
|
||||
|
||||
# Receive purchase order with 600 kg FIFO Ice Cream at 80 euro/kg
|
||||
purchase_order_neg2 = self.env['purchase.order'].create({
|
||||
@@ -310,7 +318,8 @@ class TestFifoPrice(TestPurchase):
|
||||
|
||||
# Process the reception of purchase order neg2
|
||||
picking = purchase_order_neg2.picking_ids[0]
|
||||
self.env['stock.immediate.transfer'].create({'pick_ids': [(4, picking.id)]}).process()
|
||||
res = picking.button_validate()
|
||||
self.env[res['res_model']].browse(res['res_id']).with_context(res['context']).process()
|
||||
|
||||
original_out_move = outgoing_shipment_neg.move_lines[0]
|
||||
self.assertEqual(original_out_move.product_id.value_svl, 12000.0, 'Value of the move should be 12000')
|
||||
|
||||
@@ -60,7 +60,8 @@ class TestFifoReturns(TestPurchase):
|
||||
|
||||
# Process the reception of purchase order 1
|
||||
picking = purchase_order_1.picking_ids[0]
|
||||
self.env['stock.immediate.transfer'].create({'pick_ids': [(4, picking.id)]}).process()
|
||||
res = picking.button_validate()
|
||||
self.env[res['res_model']].browse(res['res_id']).with_context(res['context']).process()
|
||||
|
||||
# Check the standard price of the product (fifo icecream)
|
||||
self.assertEqual(product_fiforet_icecream.standard_price, 0.0, 'Standard price should not have changed!')
|
||||
@@ -68,7 +69,8 @@ class TestFifoReturns(TestPurchase):
|
||||
# Confirm the second purchase order
|
||||
purchase_order_2.button_confirm()
|
||||
picking = purchase_order_2.picking_ids[0]
|
||||
self.env['stock.immediate.transfer'].create({'pick_ids': [(4, picking.id)]}).process()
|
||||
res = picking.button_validate()
|
||||
self.env[res['res_model']].browse(res['res_id']).with_context(res['context']).process()
|
||||
|
||||
# Return the goods of purchase order 2
|
||||
picking = purchase_order_2.picking_ids[0]
|
||||
|
||||
@@ -84,7 +84,7 @@ class TestStockValuation(TransactionCase):
|
||||
|
||||
# validate the receipt
|
||||
res_dict = picking1.button_validate()
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id'))
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id')).with_context(res_dict['context'])
|
||||
wizard.process()
|
||||
|
||||
# the unit price of the valuationlayer used the latest value
|
||||
@@ -132,7 +132,7 @@ class TestStockValuation(TransactionCase):
|
||||
|
||||
# validate the receipt
|
||||
res_dict = picking1.button_validate()
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id'))
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id')).with_context(res_dict['context'])
|
||||
wizard.process()
|
||||
|
||||
# the unit price of the valuation layer used the latest value
|
||||
@@ -202,7 +202,7 @@ class TestStockValuation(TransactionCase):
|
||||
|
||||
# validate the receipt
|
||||
res_dict = picking1.button_validate()
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id'))
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id')).with_context(res_dict['context'])
|
||||
wizard.process()
|
||||
|
||||
# the unit price of the valuation layer used the latest value
|
||||
@@ -267,7 +267,7 @@ class TestStockValuation(TransactionCase):
|
||||
move1.quantity_done = 5
|
||||
res_dict = picking1.button_validate()
|
||||
self.assertEqual(res_dict['res_model'], 'stock.backorder.confirmation')
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id'))
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id')).with_context(res_dict['context'])
|
||||
wizard.process()
|
||||
|
||||
self.assertEqual(len(picking1.move_lines), 1)
|
||||
|
||||
@@ -535,7 +535,7 @@ class TestSaleMrpFlow(common.SavepointCase):
|
||||
pick = so.picking_ids
|
||||
pick.move_lines.write({'quantity_done': 1})
|
||||
wiz_act = pick.button_validate()
|
||||
wiz = self.env[wiz_act['res_model']].browse(wiz_act['res_id'])
|
||||
wiz = self.env[wiz_act['res_model']].browse(wiz_act['res_id']).with_context(wiz_act['context'])
|
||||
wiz.process()
|
||||
self.assertEqual(so.invoice_status, 'no', 'Sale MRP: so invoice_status should be "no" after partial delivery of a kit')
|
||||
del_qty = sum(sol.qty_delivered for sol in so.order_line)
|
||||
@@ -653,7 +653,7 @@ class TestSaleMrpFlow(common.SavepointCase):
|
||||
# To check the products on the picking
|
||||
self.assertEqual(pick.move_lines.mapped('product_id'), self.component1 | self.component2)
|
||||
wiz_act = pick.button_validate()
|
||||
wiz = self.env[wiz_act['res_model']].browse(wiz_act['res_id'])
|
||||
wiz = self.env[wiz_act['res_model']].browse(wiz_act['res_id']).with_context(wiz_act['context'])
|
||||
wiz.process()
|
||||
# Create the invoice
|
||||
self.so._create_invoices()
|
||||
@@ -732,8 +732,9 @@ class TestSaleMrpFlow(common.SavepointCase):
|
||||
|
||||
# Process only x1 of the first component then create a backorder for the missing components
|
||||
picking_original.move_lines.sorted()[0].write({'quantity_done': 1})
|
||||
backorder_wizard = self.env['stock.backorder.confirmation'].create({'pick_ids': [(4, so.picking_ids[0].id)]})
|
||||
backorder_wizard.process()
|
||||
|
||||
wiz_act = so.picking_ids[0].button_validate()
|
||||
wiz = self.env[wiz_act['res_model']].browse(wiz_act['res_id']).with_context(wiz_act['context']).process()
|
||||
|
||||
# Check that the backorder was created, no kit should be delivered at this point
|
||||
self.assertEqual(len(so.picking_ids), 2)
|
||||
@@ -744,8 +745,8 @@ class TestSaleMrpFlow(common.SavepointCase):
|
||||
# Process only x6 each componenent in the picking
|
||||
# Then create a backorder for the missing components
|
||||
backorder_1.move_lines.write({'quantity_done': 6})
|
||||
backorder_wizard = self.env['stock.backorder.confirmation'].create({'pick_ids': [(4, backorder_1.id)]})
|
||||
backorder_wizard.process()
|
||||
wiz_act = backorder_1.button_validate()
|
||||
wiz = self.env[wiz_act['res_model']].browse(wiz_act['res_id']).with_context(wiz_act['context']).process()
|
||||
|
||||
# Check that a backorder is created
|
||||
self.assertEqual(len(so.picking_ids), 3)
|
||||
@@ -761,8 +762,8 @@ class TestSaleMrpFlow(common.SavepointCase):
|
||||
# - A backorder will be created, the SO should have 3 picking_ids linked to it.
|
||||
backorder_2.move_lines.write({'quantity_done': 3})
|
||||
|
||||
backorder_wizard = self.env['stock.backorder.confirmation'].create({'pick_ids': [(4, backorder_2.id)]})
|
||||
backorder_wizard.process()
|
||||
wiz_act = backorder_2.button_validate()
|
||||
wiz = self.env[wiz_act['res_model']].browse(wiz_act['res_id']).with_context(wiz_act['context']).process()
|
||||
|
||||
self.assertEqual(len(so.picking_ids), 4)
|
||||
backorder_3 = so.picking_ids - picking_original - backorder_2 - backorder_1
|
||||
@@ -854,8 +855,8 @@ class TestSaleMrpFlow(common.SavepointCase):
|
||||
move_lines.write({'quantity_done': qty_to_process})
|
||||
|
||||
# Create a backorder for the missing componenents
|
||||
backorder_wizard = self.env['stock.backorder.confirmation'].create({'pick_ids': [(4, so.picking_ids[0].id)]})
|
||||
backorder_wizard.process()
|
||||
wiz_act = picking_original.button_validate()
|
||||
wiz = self.env[wiz_act['res_model']].browse(wiz_act['res_id']).with_context(wiz_act['context']).process()
|
||||
|
||||
# Check that a backorded is created
|
||||
self.assertEqual(len(so.picking_ids), 2)
|
||||
@@ -874,8 +875,8 @@ class TestSaleMrpFlow(common.SavepointCase):
|
||||
self._process_quantities(backorder_1.move_lines, qty_to_process)
|
||||
|
||||
# Create a backorder for the missing componenents
|
||||
backorder_wizard = self.env['stock.backorder.confirmation'].create({'pick_ids': [(4, backorder_1.id)]})
|
||||
backorder_wizard.process()
|
||||
wiz_act = backorder_1.button_validate()
|
||||
wiz = self.env[wiz_act['res_model']].browse(wiz_act['res_id']).with_context(wiz_act['context']).process()
|
||||
|
||||
# Only 1 kit_parent should be delivered at this point
|
||||
self.assertEqual(order_line.qty_delivered, 1)
|
||||
@@ -913,8 +914,8 @@ class TestSaleMrpFlow(common.SavepointCase):
|
||||
self._process_quantities(backorder_2.move_lines, qty_to_process)
|
||||
|
||||
# Create a backorder for the missing componenents
|
||||
backorder_wizard = self.env['stock.backorder.confirmation'].create({'pick_ids': [(4, backorder_2.id)]})
|
||||
backorder_wizard.process()
|
||||
wiz_act = backorder_2.button_validate()
|
||||
wiz = self.env[wiz_act['res_model']].browse(wiz_act['res_id']).with_context(wiz_act['context']).process()
|
||||
|
||||
# Check that x3 kit_parents are indeed delivered
|
||||
self.assertEqual(order_line.qty_delivered, 3)
|
||||
@@ -958,7 +959,7 @@ class TestSaleMrpFlow(common.SavepointCase):
|
||||
|
||||
# Process all components and validate the picking
|
||||
wiz_act = return_pick.button_validate()
|
||||
wiz = self.env[wiz_act['res_model']].browse(wiz_act['res_id'])
|
||||
wiz = self.env[wiz_act['res_model']].browse(wiz_act['res_id']).with_context(wiz_act['context'])
|
||||
wiz.process()
|
||||
|
||||
# Now quantity delivered should be 3 again
|
||||
@@ -980,8 +981,8 @@ class TestSaleMrpFlow(common.SavepointCase):
|
||||
'to_refund': True
|
||||
})
|
||||
|
||||
backorder_wizard = self.env['stock.backorder.confirmation'].create({'pick_ids': [(4, return_of_return_pick.id)]})
|
||||
backorder_wizard.process()
|
||||
wiz_act = return_of_return_pick.button_validate()
|
||||
self.env[wiz_act['res_model']].browse(wiz_act['res_id']).with_context(wiz_act['context']).process()
|
||||
|
||||
# As one of each component is missing, only 6 kit_parents should be delivered
|
||||
self.assertEqual(order_line.qty_delivered, 6)
|
||||
@@ -1174,9 +1175,8 @@ class TestSaleMrpFlow(common.SavepointCase):
|
||||
component_uom_kg: 0.006
|
||||
}
|
||||
self._process_quantities(move_lines, qty_to_process)
|
||||
backorder_wizard = self.env['stock.backorder.confirmation'].create(
|
||||
{'pick_ids': [(4, so.picking_ids[0].id)]})
|
||||
backorder_wizard.process()
|
||||
res = move_lines.picking_id.button_validate()
|
||||
self.env[res['res_model']].browse(res['res_id']).with_context(res['context']).process()
|
||||
|
||||
# Check that a backorder is created
|
||||
self.assertEqual(len(so.picking_ids), 2)
|
||||
|
||||
@@ -203,7 +203,7 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
# Deliver one.
|
||||
sale_order.picking_ids.move_lines.quantity_done = 1
|
||||
wiz = sale_order.picking_ids.button_validate()
|
||||
wiz = self.env[wiz['res_model']].browse(wiz['res_id'])
|
||||
wiz = self.env[wiz['res_model']].browse(wiz['res_id']).with_context(wiz['context'])
|
||||
wiz.process()
|
||||
|
||||
# Invoice 1
|
||||
@@ -275,7 +275,7 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
# Deliver one.
|
||||
sale_order.picking_ids.move_lines.quantity_done = 1
|
||||
wiz = sale_order.picking_ids.button_validate()
|
||||
wiz = self.env[wiz['res_model']].browse(wiz['res_id'])
|
||||
wiz = self.env[wiz['res_model']].browse(wiz['res_id']).with_context(wiz['context'])
|
||||
wiz.process()
|
||||
|
||||
# change the standard price to 14
|
||||
@@ -342,7 +342,7 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
# Deliver one.
|
||||
sale_order.picking_ids.move_lines.quantity_done = 1
|
||||
wiz = sale_order.picking_ids.button_validate()
|
||||
wiz = self.env[wiz['res_model']].browse(wiz['res_id'])
|
||||
wiz = self.env[wiz['res_model']].browse(wiz['res_id']).with_context(wiz['context'])
|
||||
wiz.process()
|
||||
|
||||
# Invoice 1
|
||||
@@ -414,7 +414,7 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
# Deliver one.
|
||||
sale_order.picking_ids.move_lines.quantity_done = 1
|
||||
wiz = sale_order.picking_ids.button_validate()
|
||||
wiz = self.env[wiz['res_model']].browse(wiz['res_id'])
|
||||
wiz = self.env[wiz['res_model']].browse(wiz['res_id']).with_context(wiz['context'])
|
||||
wiz.process()
|
||||
|
||||
# change the standard price to 14
|
||||
@@ -494,7 +494,7 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
# Deliver one.
|
||||
sale_order.picking_ids.move_lines.quantity_done = 1
|
||||
wiz = sale_order.picking_ids.button_validate()
|
||||
wiz = self.env[wiz['res_model']].browse(wiz['res_id'])
|
||||
wiz = self.env[wiz['res_model']].browse(wiz['res_id']).with_context(wiz['context'])
|
||||
wiz.process()
|
||||
|
||||
# Invoice the sale order.
|
||||
@@ -588,7 +588,7 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
# Deliver one.
|
||||
sale_order.picking_ids.move_lines.quantity_done = 1
|
||||
wiz = sale_order.picking_ids.button_validate()
|
||||
wiz = self.env[wiz['res_model']].browse(wiz['res_id'])
|
||||
wiz = self.env[wiz['res_model']].browse(wiz['res_id']).with_context(wiz['context'])
|
||||
wiz.process()
|
||||
|
||||
# Invoice the sale order.
|
||||
@@ -694,7 +694,7 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
# Deliver one.
|
||||
sale_order.picking_ids.move_lines.quantity_done = 1
|
||||
wiz = sale_order.picking_ids.button_validate()
|
||||
wiz = self.env[wiz['res_model']].browse(wiz['res_id'])
|
||||
wiz = self.env[wiz['res_model']].browse(wiz['res_id']).with_context(wiz['context'])
|
||||
wiz.process()
|
||||
|
||||
# upate the standard price to 12
|
||||
@@ -790,7 +790,7 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
# Deliver one.
|
||||
sale_order.picking_ids.move_lines.quantity_done = 1
|
||||
wiz = sale_order.picking_ids.button_validate()
|
||||
wiz = self.env[wiz['res_model']].browse(wiz['res_id'])
|
||||
wiz = self.env[wiz['res_model']].browse(wiz['res_id']).with_context(wiz['context'])
|
||||
wiz.process()
|
||||
|
||||
# upate the standard price to 12
|
||||
|
||||
@@ -57,7 +57,7 @@ class TestSaleStock(TestSale):
|
||||
pick = self.so.picking_ids
|
||||
pick.move_lines.write({'quantity_done': 1})
|
||||
wiz_act = pick.button_validate()
|
||||
wiz = self.env[wiz_act['res_model']].browse(wiz_act['res_id'])
|
||||
wiz = self.env[wiz_act['res_model']].browse(wiz_act['res_id']).with_context(wiz_act['context'])
|
||||
wiz.process()
|
||||
self.assertEqual(self.so.invoice_status, 'to invoice', 'Sale Stock: so invoice_status should be "to invoice" after partial delivery')
|
||||
del_qties = [sol.qty_delivered for sol in self.so.order_line]
|
||||
@@ -74,7 +74,7 @@ class TestSaleStock(TestSale):
|
||||
self.assertEqual(len(self.so.picking_ids), 2, 'Sale Stock: number of pickings should be 2')
|
||||
pick_2 = self.so.picking_ids.filtered('backorder_id')
|
||||
pick_2.move_lines.write({'quantity_done': 1})
|
||||
self.assertIsNone(pick_2.button_validate(), 'Sale Stock: second picking should be final without need for a backorder')
|
||||
self.assertTrue(pick_2.button_validate(), 'Sale Stock: second picking should be final without need for a backorder')
|
||||
self.assertEqual(self.so.invoice_status, 'to invoice', 'Sale Stock: so invoice_status should be "to invoice" after complete delivery')
|
||||
del_qties = [sol.qty_delivered for sol in self.so.order_line]
|
||||
del_qties_truth = [2.0 if sol.product_id.type in ['product', 'consu'] else 0.0 for sol in self.so.order_line]
|
||||
@@ -137,7 +137,7 @@ class TestSaleStock(TestSale):
|
||||
# deliver, check the delivered quantities
|
||||
pick = self.so.picking_ids
|
||||
pick.move_lines.write({'quantity_done': 2})
|
||||
self.assertIsNone(pick.button_validate(), 'Sale Stock: complete delivery should not need a backorder')
|
||||
self.assertTrue(pick.button_validate(), 'Sale Stock: complete delivery should not need a backorder')
|
||||
del_qties = [sol.qty_delivered for sol in self.so.order_line]
|
||||
del_qties_truth = [2.0 if sol.product_id.type in ['product', 'consu'] else 0.0 for sol in self.so.order_line]
|
||||
self.assertEqual(del_qties, del_qties_truth, 'Sale Stock: delivered quantities are wrong after partial delivery')
|
||||
@@ -250,7 +250,7 @@ class TestSaleStock(TestSale):
|
||||
pick = self.so.picking_ids
|
||||
pick.move_lines.write({'quantity_done': 4})
|
||||
res_dict = pick.button_validate()
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id'))
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id')).with_context(res_dict['context'])
|
||||
wizard.process_cancel_backorder()
|
||||
|
||||
# Check quantity delivered
|
||||
@@ -293,10 +293,10 @@ class TestSaleStock(TestSale):
|
||||
# will ask to create a backorder for the unavailable product.
|
||||
self.assertEqual(len(self.so.picking_ids), 1)
|
||||
res_dict = self.so.picking_ids.sorted()[0].button_validate()
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id'))
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id')).with_context(res_dict['context'])
|
||||
self.assertEqual(wizard._name, 'stock.immediate.transfer')
|
||||
res_dict = wizard.process()
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id'))
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id')).with_context(res_dict['context'])
|
||||
self.assertEqual(wizard._name, 'stock.backorder.confirmation')
|
||||
wizard.process()
|
||||
|
||||
@@ -357,7 +357,7 @@ class TestSaleStock(TestSale):
|
||||
# deliver them
|
||||
self.assertEqual(len(self.so.picking_ids), 1)
|
||||
res_dict = self.so.picking_ids.sorted()[0].button_validate()
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id'))
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id')).with_context(res_dict['context'])
|
||||
wizard.process()
|
||||
self.assertEqual(self.so.picking_ids.sorted()[0].state, "done")
|
||||
|
||||
@@ -583,7 +583,7 @@ class TestSaleStock(TestSale):
|
||||
|
||||
picking = so1.picking_ids
|
||||
wiz_act = picking.button_validate()
|
||||
wiz = self.env[wiz_act['res_model']].browse(wiz_act['res_id'])
|
||||
wiz = self.env[wiz_act['res_model']].browse(wiz_act['res_id']).with_context(wiz_act['context'])
|
||||
wiz.process()
|
||||
|
||||
# Return 5 units
|
||||
@@ -601,7 +601,7 @@ class TestSaleStock(TestSale):
|
||||
res = return_wiz.create_returns()
|
||||
return_pick = self.env['stock.picking'].browse(res['res_id'])
|
||||
wiz_act = return_pick.button_validate()
|
||||
wiz = self.env[wiz_act['res_model']].browse(wiz_act['res_id'])
|
||||
wiz = self.env[wiz_act['res_model']].browse(wiz_act['res_id']).with_context(wiz_act['context'])
|
||||
wiz.process()
|
||||
|
||||
self.assertEqual(so1.order_line.qty_delivered, 5)
|
||||
|
||||
@@ -782,66 +782,62 @@ class Picking(models.Model):
|
||||
picking.move_lines._do_unreserve()
|
||||
picking.package_level_ids.filtered(lambda p: not p.move_ids).unlink()
|
||||
|
||||
def _check_sms_confirmation_popup(self):
|
||||
return False
|
||||
|
||||
def button_validate(self):
|
||||
self.ensure_one()
|
||||
if not self.move_lines and not self.move_line_ids:
|
||||
raise UserError(_('Please add some items to move.'))
|
||||
# Sanity checks.
|
||||
for picking in self:
|
||||
if not picking.move_lines and not picking.move_line_ids:
|
||||
raise UserError(_('Please add some items to move.'))
|
||||
|
||||
# If no lots when needed, raise error
|
||||
picking_type = self.picking_type_id
|
||||
precision_digits = self.env['decimal.precision'].precision_get('Product Unit of Measure')
|
||||
no_quantities_done = all(float_is_zero(move_line.qty_done, precision_digits=precision_digits) for move_line in self.move_line_ids.filtered(lambda m: m.state not in ('done', 'cancel')))
|
||||
no_reserved_quantities = all(float_is_zero(move_line.product_qty, precision_rounding=move_line.product_uom_id.rounding) for move_line in self.move_line_ids)
|
||||
if no_reserved_quantities and no_quantities_done:
|
||||
raise UserError(_('You cannot validate a transfer if no quantites are reserved nor done. To force the transfer, switch in edit more and encode the done quantities.'))
|
||||
# If no lots when needed, raise error
|
||||
picking_type = picking.picking_type_id
|
||||
precision_digits = self.env['decimal.precision'].precision_get('Product Unit of Measure')
|
||||
no_quantities_done = all(float_is_zero(move_line.qty_done, precision_digits=precision_digits) for move_line in picking.move_line_ids.filtered(lambda m: m.state not in ('done', 'cancel')))
|
||||
no_reserved_quantities = all(float_is_zero(move_line.product_qty, precision_rounding=move_line.product_uom_id.rounding) for move_line in picking.move_line_ids)
|
||||
if no_reserved_quantities and no_quantities_done:
|
||||
raise UserError(_('You cannot validate a transfer if no quantites are reserved nor done. To force the transfer, switch in edit more and encode the done quantities.'))
|
||||
|
||||
if picking_type.use_create_lots or picking_type.use_existing_lots:
|
||||
lines_to_check = self.move_line_ids
|
||||
if not no_quantities_done:
|
||||
lines_to_check = lines_to_check.filtered(
|
||||
lambda line: float_compare(line.qty_done, 0,
|
||||
precision_rounding=line.product_uom_id.rounding)
|
||||
)
|
||||
if picking_type.use_create_lots or picking_type.use_existing_lots:
|
||||
lines_to_check = picking.move_line_ids
|
||||
if not no_quantities_done:
|
||||
lines_to_check = lines_to_check.filtered(lambda line: float_compare(line.qty_done, 0, precision_rounding=line.product_uom_id.rounding))
|
||||
for line in lines_to_check:
|
||||
product = line.product_id
|
||||
if product and product.tracking != 'none':
|
||||
if not line.lot_name and not line.lot_id:
|
||||
raise UserError(_('You need to supply a Lot/Serial number for product %s.') % product.display_name)
|
||||
|
||||
for line in lines_to_check:
|
||||
product = line.product_id
|
||||
if product and product.tracking != 'none':
|
||||
if not line.lot_name and not line.lot_id:
|
||||
raise UserError(_('You need to supply a Lot/Serial number for product %s.') % product.display_name)
|
||||
# Run the pre-validation wizards. Processing a pre-validation wizard should work on the
|
||||
# moves and/or the context and never call `_action_done`.
|
||||
if not self.env.context.get('button_validate_picking_ids'):
|
||||
self = self.with_context(button_validate_picking_ids=self.ids)
|
||||
res = self._pre_action_done_hook()
|
||||
if res is not True:
|
||||
return res
|
||||
|
||||
# Propose to use the sms mechanism the first time a delivery
|
||||
# picking is validated. Whatever the user's decision (use it or not),
|
||||
# the method button_validate is called again (except if it's cancel),
|
||||
# so the checks are made twice in that case, but the flow is not broken
|
||||
sms_confirmation = self._check_sms_confirmation_popup()
|
||||
if sms_confirmation:
|
||||
return sms_confirmation
|
||||
# Call `_action_done`.
|
||||
if self.env.context.get('picking_ids_not_to_backorder'):
|
||||
pickings_not_to_backorder = self.browse(self.env.context['picking_ids_not_to_backorder'])
|
||||
pickings_to_backorder = self - pickings_not_to_backorder
|
||||
else:
|
||||
pickings_not_to_backorder = self.env['stock.picking']
|
||||
pickings_to_backorder = self
|
||||
pickings_not_to_backorder.with_context(cancel_backorder=True)._action_done()
|
||||
pickings_to_backorder.with_context(cancel_backorder=False)._action_done()
|
||||
return True
|
||||
|
||||
if no_quantities_done:
|
||||
view = self.env.ref('stock.view_immediate_transfer')
|
||||
wiz = self.env['stock.immediate.transfer'].create({'pick_ids': [(4, self.id)]})
|
||||
return {
|
||||
'name': _('Immediate Transfer?'),
|
||||
'type': 'ir.actions.act_window',
|
||||
'view_mode': 'form',
|
||||
'res_model': 'stock.immediate.transfer',
|
||||
'views': [(view.id, 'form')],
|
||||
'view_id': view.id,
|
||||
'target': 'new',
|
||||
'res_id': wiz.id,
|
||||
'context': self.env.context,
|
||||
}
|
||||
def _pre_action_done_hook(self):
|
||||
if not self.env.context.get('skip_immediate'):
|
||||
pickings_to_immediate = self._check_immediate()
|
||||
if pickings_to_immediate:
|
||||
return pickings_to_immediate._action_generate_immediate_wizard()
|
||||
|
||||
# Check backorder should check for other barcodes
|
||||
if self._check_backorder():
|
||||
return self.action_generate_backorder_wizard()
|
||||
self._action_done()
|
||||
return
|
||||
if not self.env.context.get('skip_backorder'):
|
||||
pickings_to_backorder = self._check_backorder()
|
||||
if pickings_to_backorder:
|
||||
return pickings_to_backorder._action_generate_backorder_wizard()
|
||||
return True
|
||||
|
||||
def action_generate_backorder_wizard(self):
|
||||
def _action_generate_backorder_wizard(self):
|
||||
view = self.env.ref('stock.view_backorder_confirmation')
|
||||
wiz = self.env['stock.backorder.confirmation'].create({'pick_ids': [(4, p.id) for p in self]})
|
||||
return {
|
||||
@@ -856,42 +852,60 @@ class Picking(models.Model):
|
||||
'context': self.env.context,
|
||||
}
|
||||
|
||||
def _action_generate_immediate_wizard(self):
|
||||
view = self.env.ref('stock.view_immediate_transfer')
|
||||
wiz = self.env['stock.immediate.transfer'].create({'pick_ids': [(4, p.id) for p in self]})
|
||||
return {
|
||||
'name': _('Immediate Transfer?'),
|
||||
'type': 'ir.actions.act_window',
|
||||
'view_mode': 'form',
|
||||
'res_model': 'stock.immediate.transfer',
|
||||
'views': [(view.id, 'form')],
|
||||
'view_id': view.id,
|
||||
'target': 'new',
|
||||
'res_id': wiz.id,
|
||||
'context': self.env.context,
|
||||
}
|
||||
|
||||
def action_toggle_is_locked(self):
|
||||
self.ensure_one()
|
||||
self.is_locked = not self.is_locked
|
||||
return True
|
||||
|
||||
def _check_backorder(self):
|
||||
""" This method will loop over all the move lines of self and
|
||||
check if creating a backorder is necessary. This method is
|
||||
called during button_validate if the user has already processed
|
||||
some quantities and in the immediate transfer wizard that is
|
||||
displayed if the user has not processed any quantities.
|
||||
backorder_pickings = self.browse()
|
||||
for picking in self:
|
||||
quantity_todo = {}
|
||||
quantity_done = {}
|
||||
for move in picking.mapped('move_lines'):
|
||||
quantity_todo.setdefault(move.product_id.id, 0)
|
||||
quantity_done.setdefault(move.product_id.id, 0)
|
||||
quantity_todo[move.product_id.id] += move.product_uom_qty
|
||||
quantity_done[move.product_id.id] += move.quantity_done
|
||||
for ops in picking.mapped('move_line_ids').filtered(lambda x: x.package_id and not x.product_id and not x.move_id):
|
||||
for quant in ops.package_id.quant_ids:
|
||||
quantity_done.setdefault(quant.product_id.id, 0)
|
||||
quantity_done[quant.product_id.id] += quant.qty
|
||||
for pack in picking.mapped('move_line_ids').filtered(lambda x: x.product_id and not x.move_id):
|
||||
quantity_done.setdefault(pack.product_id.id, 0)
|
||||
quantity_done[pack.product_id.id] += pack.product_uom_id._compute_quantity(pack.qty_done, pack.product_id.uom_id)
|
||||
if any(quantity_done[x] < quantity_todo.get(x, 0) for x in quantity_done):
|
||||
backorder_pickings |= picking
|
||||
return backorder_pickings
|
||||
|
||||
:return: True if a backorder is necessary else False
|
||||
"""
|
||||
quantity_todo = {}
|
||||
quantity_done = {}
|
||||
for move in self.mapped('move_lines'):
|
||||
quantity_todo.setdefault(move.product_id.id, 0)
|
||||
quantity_done.setdefault(move.product_id.id, 0)
|
||||
quantity_todo[move.product_id.id] += move.product_uom_qty
|
||||
quantity_done[move.product_id.id] += move.quantity_done
|
||||
for ops in self.mapped('move_line_ids').filtered(lambda x: x.package_id and not x.product_id and not x.move_id):
|
||||
for quant in ops.package_id.quant_ids:
|
||||
quantity_done.setdefault(quant.product_id.id, 0)
|
||||
quantity_done[quant.product_id.id] += quant.qty
|
||||
for pack in self.mapped('move_line_ids').filtered(lambda x: x.product_id and not x.move_id):
|
||||
quantity_done.setdefault(pack.product_id.id, 0)
|
||||
quantity_done[pack.product_id.id] += pack.product_uom_id._compute_quantity(pack.qty_done, pack.product_id.uom_id)
|
||||
return any(quantity_done[x] < quantity_todo.get(x, 0) for x in quantity_done)
|
||||
def _check_immediate(self):
|
||||
immediate_pickings = self.browse()
|
||||
precision_digits = self.env['decimal.precision'].precision_get('Product Unit of Measure')
|
||||
for picking in self:
|
||||
if all(float_is_zero(move_line.qty_done, precision_digits=precision_digits) for move_line in picking.move_line_ids.filtered(lambda m: m.state not in ('done', 'cancel'))):
|
||||
immediate_pickings |= picking
|
||||
return immediate_pickings
|
||||
|
||||
def _autoconfirm_picking(self):
|
||||
for picking in self.filtered(lambda picking: picking.immediate_transfer and picking.state not in ('done', 'cancel') and (picking.move_lines or picking.package_level_ids)):
|
||||
picking.action_confirm()
|
||||
|
||||
def _create_backorder(self):
|
||||
|
||||
""" This method is called when the user chose to create a backorder. It will create a new
|
||||
picking, the backorder, and move the stock.moves that are not `done` or `cancel` into it.
|
||||
"""
|
||||
|
||||
@@ -1943,7 +1943,7 @@ class StockMove(SavepointCase):
|
||||
|
||||
# create the backorder in the uom of the quants
|
||||
backorder_wizard_dict = picking_stock_pack.button_validate()
|
||||
backorder_wizard = self.env[backorder_wizard_dict['res_model']].browse(backorder_wizard_dict['res_id'])
|
||||
backorder_wizard = self.env[backorder_wizard_dict['res_model']].browse(backorder_wizard_dict['res_id']).with_context(backorder_wizard_dict['context'])
|
||||
backorder_wizard.process()
|
||||
self.assertEqual(move_stock_pack.state, 'done')
|
||||
self.assertEqual(move_stock_pack.quantity_done, 0.5)
|
||||
@@ -2109,7 +2109,7 @@ class StockMove(SavepointCase):
|
||||
if ml.lot_id.name != 'lot3':
|
||||
ml.qty_done = 1
|
||||
res_dict_for_back_order = picking_pack_cust.button_validate()
|
||||
backorder_wizard = self.env[(res_dict_for_back_order.get('res_model'))].browse(res_dict_for_back_order.get('res_id'))
|
||||
backorder_wizard = self.env[(res_dict_for_back_order.get('res_model'))].browse(res_dict_for_back_order.get('res_id')).with_context(res_dict_for_back_order['context'])
|
||||
backorder_wizard.process()
|
||||
backorder = self.env['stock.picking'].search([('backorder_id', '=', picking_pack_cust.id)])
|
||||
backordered_move = backorder.move_lines
|
||||
@@ -3298,7 +3298,7 @@ class StockMove(SavepointCase):
|
||||
picking.action_assign()
|
||||
res_dict = picking.button_validate()
|
||||
self.assertEqual(res_dict.get('res_model'), 'stock.immediate.transfer')
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id'))
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id')).with_context(res_dict['context'])
|
||||
wizard.process()
|
||||
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product, self.stock_location), 10.0)
|
||||
|
||||
@@ -3331,10 +3331,10 @@ class StockMove(SavepointCase):
|
||||
# Only 5 products are reserved on the move of 10, click on `button_validate`.
|
||||
res_dict = picking.button_validate()
|
||||
self.assertEqual(res_dict.get('res_model'), 'stock.immediate.transfer')
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id'))
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id')).with_context(res_dict['context'])
|
||||
res_dict_for_back_order = wizard.process()
|
||||
self.assertEqual(res_dict_for_back_order.get('res_model'), 'stock.backorder.confirmation')
|
||||
backorder_wizard = self.env[(res_dict_for_back_order.get('res_model'))].browse(res_dict_for_back_order.get('res_id'))
|
||||
backorder_wizard = self.env[(res_dict_for_back_order.get('res_model'))].browse(res_dict_for_back_order.get('res_id')).with_context(res_dict_for_back_order['context'])
|
||||
# Chose to create a backorder.
|
||||
backorder_wizard.process()
|
||||
|
||||
@@ -3397,11 +3397,11 @@ class StockMove(SavepointCase):
|
||||
|
||||
action = picking.button_validate()
|
||||
self.assertEqual(action.get('res_model'), 'stock.immediate.transfer')
|
||||
wizard = self.env[(action.get('res_model'))].browse(action.get('res_id'))
|
||||
wizard = self.env[(action.get('res_model'))].browse(action.get('res_id')).with_context(action.get('context'))
|
||||
action = wizard.process()
|
||||
self.assertTrue(isinstance(action, dict), 'Should open backorder wizard')
|
||||
self.assertEqual(action.get('res_model'), 'stock.backorder.confirmation')
|
||||
wizard = self.env[(action.get('res_model'))].browse(action.get('res_id'))
|
||||
wizard = self.env[(action.get('res_model'))].browse(action.get('res_id')).with_context(action.get('context'))
|
||||
wizard.process()
|
||||
backorder = self.env['stock.picking'].search([('backorder_id', '=', picking.id)])
|
||||
self.assertEqual(len(backorder), 1.0)
|
||||
@@ -3445,7 +3445,7 @@ class StockMove(SavepointCase):
|
||||
# No quantites filled, immediate transfer wizard should pop up.
|
||||
immediate_trans_wiz_dict = picking.button_validate()
|
||||
self.assertEqual(immediate_trans_wiz_dict.get('res_model'), 'stock.immediate.transfer')
|
||||
immediate_trans_wiz = self.env[immediate_trans_wiz_dict['res_model']].browse(immediate_trans_wiz_dict['res_id'])
|
||||
immediate_trans_wiz = self.env[immediate_trans_wiz_dict['res_model']].browse(immediate_trans_wiz_dict['res_id']).with_context(immediate_trans_wiz_dict['context'])
|
||||
immediate_trans_wiz.process()
|
||||
|
||||
self.assertEqual(picking.move_lines.quantity_done, 5.0)
|
||||
|
||||
@@ -641,7 +641,7 @@ class TestPickShip(TestStockCommon):
|
||||
self.env['stock.quant']._update_available_quantity(self.productA, location, 10.0)
|
||||
picking_pick.move_lines.quantity_done = 5.0
|
||||
backorder_wizard_values = picking_pick.button_validate()
|
||||
backorder_wizard = self.env[(backorder_wizard_values.get('res_model'))].browse(backorder_wizard_values.get('res_id'))
|
||||
backorder_wizard = self.env[(backorder_wizard_values.get('res_model'))].browse(backorder_wizard_values.get('res_id')).with_context(backorder_wizard_values['context'])
|
||||
backorder_wizard.process()
|
||||
|
||||
self.assertTrue(picking_client.move_line_ids, 'A move line should be created.')
|
||||
@@ -896,7 +896,8 @@ class TestSinglePicking(TestStockCommon):
|
||||
|
||||
# Process only one product without creating a backorder
|
||||
delivery_order.move_lines[0].move_line_ids[0].qty_done = 2
|
||||
backorder_wizard = self.env['stock.backorder.confirmation'].create({'pick_ids': [(4, delivery_order.id)]})
|
||||
res_dict = delivery_order.button_validate()
|
||||
backorder_wizard = self.env['stock.backorder.confirmation'].browse(res_dict['res_id']).with_context(res_dict['context'])
|
||||
backorder_wizard.process_cancel_backorder()
|
||||
|
||||
# No backorder should be created and the move corresponding to the missing product should be cancelled
|
||||
@@ -1851,7 +1852,7 @@ class TestSinglePicking(TestStockCommon):
|
||||
receipt.owner_id = owner1
|
||||
receipt = receipt.save()
|
||||
wiz = receipt.button_validate()
|
||||
self.env['stock.immediate.transfer'].browse(wiz['res_id']).process()
|
||||
self.env['stock.immediate.transfer'].browse(wiz['res_id']).with_context(wiz['context']).process()
|
||||
|
||||
supplier_location = self.env['stock.location'].browse(self.supplier_location)
|
||||
stock_location = self.env['stock.location'].browse(self.stock_location)
|
||||
|
||||
@@ -509,7 +509,7 @@ class TestStockFlow(TestStockCommon):
|
||||
PackSdozAround = self.StockPackObj.search([('product_id', '=', self.SDozARound.id), ('picking_id', '=', picking_in_A.id)], limit=1)
|
||||
self.assertEqual(PackSdozAround.product_qty, 11, 'Wrong quantity in pack operation (%s found instead of 11)' % (PackSdozAround.product_qty))
|
||||
res_dict = picking_in_A.button_validate()
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id'))
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id')).with_context(res_dict['context'])
|
||||
wizard.process()
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
@@ -651,9 +651,9 @@ class TestStockFlow(TestStockCommon):
|
||||
# -----------------
|
||||
|
||||
res_dict = picking_in_B.button_validate()
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id'))
|
||||
wizard = self.env[res_dict.get('res_model')].browse(res_dict.get('res_id')).with_context(res_dict['context'])
|
||||
res_dict_for_back_order = wizard.process()
|
||||
backorder_wizard = self.env[(res_dict_for_back_order.get('res_model'))].browse(res_dict_for_back_order.get('res_id'))
|
||||
backorder_wizard = self.env[(res_dict_for_back_order.get('res_model'))].browse(res_dict_for_back_order.get('res_id')).with_context(res_dict_for_back_order['context'])
|
||||
backorder_wizard.process()
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
@@ -761,7 +761,7 @@ class TestStockFlow(TestStockCommon):
|
||||
picking_out.action_confirm()
|
||||
picking_out.action_assign()
|
||||
res_dict = picking_out.button_validate()
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id'))
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id')).with_context(res_dict['context'])
|
||||
wizard.process()
|
||||
|
||||
# Check quantity difference after stock transfer.
|
||||
@@ -848,7 +848,7 @@ class TestStockFlow(TestStockCommon):
|
||||
self.assertEqual(kgB_qty, 0.020, 'Wrong move quantity availability (%s found instead of 0.020)' % (kgB_qty))
|
||||
|
||||
res_dict = picking_out.button_validate()
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id'))
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id')).with_context(res_dict['context'])
|
||||
wizard.process()
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
@@ -886,7 +886,7 @@ class TestStockFlow(TestStockCommon):
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
res_dict = bo_in_B.button_validate()
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id'))
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id')).with_context(res_dict['context'])
|
||||
wizard.process()
|
||||
# Check quants and available quantity for product kgB.
|
||||
quants = self.StockQuantObj.search([('product_id', '=', self.DozA.id), ('location_id', '=', self.stock_location)])
|
||||
@@ -928,7 +928,7 @@ class TestStockFlow(TestStockCommon):
|
||||
self.assertEqual(packKG.product_uom_id.id, self.uom_tone.id, 'Wrong product uom in pack operation.')
|
||||
# Transfer Incoming shipment.
|
||||
res_dict = picking_in.button_validate()
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id'))
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id')).with_context(res_dict['context'])
|
||||
wizard.process()
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
@@ -964,9 +964,9 @@ class TestStockFlow(TestStockCommon):
|
||||
pack_opt = self.StockPackObj.search([('product_id', '=', productKG.id), ('picking_id', '=', picking_out.id)], limit=1)
|
||||
pack_opt.write({'product_uom_qty': 0.5})
|
||||
res_dict = picking_out.button_validate()
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id'))
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id')).with_context(res_dict['context'])
|
||||
res_dict_for_back_order = wizard.process()
|
||||
backorder_wizard = self.env[(res_dict_for_back_order.get('res_model'))].browse(res_dict_for_back_order.get('res_id'))
|
||||
backorder_wizard = self.env[(res_dict_for_back_order.get('res_model'))].browse(res_dict_for_back_order.get('res_id')).with_context(res_dict_for_back_order['context'])
|
||||
backorder_wizard.process()
|
||||
quants = self.StockQuantObj.search([('product_id', '=', productKG.id), ('location_id', '=', self.stock_location)])
|
||||
total_qty = [quant.quantity for quant in quants]
|
||||
@@ -988,9 +988,9 @@ class TestStockFlow(TestStockCommon):
|
||||
pack_opt = self.StockPackObj.search([('product_id', '=', productKG.id), ('picking_id', '=', bo_out_1.id)], limit=1)
|
||||
pack_opt.write({'product_uom_qty': 0.5})
|
||||
res_dict = bo_out_1.button_validate()
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id'))
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id')).with_context(res_dict['context'])
|
||||
res_dict_for_back_order = wizard.process()
|
||||
backorder_wizard = self.env[(res_dict_for_back_order.get('res_model'))].browse(res_dict_for_back_order.get('res_id'))
|
||||
backorder_wizard = self.env[(res_dict_for_back_order.get('res_model'))].browse(res_dict_for_back_order.get('res_id')).with_context(res_dict_for_back_order['context'])
|
||||
backorder_wizard.process()
|
||||
quants = self.StockQuantObj.search([('product_id', '=', productKG.id), ('location_id', '=', self.stock_location)])
|
||||
total_qty = [quant.quantity for quant in quants]
|
||||
@@ -1012,9 +1012,9 @@ class TestStockFlow(TestStockCommon):
|
||||
pack_opt = self.StockPackObj.search([('product_id', '=', productKG.id), ('picking_id', '=', bo_out_2.id)], limit=1)
|
||||
pack_opt.write({'product_uom_qty': 0.5})
|
||||
res_dict = bo_out_2.button_validate()
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id'))
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id')).with_context(res_dict['context'])
|
||||
res_dict_for_back_order = wizard.process()
|
||||
backorder_wizard = self.env[(res_dict_for_back_order.get('res_model'))].browse(res_dict_for_back_order.get('res_id'))
|
||||
backorder_wizard = self.env[(res_dict_for_back_order.get('res_model'))].browse(res_dict_for_back_order.get('res_id')).with_context(res_dict_for_back_order['context'])
|
||||
backorder_wizard.process()
|
||||
# Check total quantity stock location of product KG.
|
||||
quants = self.StockQuantObj.search([('product_id', '=', productKG.id), ('location_id', '=', self.stock_location)])
|
||||
@@ -1035,9 +1035,9 @@ class TestStockFlow(TestStockCommon):
|
||||
pack_opt = self.StockPackObj.search([('product_id', '=', productKG.id), ('picking_id', '=', bo_out_3.id)], limit=1)
|
||||
pack_opt.write({'product_uom_qty': 0.5})
|
||||
res_dict = bo_out_3.button_validate()
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id'))
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id')).with_context(res_dict['context'])
|
||||
res_dict_for_back_order = wizard.process()
|
||||
backorder_wizard = self.env[(res_dict_for_back_order.get('res_model'))].browse(res_dict_for_back_order.get('res_id'))
|
||||
backorder_wizard = self.env[(res_dict_for_back_order.get('res_model'))].browse(res_dict_for_back_order.get('res_id')).with_context(res_dict_for_back_order['context'])
|
||||
backorder_wizard.process()
|
||||
quants = self.StockQuantObj.search([('product_id', '=', productKG.id), ('location_id', '=', self.stock_location)])
|
||||
total_qty = [quant.quantity for quant in quants]
|
||||
@@ -1058,7 +1058,7 @@ class TestStockFlow(TestStockCommon):
|
||||
pack_opt = self.StockPackObj.search([('product_id', '=', productKG.id), ('picking_id', '=', bo_out_4.id)], limit=1)
|
||||
pack_opt.write({'product_uom_qty': 0.5})
|
||||
res_dict = bo_out_4.button_validate()
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id'))
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id')).with_context(res_dict['context'])
|
||||
wizard.process()
|
||||
quants = self.StockQuantObj.search([('product_id', '=', productKG.id), ('location_id', '=', self.stock_location)])
|
||||
total_qty = [quant.quantity for quant in quants]
|
||||
@@ -1762,7 +1762,8 @@ class TestStockFlow(TestStockCommon):
|
||||
|
||||
# Only 4 items are processed
|
||||
move_a.move_line_ids.qty_done = 4
|
||||
backorder_wizard = self.env['stock.backorder.confirmation'].create({'pick_ids': [(4, picking.id)]})
|
||||
res_dict = picking.button_validate()
|
||||
backorder_wizard = self.env['stock.backorder.confirmation'].browse(res_dict['res_id']).with_context(res_dict['context'])
|
||||
backorder_wizard.process_cancel_backorder()
|
||||
|
||||
# Checking that no backorders were attached to the picking
|
||||
|
||||
@@ -462,6 +462,19 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_validate_picking" model="ir.actions.server">
|
||||
<field name="name">Validate</field>
|
||||
<field name="model_id" ref="stock.model_stock_picking"/>
|
||||
<field name="binding_model_id" ref="stock.model_stock_picking"/>
|
||||
<field name="binding_view_types">list</field>
|
||||
<field name="state">code</field>
|
||||
<field name="code">
|
||||
if records:
|
||||
res = records.button_validate()
|
||||
action = res
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="all_picking" name="Transfers" parent="menu_stock_warehouse_mgmt" sequence="5" action="action_picking_tree_all" groups="stock.group_stock_manager,stock.group_stock_user"/>
|
||||
|
||||
<record id="stock_picking_action_picking_type" model="ir.actions.act_window">
|
||||
|
||||
@@ -22,10 +22,18 @@ class StockBackorderConfirmation(models.TransientModel):
|
||||
precision_rounding=move.product_uom.rounding) > 0:
|
||||
moves_to_log[move] = (move.quantity_done, move.product_uom_qty)
|
||||
pick_id._log_less_quantities_than_expected(moves_to_log)
|
||||
confirmation.pick_ids.with_context(cancel_backorder=cancel_backorder)._action_done()
|
||||
|
||||
pickings_to_validate = self.env.context.get('button_validate_picking_ids')
|
||||
if pickings_to_validate:
|
||||
pickings_to_validate = self.env['stock.picking'].browse(pickings_to_validate).with_context(skip_backorder=True)
|
||||
if cancel_backorder:
|
||||
pickings_to_validate = pickings_to_validate.with_context(picking_ids_not_to_backorder=self.pick_ids.ids)
|
||||
return pickings_to_validate.button_validate()
|
||||
return True
|
||||
|
||||
|
||||
def process(self):
|
||||
self._process()
|
||||
return self._process()
|
||||
|
||||
def process_cancel_backorder(self):
|
||||
self._process(cancel_backorder=True)
|
||||
return self._process(cancel_backorder=True)
|
||||
|
||||
@@ -12,8 +12,6 @@ class StockImmediateTransfer(models.TransientModel):
|
||||
pick_ids = fields.Many2many('stock.picking', 'stock_picking_transfer_rel')
|
||||
|
||||
def process(self):
|
||||
pick_to_backorder = self.env['stock.picking']
|
||||
pick_to_do = self.env['stock.picking']
|
||||
for picking in self.pick_ids:
|
||||
# If still in draft => confirm and assign
|
||||
if picking.state == 'draft':
|
||||
@@ -25,13 +23,18 @@ class StockImmediateTransfer(models.TransientModel):
|
||||
for move in picking.move_lines.filtered(lambda m: m.state not in ['done', 'cancel']):
|
||||
for move_line in move.move_line_ids:
|
||||
move_line.qty_done = move_line.product_uom_qty
|
||||
if picking._check_backorder():
|
||||
pick_to_backorder |= picking
|
||||
continue
|
||||
pick_to_do |= picking
|
||||
# Process every picking that do not require a backorder, then return a single backorder wizard for every other ones.
|
||||
if pick_to_do:
|
||||
pick_to_do._action_done()
|
||||
if pick_to_backorder:
|
||||
return pick_to_backorder.action_generate_backorder_wizard()
|
||||
return False
|
||||
|
||||
pickings_to_validate = self.env.context.get('button_validate_picking_ids')
|
||||
if pickings_to_validate:
|
||||
return self.env['stock.picking'].browse(pickings_to_validate).with_context(skip_immediate=True).button_validate()
|
||||
return True
|
||||
|
||||
def process_no_immediate(self):
|
||||
# Remove `self.pick_ids` from `button_validate_picking_ids` and call `button_validate` with
|
||||
# the subset (if any).
|
||||
pickings_to_validate = self.env['stock.picking'].browse(self.env.context.get('button_validate_picking_ids'))
|
||||
pickings_to_validate = pickings_to_validate - self.pick_ids
|
||||
if pickings_to_validate:
|
||||
return pickings_to_validate.with_context(skip_immediate=True).button_validate()
|
||||
return True
|
||||
|
||||
|
||||
@@ -12,10 +12,11 @@
|
||||
</p>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="process" string="_Apply" type="object" class="btn-primary"/>
|
||||
<button name="process" string="Apply" type="object" class="btn-primary"/>
|
||||
<button name="process_no_immediate" string="Skip" class="btn-primary" type="object" />
|
||||
<button string="Cancel" class="btn-secondary" special="cancel" />
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
</odoo>
|
||||
|
||||
@@ -61,7 +61,7 @@ class TestStockValuation(AccountingTestCase):
|
||||
self.assertEqual(len(self.sale_order1.picking_ids), 1)
|
||||
#self.assertEqual(self.sale_order1.picking_ids.move_lines._is_dropshipped(), True)
|
||||
wizard = self.sale_order1.picking_ids.button_validate()
|
||||
immediate_transfer = self.env[wizard['res_model']].browse(wizard['res_id'])
|
||||
immediate_transfer = self.env[wizard['res_model']].browse(wizard['res_id']).with_context(wizard['context'])
|
||||
immediate_transfer.process()
|
||||
self.assertEqual(self.sale_order1.picking_ids.state, 'done')
|
||||
|
||||
|
||||
@@ -234,7 +234,7 @@ class TestLandedCosts(TestStockLandedCostsCommon):
|
||||
self.picking_in.action_confirm()
|
||||
# Transfer incoming shipment
|
||||
res_dict = self.picking_in.button_validate()
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id'))
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id')).with_context(res_dict.get('context'))
|
||||
wizard.process()
|
||||
return self.picking_in
|
||||
|
||||
@@ -247,7 +247,7 @@ class TestLandedCosts(TestStockLandedCostsCommon):
|
||||
# Transfer picking.
|
||||
|
||||
res_dict = self.picking_out.button_validate()
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id'))
|
||||
wizard = self.env[(res_dict.get('res_model'))].browse(res_dict.get('res_id')).with_context(res_dict['context'])
|
||||
wizard.process()
|
||||
|
||||
def _create_landed_costs(self, value, picking_in):
|
||||
|
||||
@@ -253,7 +253,7 @@ class TestStockValuationLCFIFOVB(TestStockValuationLC):
|
||||
# Process the receipt
|
||||
receipt = rfq.picking_ids
|
||||
wiz = receipt.button_validate()
|
||||
wiz = self.env['stock.immediate.transfer'].browse(wiz['res_id']).process()
|
||||
wiz = self.env['stock.immediate.transfer'].browse(wiz['res_id']).with_context(wiz['context']).process()
|
||||
self.assertEqual(rfq.order_line.qty_received, 10)
|
||||
|
||||
input_aml = self._get_stock_input_move_lines()[-1]
|
||||
@@ -341,7 +341,7 @@ class TestStockValuationLCFIFOVB(TestStockValuationLC):
|
||||
# Process the receipt
|
||||
receipt = rfq.picking_ids
|
||||
wiz = receipt.button_validate()
|
||||
wiz = self.env['stock.immediate.transfer'].browse(wiz['res_id']).process()
|
||||
wiz = self.env['stock.immediate.transfer'].browse(wiz['res_id']).with_context(wiz['context']).process()
|
||||
self.assertEqual(rfq.order_line.qty_received, 10)
|
||||
|
||||
input_aml = self._get_stock_input_move_lines()[-1]
|
||||
|
||||
@@ -67,43 +67,8 @@ class StockPickingBatch(models.Model):
|
||||
picking.batch_id.id,
|
||||
picking.batch_id.name))
|
||||
|
||||
picking_to_backorder = self.env['stock.picking']
|
||||
picking_without_qty_done = self.env['stock.picking']
|
||||
for picking in pickings:
|
||||
if all([x.qty_done == 0.0 for x in picking.move_line_ids]):
|
||||
# If no lots when needed, raise error
|
||||
picking_type = picking.picking_type_id
|
||||
if (picking_type.use_create_lots or picking_type.use_existing_lots):
|
||||
for ml in picking.move_line_ids:
|
||||
if ml.product_id.tracking != 'none':
|
||||
raise UserError(_('Some products require lots/serial numbers.'))
|
||||
# Check if we need to set some qty done.
|
||||
picking_without_qty_done |= picking
|
||||
elif picking._check_backorder():
|
||||
picking_to_backorder |= picking
|
||||
else:
|
||||
picking._action_done()
|
||||
self.write({'state': 'done'})
|
||||
if picking_without_qty_done:
|
||||
view = self.env.ref('stock.view_immediate_transfer')
|
||||
wiz = self.env['stock.immediate.transfer'].create({
|
||||
'pick_ids': [(4, p.id) for p in picking_without_qty_done],
|
||||
'pick_to_backorder_ids': [(4, p.id) for p in picking_to_backorder],
|
||||
})
|
||||
return {
|
||||
'name': _('Immediate Transfer?'),
|
||||
'type': 'ir.actions.act_window',
|
||||
'view_mode': 'form',
|
||||
'res_model': 'stock.immediate.transfer',
|
||||
'views': [(view.id, 'form')],
|
||||
'view_id': view.id,
|
||||
'target': 'new',
|
||||
'res_id': wiz.id,
|
||||
'context': self.env.context,
|
||||
}
|
||||
if picking_to_backorder:
|
||||
return picking_to_backorder.action_generate_backorder_wizard()
|
||||
return True
|
||||
return self.picking_ids.button_validate()
|
||||
|
||||
def _track_subtype(self, init_values):
|
||||
if 'state' in init_values:
|
||||
|
||||
@@ -102,7 +102,7 @@ class TestBatchPicking(TransactionCase):
|
||||
# There should be a wizard asking to process picking without quantity done
|
||||
immediate_transfer_wizard_dict = self.batch.done()
|
||||
self.assertTrue(immediate_transfer_wizard_dict)
|
||||
immediate_transfer_wizard = self.env[(immediate_transfer_wizard_dict.get('res_model'))].browse(immediate_transfer_wizard_dict.get('res_id'))
|
||||
immediate_transfer_wizard = self.env[(immediate_transfer_wizard_dict.get('res_model'))].browse(immediate_transfer_wizard_dict.get('res_id')).with_context(immediate_transfer_wizard_dict['context'])
|
||||
self.assertEqual(len(immediate_transfer_wizard.pick_ids), 2)
|
||||
immediate_transfer_wizard.process()
|
||||
|
||||
@@ -135,11 +135,11 @@ class TestBatchPicking(TransactionCase):
|
||||
# There should be a wizard asking to process picking without quantity done
|
||||
back_order_wizard_dict = self.batch.done()
|
||||
self.assertTrue(back_order_wizard_dict)
|
||||
back_order_wizard = self.env[(back_order_wizard_dict.get('res_model'))].browse(back_order_wizard_dict.get('res_id'))
|
||||
back_order_wizard = self.env[(back_order_wizard_dict.get('res_model'))].browse(back_order_wizard_dict.get('res_id')).with_context(back_order_wizard_dict['context'])
|
||||
self.assertEqual(len(back_order_wizard.pick_ids), 1)
|
||||
self.assertEqual(self.picking_client_2.state, 'done', 'Picking 2 should be done')
|
||||
back_order_wizard.process()
|
||||
|
||||
self.assertEqual(self.picking_client_2.state, 'done', 'Picking 2 should be done')
|
||||
self.assertEqual(self.picking_client_1.state, 'done', 'Picking 1 should be done')
|
||||
self.assertEqual(self.picking_client_1.move_lines.product_uom_qty, 5, 'initial demand should be 5 after picking split')
|
||||
self.assertTrue(self.env['stock.picking'].search([('backorder_id', '=', self.picking_client_1.id)]), 'no back order created')
|
||||
@@ -168,11 +168,11 @@ class TestBatchPicking(TransactionCase):
|
||||
# There should be a wizard asking to process picking without quantity done
|
||||
immediate_transfer_wizard_dict = self.batch.done()
|
||||
self.assertTrue(immediate_transfer_wizard_dict)
|
||||
immediate_transfer_wizard = self.env[(immediate_transfer_wizard_dict.get('res_model'))].browse(immediate_transfer_wizard_dict.get('res_id'))
|
||||
immediate_transfer_wizard = self.env[(immediate_transfer_wizard_dict.get('res_model'))].browse(immediate_transfer_wizard_dict.get('res_id')).with_context(immediate_transfer_wizard_dict['context'])
|
||||
self.assertEqual(len(immediate_transfer_wizard.pick_ids), 2)
|
||||
back_order_wizard_dict = immediate_transfer_wizard.process()
|
||||
self.assertTrue(back_order_wizard_dict)
|
||||
back_order_wizard = self.env[(back_order_wizard_dict.get('res_model'))].browse(back_order_wizard_dict.get('res_id'))
|
||||
back_order_wizard = self.env[(back_order_wizard_dict.get('res_model'))].browse(back_order_wizard_dict.get('res_id')).with_context(back_order_wizard_dict['context'])
|
||||
self.assertEqual(len(back_order_wizard.pick_ids), 1)
|
||||
back_order_wizard.process()
|
||||
|
||||
@@ -205,11 +205,11 @@ class TestBatchPicking(TransactionCase):
|
||||
# There should be a wizard asking to process picking without quantity done
|
||||
immediate_transfer_wizard_dict = self.batch.done()
|
||||
self.assertTrue(immediate_transfer_wizard_dict)
|
||||
immediate_transfer_wizard = self.env[(immediate_transfer_wizard_dict.get('res_model'))].browse(immediate_transfer_wizard_dict.get('res_id'))
|
||||
immediate_transfer_wizard = self.env[(immediate_transfer_wizard_dict.get('res_model'))].browse(immediate_transfer_wizard_dict.get('res_id')).with_context(immediate_transfer_wizard_dict['context'])
|
||||
self.assertEqual(len(immediate_transfer_wizard.pick_ids), 1)
|
||||
back_order_wizard_dict = immediate_transfer_wizard.process()
|
||||
self.assertTrue(back_order_wizard_dict)
|
||||
back_order_wizard = self.env[(back_order_wizard_dict.get('res_model'))].browse(back_order_wizard_dict.get('res_id'))
|
||||
back_order_wizard = self.env[(back_order_wizard_dict.get('res_model'))].browse(back_order_wizard_dict.get('res_id')).with_context(back_order_wizard_dict['context'])
|
||||
self.assertEqual(len(back_order_wizard.pick_ids), 1)
|
||||
back_order_wizard.process()
|
||||
|
||||
|
||||
@@ -2,4 +2,3 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import stock_picking_to_batch
|
||||
from . import stock_immediate_transfer
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
from odoo import models, fields, api
|
||||
|
||||
|
||||
class StockImmediateTransfer(models.TransientModel):
|
||||
_inherit = 'stock.immediate.transfer'
|
||||
_description = 'Immediate Transfer'
|
||||
|
||||
pick_to_backorder_ids = fields.Many2many('stock.picking', help='Picking to backorder')
|
||||
|
||||
def process(self):
|
||||
backorder_wizard_dict = super(StockImmediateTransfer, self).process()
|
||||
# If the immediate transfer wizard process all our picking but with some back order maybe needed we want to add the backorder already passed to the wizard.
|
||||
if backorder_wizard_dict:
|
||||
backorder_wizard = self.env['stock.backorder.confirmation'].browse(backorder_wizard_dict.get('res_id', False))
|
||||
backorder_wizard.write({'pick_ids': [(4, p.id) for p in self.pick_to_backorder_ids]})
|
||||
return backorder_wizard_dict
|
||||
# If there is no backorder returned by the immediate transfer basic function we still wanted to process those manually given
|
||||
elif self.pick_to_backorder_ids:
|
||||
return self.pick_to_backorder_ids.action_generate_backorder_wizard()
|
||||
return False
|
||||
@@ -9,34 +9,47 @@ import threading
|
||||
class Picking(models.Model):
|
||||
_inherit = 'stock.picking'
|
||||
|
||||
def _pre_action_done_hook(self):
|
||||
res = super()._pre_action_done_hook()
|
||||
if res is True:
|
||||
pickings_to_warn_sms = self._check_warn_sms()
|
||||
if pickings_to_warn_sms:
|
||||
return pickings_to_warn_sms._action_generate_warn_sms_wizard()
|
||||
return res
|
||||
|
||||
def _check_warn_sms(self):
|
||||
warn_sms_pickings = self.browse()
|
||||
for picking in self:
|
||||
is_delivery = picking.company_id.stock_move_sms_validation \
|
||||
and picking.picking_type_id.code == 'outgoing' \
|
||||
and (picking.partner_id.mobile or picking.partner_id.phone)
|
||||
if is_delivery and not getattr(threading.currentThread(), 'testing', False) \
|
||||
and not self.env.registry.in_test_mode() \
|
||||
and not picking.company_id.has_received_warning_stock_sms \
|
||||
and picking.company_id.stock_move_sms_validation:
|
||||
warn_sms_pickings |= picking
|
||||
return warn_sms_pickings
|
||||
|
||||
def _action_generate_warn_sms_wizard(self):
|
||||
view = self.env.ref('stock_sms.view_confirm_stock_sms')
|
||||
wiz = self.env['confirm.stock.sms'].create({'pick_ids': [(4, p.id) for p in self]})
|
||||
return {
|
||||
'name': _('SMS'),
|
||||
'type': 'ir.actions.act_window',
|
||||
'view_mode': 'form',
|
||||
'res_model': 'confirm.stock.sms',
|
||||
'views': [(view.id, 'form')],
|
||||
'view_id': view.id,
|
||||
'target': 'new',
|
||||
'res_id': wiz.id,
|
||||
'context': self.env.context,
|
||||
}
|
||||
|
||||
def _sms_get_number_fields(self):
|
||||
""" This method returns the fields to use to find the number to use to
|
||||
send an SMS on a record. """
|
||||
return ['mobile', 'phone']
|
||||
|
||||
def _check_sms_confirmation_popup(self):
|
||||
is_delivery = self.company_id.stock_move_sms_validation \
|
||||
and self.picking_type_id.code == 'outgoing' \
|
||||
and (self.partner_id.mobile or self.partner_id.phone)
|
||||
if is_delivery and not getattr(threading.currentThread(), 'testing', False) \
|
||||
and not self.env.registry.in_test_mode() \
|
||||
and not self.company_id.has_received_warning_stock_sms \
|
||||
and self.company_id.stock_move_sms_validation:
|
||||
view = self.env.ref('stock_sms.view_confirm_stock_sms')
|
||||
wiz = self.env['confirm.stock.sms'].create({'picking_id': self.id})
|
||||
return {
|
||||
'name': _('SMS'),
|
||||
'type': 'ir.actions.act_window',
|
||||
'view_mode': 'form',
|
||||
'res_model': 'confirm.stock.sms',
|
||||
'views': [(view.id, 'form')],
|
||||
'view_id': view.id,
|
||||
'target': 'new',
|
||||
'res_id': wiz.id,
|
||||
'context': self.env.context,
|
||||
}
|
||||
return False
|
||||
|
||||
def _send_confirmation_email(self):
|
||||
super(Picking, self)._send_confirmation_email()
|
||||
if not getattr(threading.currentThread(), 'testing', False) and not self.env.registry.in_test_mode():
|
||||
|
||||
@@ -8,20 +8,24 @@ class ConfirmStockSms(models.TransientModel):
|
||||
_name = 'confirm.stock.sms'
|
||||
_description = 'Confirm Stock SMS'
|
||||
|
||||
picking_id = fields.Many2one('stock.picking', required=True)
|
||||
company_id = fields.Many2one('res.company', string='Company', required=True, related='picking_id.company_id')
|
||||
pick_ids = fields.Many2many('stock.picking', 'stock_picking_sms_rel')
|
||||
|
||||
def send_sms(self):
|
||||
self.ensure_one()
|
||||
if not self.company_id.has_received_warning_stock_sms:
|
||||
self.company_id.sudo().write({'has_received_warning_stock_sms': True})
|
||||
return self.picking_id.button_validate()
|
||||
for company in self.pick_ids.company_id:
|
||||
if not company.has_received_warning_stock_sms:
|
||||
company.sudo().write({'has_received_warning_stock_sms': True})
|
||||
pickings_to_validate = self.env['stock.picking'].browse(self.env.context.get('button_validate_picking_ids'))
|
||||
return pickings_to_validate.button_validate()
|
||||
|
||||
def dont_send_sms(self):
|
||||
self.ensure_one()
|
||||
if not self.company_id.has_received_warning_stock_sms:
|
||||
self.company_id.sudo().write({
|
||||
'has_received_warning_stock_sms': True,
|
||||
'stock_move_sms_validation': False,
|
||||
})
|
||||
return self.picking_id.button_validate()
|
||||
for company in self.pick_ids.company_id:
|
||||
if not company.has_received_warning_stock_sms:
|
||||
company.sudo().write({
|
||||
'has_received_warning_stock_sms': True,
|
||||
'stock_move_sms_validation': False,
|
||||
})
|
||||
pickings_to_validate = self.env['stock.picking'].browse(self.env.context.get('button_validate_picking_ids'))
|
||||
return pickings_to_validate.button_validate()
|
||||
|
||||
|
||||
@@ -7,10 +7,6 @@
|
||||
<form string="SMS">
|
||||
You are about to confirm this Delivery Order by SMS Text Message.<br/>
|
||||
This feature can easily be disabled from the Settings of Inventory or by clicking on "Disable SMS".<br/>
|
||||
<group invisible="1">
|
||||
<field name="picking_id" invisible="1"/>
|
||||
<field name="company_id" invisible="1"/>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="send_sms" type="object"
|
||||
string="Confirm" class="oe_highlight"/>
|
||||
|
||||
Reference in New Issue
Block a user