Tests SO for Serial No based delivery (#15072)
* fix remove SO from Serial No only when voucher SE
* SO tests - delivery by Serial No
diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py
index f2919fb..f8fd1b3 100644
--- a/erpnext/selling/doctype/sales_order/test_sales_order.py
+++ b/erpnext/selling/doctype/sales_order/test_sales_order.py
@@ -275,10 +275,10 @@
make_sales_invoice(so.name)
existing_reserved_qty = get_reserved_qty()
-
+
trans_item = json.dumps([{'item_code' : '_Test Item', 'rate' : 200, 'qty' : 7, 'docname': so.items[0].name}])
update_child_qty_rate('Sales Order', trans_item, so.name)
-
+
so.reload()
self.assertEqual(so.get("items")[0].rate, 200)
self.assertEqual(so.get("items")[0].qty, 7)
@@ -584,6 +584,107 @@
wo_qty = frappe.db.sql("select sum(qty) from `tabWork Order` where sales_order=%s and sales_order_item=%s", (so.name, item))
self.assertEquals(wo_qty[0][0], so_item_name.get(item))
+ def test_serial_no_based_delivery(self):
+ from erpnext.stock.doctype.item.test_item import make_item
+ frappe.set_value("Stock Settings", None, "automatically_set_serial_nos_based_on_fifo", 1)
+ item = make_item("_Reserved_Serialized_Item", {"is_stock_item": 1,
+ "maintain_stock": 1,
+ "has_serial_no": 1,
+ "serial_no_series": "SI.####",
+ "valuation_rate": 500,
+ "item_defaults": [
+ {
+ "default_warehouse": "_Test Warehouse - _TC",
+ "company": "_Test Company"
+ }]
+ })
+ frappe.db.sql("""delete from `tabSerial No` where item_code=%s""", (item.item_code))
+ make_item("_Test Item A", {"maintain_stock": 1,
+ "valuation_rate": 100,
+ "item_defaults": [
+ {
+ "default_warehouse": "_Test Warehouse - _TC",
+ "company": "_Test Company"
+ }]
+ })
+ make_item("_Test Item B", {"maintain_stock": 1,
+ "valuation_rate": 200,
+ "item_defaults": [
+ {
+ "default_warehouse": "_Test Warehouse - _TC",
+ "company": "_Test Company"
+ }]
+ })
+ from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom
+ make_bom(item=item.item_code, rate=1000,
+ raw_materials = ['_Test Item A', '_Test Item B'])
+
+ so = make_sales_order(**{
+ "item_list": [{
+ "item_code": item.item_code,
+ "ensure_delivery_based_on_produced_serial_no": 1,
+ "qty": 1,
+ "rate":1000
+ }]
+ })
+ so.submit()
+ from erpnext.manufacturing.doctype.work_order.test_work_order import \
+ make_wo_order_test_record
+ work_order = make_wo_order_test_record(item=item.item_code,
+ qty=1, do_not_save=True)
+ work_order.fg_warehouse = "_Test Warehouse - _TC"
+ work_order.sales_order = so.name
+ work_order.submit()
+ make_stock_entry(item_code=item.item_code, target="_Test Warehouse - _TC", qty=1)
+ item_serial_no = frappe.get_doc("Serial No", {"item_code": item.item_code})
+ from erpnext.manufacturing.doctype.work_order.work_order import \
+ make_stock_entry as make_production_stock_entry
+ se = frappe.get_doc(make_production_stock_entry(work_order.name, "Manufacture", 1))
+ se.submit()
+ reserved_serial_no = se.get("items")[2].serial_no
+ serial_no_so = frappe.get_value("Serial No", reserved_serial_no, "sales_order")
+ self.assertEqual(serial_no_so, so.name)
+ dn = make_delivery_note(so.name)
+ dn.save()
+ self.assertEqual(reserved_serial_no, dn.get("items")[0].serial_no)
+ item_line = dn.get("items")[0]
+ item_line.serial_no = item_serial_no.name
+ self.assertRaises(frappe.ValidationError, dn.submit)
+ item_line = dn.get("items")[0]
+ item_line.serial_no = reserved_serial_no
+ self.assertTrue(dn.submit)
+ dn.load_from_db()
+ dn.cancel()
+ si = make_sales_invoice(so.name)
+ si.update_stock = 1
+ si.save()
+ self.assertEqual(si.get("items")[0].serial_no, reserved_serial_no)
+ item_line = si.get("items")[0]
+ item_line.serial_no = item_serial_no.name
+ self.assertRaises(frappe.ValidationError, dn.submit)
+ item_line = si.get("items")[0]
+ item_line.serial_no = reserved_serial_no
+ self.assertTrue(si.submit)
+ si.submit()
+ si.load_from_db()
+ si.cancel()
+ si = make_sales_invoice(so.name)
+ si.update_stock = 0
+ si.submit()
+ from erpnext.accounts.doctype.sales_invoice.sales_invoice import \
+ make_delivery_note as make_delivery_note_from_invoice
+ dn = make_delivery_note_from_invoice(si.name)
+ dn.save()
+ dn.submit()
+ self.assertEqual(dn.get("items")[0].serial_no, reserved_serial_no)
+ dn.load_from_db()
+ dn.cancel()
+ si.load_from_db()
+ si.cancel()
+ se.load_from_db()
+ se.cancel()
+ self.assertFalse(frappe.db.exists("Serial No", {"sales_order": so.name}))
+
def make_sales_order(**args):
so = frappe.new_doc("Sales Order")
args = frappe._dict(args)
diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py
index dcf7675..872daba 100644
--- a/erpnext/stock/doctype/serial_no/serial_no.py
+++ b/erpnext/stock/doctype/serial_no/serial_no.py
@@ -351,7 +351,8 @@
sr.warehouse = args.get('warehouse') if args.get('actual_qty', 0) > 0 else None
sr.batch_no = args.get('batch_no')
sr.location = args.get('location')
- if sr.sales_order and not args.get('actual_qty', 0) > 0:
+ if sr.sales_order and args.get('voucher_type') == "Stock Entry" \
+ and not args.get('actual_qty', 0) > 0:
sr.sales_order = None
sr.save(ignore_permissions=True)
elif args.get('actual_qty', 0) > 0: