@@ -2602,6 +2602,293 @@ def test_serial_no_status_for_stock_entry(self):
26022602 status = frappe .db .get_value ("Serial No" , row , "status" )
26032603 self .assertEqual (status , "Consumed" )
26042604
2605+ < << << << HEAD
2606+ == == == =
2607+ def test_stock_reservation_for_serialized_raw_material (self ):
2608+ from erpnext .stock .doctype .stock_entry .stock_entry_utils import (
2609+ make_stock_entry as make_stock_entry_test_record ,
2610+ )
2611+
2612+ production_item = "Test Stock Reservation FG 1"
2613+ rm_item = "Test Stock Reservation RM 1"
2614+ source_warehouse = "Stores - _TC"
2615+
2616+ make_item (production_item , {"is_stock_item" : 1 })
2617+ make_item (rm_item , {"is_stock_item" : 1 , "has_serial_no" : 1 , "serial_no_series" : "TST-SER-RES-.###" })
2618+
2619+ bom = make_bom (
2620+ item = production_item ,
2621+ source_warehouse = source_warehouse ,
2622+ raw_materials = [rm_item ],
2623+ operating_cost_per_bom_quantity = 100 ,
2624+ do_not_submit = True ,
2625+ )
2626+
2627+ for row in bom .exploded_items :
2628+ make_stock_entry_test_record (
2629+ item_code = row .item_code ,
2630+ target = source_warehouse ,
2631+ qty = 10 ,
2632+ basic_rate = 100 ,
2633+ )
2634+
2635+ wo = make_wo_order_test_record (
2636+ item = production_item ,
2637+ qty = 10 ,
2638+ reserve_stock = 1 ,
2639+ source_warehouse = source_warehouse ,
2640+ )
2641+
2642+ self .assertTrue (frappe .get_all ("Stock Reservation Entry" , filters = {"voucher_no" : wo .name }))
2643+
2644+ wo1 = make_wo_order_test_record (
2645+ item = production_item ,
2646+ qty = 10 ,
2647+ reserve_stock = 1 ,
2648+ source_warehouse = source_warehouse ,
2649+ )
2650+
2651+ self .assertFalse (frappe .get_all ("Stock Reservation Entry" , filters = {"voucher_no" : wo1 .name }))
2652+
2653+ transfer_entry = frappe .get_doc (make_stock_entry (wo1 .name , "Material Transfer for Manufacture" , 10 ))
2654+ transfer_entry .save ()
2655+
2656+ self .assertRaises (frappe .ValidationError , transfer_entry .submit )
2657+
2658+ def test_stock_reservation_for_batched_raw_material (self ):
2659+ from erpnext .stock .doctype .stock_entry .stock_entry_utils import (
2660+ make_stock_entry as make_stock_entry_test_record ,
2661+ )
2662+
2663+ production_item = "Test Stock Reservation FG 2"
2664+ rm_item = "Test Stock Reservation RM 2"
2665+ source_warehouse = "Stores - _TC"
2666+
2667+ make_item (production_item , {"is_stock_item" : 1 })
2668+ make_item (
2669+ rm_item ,
2670+ {
2671+ "is_stock_item" : 1 ,
2672+ "has_batch_no" : 1 ,
2673+ "batch_number_series" : "TST-BATCH-RES-.###" ,
2674+ "create_new_batch" : 1 ,
2675+ },
2676+ )
2677+
2678+ bom = make_bom (
2679+ item = production_item ,
2680+ source_warehouse = source_warehouse ,
2681+ raw_materials = [rm_item ],
2682+ operating_cost_per_bom_quantity = 100 ,
2683+ do_not_submit = True ,
2684+ )
2685+
2686+ for row in bom .exploded_items :
2687+ make_stock_entry_test_record (
2688+ item_code = row .item_code ,
2689+ target = source_warehouse ,
2690+ qty = 10 ,
2691+ basic_rate = 100 ,
2692+ )
2693+
2694+ wo = make_wo_order_test_record (
2695+ item = production_item ,
2696+ qty = 10 ,
2697+ reserve_stock = 1 ,
2698+ source_warehouse = source_warehouse ,
2699+ )
2700+
2701+ self .assertTrue (frappe .get_all ("Stock Reservation Entry" , filters = {"voucher_no" : wo .name }))
2702+
2703+ wo1 = make_wo_order_test_record (
2704+ item = production_item ,
2705+ qty = 10 ,
2706+ reserve_stock = 1 ,
2707+ source_warehouse = source_warehouse ,
2708+ )
2709+
2710+ self .assertFalse (frappe .get_all ("Stock Reservation Entry" , filters = {"voucher_no" : wo1 .name }))
2711+
2712+ transfer_entry = frappe .get_doc (make_stock_entry (wo1 .name , "Material Transfer for Manufacture" , 10 ))
2713+ transfer_entry .save ()
2714+
2715+ self .assertRaises (frappe .ValidationError , transfer_entry .submit )
2716+
2717+ def test_auto_stock_reservation_for_batched_raw_material (self ):
2718+ from erpnext .stock .doctype .stock_entry .stock_entry_utils import (
2719+ make_stock_entry as make_stock_entry_test_record ,
2720+ )
2721+
2722+ frappe .db .set_single_value ("Stock Settings" , "auto_reserve_serial_and_batch" , 1 )
2723+
2724+ production_item = "Test Stock Reservation FG 3"
2725+ rm_item = "Test Stock Reservation RM 3"
2726+ source_warehouse = "Stores - _TC"
2727+
2728+ make_item (production_item , {"is_stock_item" : 1 })
2729+ make_item (
2730+ rm_item ,
2731+ {
2732+ "is_stock_item" : 1 ,
2733+ "has_batch_no" : 1 ,
2734+ "batch_number_series" : "TST-BATCH-RES-.###" ,
2735+ "create_new_batch" : 1 ,
2736+ },
2737+ )
2738+
2739+ bom = make_bom (
2740+ item = production_item ,
2741+ source_warehouse = source_warehouse ,
2742+ raw_materials = [rm_item ],
2743+ operating_cost_per_bom_quantity = 100 ,
2744+ do_not_submit = True ,
2745+ )
2746+
2747+ itemwise_batches = frappe ._dict ()
2748+ for row in bom .exploded_items :
2749+ se = make_stock_entry_test_record (
2750+ item_code = row .item_code ,
2751+ target = source_warehouse ,
2752+ qty = 10 ,
2753+ basic_rate = 100 ,
2754+ )
2755+
2756+ itemwise_batches [row .item_code ] = get_batch_from_bundle (se .items [0 ].serial_and_batch_bundle )
2757+
2758+ wo = make_wo_order_test_record (
2759+ item = production_item ,
2760+ qty = 10 ,
2761+ reserve_stock = 1 ,
2762+ source_warehouse = source_warehouse ,
2763+ )
2764+
2765+ self .assertTrue (frappe .get_all ("Stock Reservation Entry" , filters = {"voucher_no" : wo .name }))
2766+
2767+ for row in frappe .get_all ("Stock Reservation Entry" , filters = {"voucher_no" : wo .name }):
2768+ reservation_entry = frappe .get_doc ("Stock Reservation Entry" , row .name )
2769+ self .assertTrue (reservation_entry .has_batch_no )
2770+ self .assertTrue (reservation_entry .sb_entries )
2771+
2772+ for row in bom .exploded_items :
2773+ make_stock_entry_test_record (
2774+ item_code = row .item_code ,
2775+ target = source_warehouse ,
2776+ qty = 10 ,
2777+ basic_rate = 100 ,
2778+ )
2779+
2780+ transfer_entry = frappe .get_doc (make_stock_entry (wo .name , "Material Transfer for Manufacture" , 10 ))
2781+ transfer_entry .save ()
2782+ transfer_entry .submit ()
2783+
2784+ for row in transfer_entry .items :
2785+ batch_no = get_batch_from_bundle (row .serial_and_batch_bundle )
2786+ self .assertEqual (batch_no , itemwise_batches [row .item_code ])
2787+
2788+ def test_work_order_valuation_auto_pick (self ):
2789+ fg_item = "Test FG Item For Non Transfer Item Batch"
2790+ rm_item = "Test RM Item For Non Transfer Item Batch"
2791+
2792+ make_item (fg_item , {"is_stock_item" : 1 })
2793+ make_item (
2794+ rm_item ,
2795+ {
2796+ "is_stock_item" : 1 ,
2797+ "has_batch_no" : 1 ,
2798+ "create_new_batch" : 1 ,
2799+ "batch_number_series" : "TST-BATCH-NTI-.###" ,
2800+ },
2801+ )
2802+
2803+ source_warehouse = "_Test Warehouse - _TC"
2804+ wip_warehouse = "Stores - _TC"
2805+ finished_goods_warehouse = create_warehouse ("_Test Finished Goods Warehouse" , company = "_Test Company" )
2806+
2807+ batches = make_stock_in_entries_and_get_batches (rm_item , source_warehouse , wip_warehouse )
2808+
2809+ if not frappe .db .get_value ("BOM" , {"item" : fg_item }):
2810+ make_bom (item = fg_item , raw_materials = [rm_item ])
2811+
2812+ wo = make_wo_order_test_record (
2813+ item = fg_item ,
2814+ qty = 5 ,
2815+ source_warehouse = source_warehouse ,
2816+ wip_warehouse = wip_warehouse ,
2817+ fg_warehouse = finished_goods_warehouse ,
2818+ )
2819+
2820+ stock_entry = frappe .get_doc (make_stock_entry (wo .name , "Material Transfer for Manufacture" , 5 ))
2821+ stock_entry .items [0 ].batch_no = batches [1 ]
2822+ stock_entry .items [0 ].use_serial_batch_fields = 1
2823+ stock_entry .submit ()
2824+ stock_entry .reload ()
2825+
2826+ self .assertEqual (stock_entry .items [0 ].valuation_rate , 200 )
2827+
2828+ original_value = frappe .db .get_single_value (
2829+ "Stock Settings" , "auto_create_serial_and_batch_bundle_for_outward"
2830+ )
2831+ original_based_on = frappe .db .get_single_value ("Stock Settings" , "pick_serial_and_batch_based_on" )
2832+
2833+ frappe .db .set_single_value ("Stock Settings" , "auto_create_serial_and_batch_bundle_for_outward" , 1 )
2834+ frappe .db .set_single_value ("Stock Settings" , "pick_serial_and_batch_based_on" , "Expiry" )
2835+
2836+ stock_entry = frappe .get_doc (make_stock_entry (wo .name , "Manufacture" , 5 ))
2837+ stock_entry .items [0 ].use_serial_batch_fields = 1
2838+ stock_entry .submit ()
2839+ stock_entry .reload ()
2840+
2841+ batch_no = get_batch_from_bundle (stock_entry .items [0 ].serial_and_batch_bundle )
2842+ self .assertEqual (batch_no , batches [1 ])
2843+ self .assertEqual (stock_entry .items [0 ].valuation_rate , 200 )
2844+ self .assertEqual (stock_entry .items [1 ].valuation_rate , 200 )
2845+
2846+ frappe .db .set_single_value (
2847+ "Stock Settings" , "auto_create_serial_and_batch_bundle_for_outward" , original_value
2848+ )
2849+ frappe .db .set_single_value ("Stock Settings" , "pick_serial_and_batch_based_on" , original_based_on )
2850+
2851+
2852+ def make_stock_in_entries_and_get_batches (rm_item , source_warehouse , wip_warehouse ):
2853+ from erpnext .stock .doctype .stock_entry .test_stock_entry import (
2854+ make_stock_entry as make_stock_entry_test_record ,
2855+ )
2856+
2857+ batches = []
2858+ for qty , rate in ((5 , 100 ), (5 , 200 )):
2859+ stock_entry = make_stock_entry_test_record (
2860+ item_code = rm_item ,
2861+ target = source_warehouse ,
2862+ qty = qty ,
2863+ basic_rate = rate ,
2864+ )
2865+ stock_entry .submit ()
2866+ stock_entry .reload ()
2867+
2868+ batch_no = get_batch_from_bundle (stock_entry .items [0 ].serial_and_batch_bundle )
2869+ batch_doc = frappe .get_doc ("Batch" , batch_no )
2870+
2871+ # keep early expiry date for the batch having rate 200
2872+ days = 10 if rate == 100 else 1
2873+ batch_doc .db_set ("expiry_date" , add_to_date (now (), days = days ))
2874+
2875+ batches .append (batch_no )
2876+
2877+ stock_entry = make_stock_entry_test_record (
2878+ item_code = rm_item ,
2879+ target = wip_warehouse ,
2880+ qty = qty ,
2881+ basic_rate = rate ,
2882+ )
2883+ stock_entry .submit ()
2884+ stock_entry .reload ()
2885+ batch_no = get_batch_from_bundle (stock_entry .items [0 ].serial_and_batch_bundle )
2886+ batch_doc = frappe .get_doc ("Batch" , batch_no )
2887+ batch_doc .db_set ("expiry_date" , add_to_date (now (), days = 10 ))
2888+
2889+ return batches
2890+
2891+ >> >> >> > 5 af8378471 (fix : valuation rate not updating for raw materials )
26052892
26062893def make_operation (** kwargs ):
26072894 kwargs = frappe ._dict (kwargs )
0 commit comments