@@ -409,6 +409,99 @@ def test_sync_picking_lot(self):
409409 po_picking_id .mapped ("move_ids.move_line_ids.lot_id.name" ),
410410 )
411411
412+ def test_sync_picking_lot_with_transit_location (self ):
413+ """
414+ Test that the lot is synchronized on the moves
415+ when using inter-company transit locations
416+ company B: Sale picking from Stock to Transit Location
417+ company A: Purchase picking from Transit Location to Stock
418+ """
419+ self .company_a .sync_picking = True
420+ self .company_b .sync_picking = True
421+ # Set inter-company locations on partners
422+ interco_location = self .env .ref ("stock.stock_location_inter_company" )
423+ self .partner_company_b .with_company (self .company_a ).write (
424+ {
425+ "property_stock_customer" : interco_location .id ,
426+ "property_stock_supplier" : interco_location .id ,
427+ }
428+ )
429+ self .partner_company_a .with_company (self .company_b ).write (
430+ {
431+ "property_stock_customer" : interco_location .id ,
432+ "property_stock_supplier" : interco_location .id ,
433+ }
434+ )
435+
436+ purchase = self ._create_purchase_order (
437+ self .partner_company_b , self .stockable_product_serial
438+ )
439+ sale = self ._approve_po (purchase )
440+
441+ # validate the SO picking
442+ po_picking_id = purchase .picking_ids
443+ so_picking_id = sale .picking_ids
444+
445+ so_move = so_picking_id .move_ids
446+ so_move .move_line_ids = [
447+ Command .clear (),
448+ Command .create (
449+ {
450+ "location_id" : so_move .location_id .id ,
451+ "location_dest_id" : so_move .location_dest_id .id ,
452+ "product_id" : self .stockable_product_serial .id ,
453+ "product_uom_id" : self .stockable_product_serial .uom_id .id ,
454+ "quantity" : 1 ,
455+ "lot_id" : self .serial_1 .id ,
456+ "picking_id" : so_picking_id .id ,
457+ },
458+ ),
459+ Command .create (
460+ {
461+ "location_id" : so_move .location_id .id ,
462+ "location_dest_id" : so_move .location_dest_id .id ,
463+ "product_id" : self .stockable_product_serial .id ,
464+ "product_uom_id" : self .stockable_product_serial .uom_id .id ,
465+ "quantity" : 1 ,
466+ "lot_id" : self .serial_2 .id ,
467+ "picking_id" : so_picking_id .id ,
468+ },
469+ ),
470+ Command .create (
471+ {
472+ "location_id" : so_move .location_id .id ,
473+ "location_dest_id" : so_move .location_dest_id .id ,
474+ "product_id" : self .stockable_product_serial .id ,
475+ "product_uom_id" : self .stockable_product_serial .uom_id .id ,
476+ "quantity" : 1 ,
477+ "lot_id" : self .serial_3 .id ,
478+ "picking_id" : so_picking_id .id ,
479+ },
480+ ),
481+ ]
482+ so_picking_id .button_validate ()
483+ self .assertEqual (so_picking_id .location_id .usage , "internal" )
484+ self .assertEqual (so_picking_id .location_dest_id .usage , "transit" )
485+ self .assertEqual (po_picking_id .location_id .usage , "transit" )
486+ self .assertEqual (po_picking_id .location_dest_id .usage , "internal" )
487+
488+ so_lots = so_move .mapped ("move_line_ids.lot_id" )
489+ po_lots = po_picking_id .mapped ("move_ids.move_line_ids.lot_id" )
490+ self .assertEqual (
491+ len (so_lots ),
492+ len (po_lots ),
493+ msg = "There aren't the same number of lots on both moves" ,
494+ )
495+ self .assertEqual (
496+ so_lots , po_lots , msg = "The lots of the moves should be the same"
497+ )
498+ self .assertEqual (
499+ so_lots .mapped ("name" ),
500+ po_lots .mapped ("name" ),
501+ msg = "The lots should have the same name in both moves" ,
502+ )
503+ self .assertFalse (so_lots .company_id , msg = "Lots should not have a company." )
504+
412505 def test_sync_picking_same_product_multiple_lines (self ):
413506 """
414507 Picking synchronization should work even when there
@@ -533,7 +626,7 @@ def test_raise_picking_problem(self):
533626 # Set quantities done on the picking and validate
534627 for move in so_picking_id .move_ids :
535628 move .quantity = move .product_uom_qty
536- with self .assertRaises (UserError ):
629+ with self .assertRaisesRegex (UserError , "There's no corresponding line in PO" ):
537630 so_picking_id .button_validate ()
538631
539632 def test_sync_picking_multi_step (self ):
@@ -609,3 +702,123 @@ def test_sync_picking_multi_step(self):
609702 new_receipt_picking = done_purchase_picking ._get_next_transfers ()
610703 self .assertEqual (len (new_receipt_picking ), 1 )
611704 self .assertEqual (new_receipt_picking .state , "assigned" )
705+
706+ def test_sync_picking_multi_step_with_transit (self ):
707+ """
708+ Test that the lot is synchronized on the moves
709+ when using inter-company transit locations
710+ and warehouses are configured with multi-step routes.
711+ company B: Sale picking
712+ Picking 1: from Stock to Packing
713+ Picking 2: from Packing to Transit Location
714+ company A: Purchase picking
715+ Picking 1: from Transit Location to Input
716+ Picking 2: from Input to Stock
717+ """
718+ self .company_a .sync_picking = True
719+ self .warehouse_a .reception_steps = "two_steps"
720+ self .company_b .sync_picking = True
721+ self .warehouse_c .delivery_steps = "pick_ship"
722+ # Set inter-company locations on partners
723+ interco_location = self .env .ref ("stock.stock_location_inter_company" )
724+ self .partner_company_b .with_company (self .company_a ).write (
725+ {
726+ "property_stock_customer" : interco_location .id ,
727+ "property_stock_supplier" : interco_location .id ,
728+ }
729+ )
730+ self .partner_company_a .with_company (self .company_b ).write (
731+ {
732+ "property_stock_customer" : interco_location .id ,
733+ "property_stock_supplier" : interco_location .id ,
734+ }
735+ )
736+ purchase = self ._create_purchase_order (
737+ self .partner_company_b , self .stockable_product_serial
738+ )
739+ sale = self ._approve_po (purchase )
740+ self .assertEqual (len (purchase .picking_ids ), 1 )
741+ # Only a single picking is created for the sale.
742+ # When this picking is validated, two pickings should be created:
743+ # one for the backorder and one for the delivery.
744+ self .assertEqual (len (sale .picking_ids ), 1 )
745+ # Check the locations
746+ self .assertEqual (purchase .picking_ids .location_id .usage , "transit" )
747+ self .assertEqual (purchase .picking_ids .location_dest_id .usage , "internal" )
748+ self .assertEqual (sale .picking_ids .location_id .usage , "internal" )
749+ self .assertEqual (sale .picking_ids .location_dest_id .usage , "internal" )
750+ self .assertEqual (sale .picking_ids .move_ids .location_final_id .usage , "transit" )
751+ # validate the SO internal picking
752+ so_internal_pick = sale .picking_ids
753+ so_move = so_internal_pick .move_ids
754+ so_move .move_line_ids = [
755+ Command .clear (),
756+ Command .create (
757+ {
758+ "location_id" : so_move .location_id .id ,
759+ "location_dest_id" : so_move .location_dest_id .id ,
760+ "product_id" : self .stockable_product_serial .id ,
761+ "product_uom_id" : self .stockable_product_serial .uom_id .id ,
762+ "quantity" : 1 ,
763+ "lot_id" : self .serial_1 .id ,
764+ "picking_id" : so_internal_pick .id ,
765+ },
766+ ),
767+ Command .create (
768+ {
769+ "location_id" : so_move .location_id .id ,
770+ "location_dest_id" : so_move .location_dest_id .id ,
771+ "product_id" : self .stockable_product_serial .id ,
772+ "product_uom_id" : self .stockable_product_serial .uom_id .id ,
773+ "quantity" : 1 ,
774+ "lot_id" : self .serial_2 .id ,
775+ "picking_id" : so_internal_pick .id ,
776+ },
777+ ),
778+ Command .create (
779+ {
780+ "location_id" : so_move .location_id .id ,
781+ "location_dest_id" : so_move .location_dest_id .id ,
782+ "product_id" : self .stockable_product_serial .id ,
783+ "product_uom_id" : self .stockable_product_serial .uom_id .id ,
784+ "quantity" : 1 ,
785+ "lot_id" : self .serial_3 .id ,
786+ "picking_id" : so_internal_pick .id ,
787+ },
788+ ),
789+ ]
790+ so_internal_pick .with_user (self .user_company_b ).button_validate ()
791+ self .assertEqual (so_internal_pick .state , "done" )
792+ po_picking = purchase .picking_ids
793+ # check po_picking state
794+ self .assertEqual (po_picking .state , "waiting" )
795+ # validate the SO picking
796+ so_picking = sale .picking_ids .filtered (
797+ lambda x : x .location_dest_id .usage == "customer"
798+ )
799+ so_picking .with_user (self .user_company_b ).button_validate ()
800+ self .assertEqual (so_picking .state , "done" )
801+ # The location at the picking level is set to Customer by the operation type,
802+ # but at the move level, it is Transit.
803+ self .assertEqual (so_picking .location_dest_id .usage , "customer" )
804+ self .assertEqual (so_picking .move_ids .location_dest_id .usage , "transit" )
805+ # the move in the receipt should have a "next move" due to "two_steps"
806+ self .assertTrue (purchase .picking_ids .move_ids .move_dest_ids )
807+ self .assertEqual (len (sale .picking_ids ), 2 ) # Pick + Delivery
808+ # Quantities should have been synced
809+ self .assertEqual (
810+ po_picking .move_ids .quantity ,
811+ so_picking .move_ids .quantity ,
812+ )
813+ # Check picking state
814+ self .assertEqual (po_picking .state , "done" )
815+ new_receipt_picking = po_picking ._get_next_transfers ()
816+ self .assertEqual (len (new_receipt_picking ), 1 )
817+ self .assertEqual (new_receipt_picking .state , "assigned" )
818+ # check the lots
819+ so_lots = so_move .mapped ("move_line_ids.lot_id" )
820+ po_lots = po_picking .mapped ("move_ids.move_line_ids.lot_id" )
821+ self .assertEqual (
822+ so_lots , po_lots , msg = "The lots of the moves should be the same"
823+ )
824+ self .assertFalse (so_lots .company_id , msg = "Lots should not have a company." )
0 commit comments