Packing Slip not considering Batch No for the same Item


I had this situation, I made an Order Sales which include the same item twice (this in order to select two different batch numbers in the delivery note).

In the Delivery Note I specified the two items with two different batch numbers.


But when I made the Packing Slip it joins them, updated the quantity and shows only one batch number (guess the last one selected).


Is there is a way to not join the two items and show them separately in the Packing Slip as it does in the Delivery Note? Maybe customizing the form or something like that?

Thanks in advanced.

Hi @eirizarry ,

I could see that the issue is you are making packing slip from the delivery note… that is the place where we have a problem.

If you pull the code of Delivery note… it has a function called:

make_packing_list ()

and that function belongs to :

and the code goes like this:

def make_packing_list(doc):
	"""make packing list for Product Bundle item"""

	if doc.get("_action") and doc._action == "update_after_submit": return

	parent_items = []
	for d in doc.get("items"):
		if frappe.db.get_value("Product Bundle", {"new_item_code": d.item_code}):
			for i in get_product_bundle_items(d.item_code):
				update_packing_list_item(doc, i.item_code, flt(i.qty)*flt(d.stock_qty), d, i.description)

			if [d.item_code,] not in parent_items:

	cleanup_packing_list(doc, parent_items)

What I could see is that they are putting items by item code :

Also in packing Slip you can see that all items are loaded with “group by” of item code:

def get_details_for_packing(self):
			* 'Delivery Note Items' query result as a list of dict
			* Item Quantity dict of current packing slip doc
			* No. of Cases of this packing slip

		rows = [d.item_code for d in self.get("items")]

		# also pick custom fields from delivery note
		custom_fields = ', '.join(['dni.`{0}`'.format(d.fieldname)
			for d in frappe.get_meta("Delivery Note Item").get_custom_fields()
			if d.fieldtype not in no_value_fields])

		if custom_fields:
			custom_fields = ', ' + custom_fields

		condition = ""
		if rows:
			condition = " and item_code in (%s)" % (", ".join(["%s"]*len(rows)))

		# gets item code, qty per item code, latest packed qty per item code and stock uom
		res = frappe.db.sql("""select item_code, sum(qty) as qty,
			(select sum(psi.qty * (abs(ps.to_case_no - ps.from_case_no) + 1))
				from `tabPacking Slip` ps, `tabPacking Slip Item` psi
				where = psi.parent and ps.docstatus = 1
				and ps.delivery_note = dni.parent and psi.item_code=dni.item_code) as packed_qty,
			stock_uom, item_name, description, dni.batch_no {custom_fields}
			from `tabDelivery Note Item` dni
			where parent=%s {condition}
			group by item_code""".format(condition=condition, custom_fields=custom_fields),
			tuple([self.delivery_note] + rows), as_dict=1)

		ps_item_qty = dict([[d.item_code, d.qty] for d in self.get("items")])
		no_of_cases = cint(self.to_case_no) - cint(self.from_case_no) + 1

		return res, ps_item_qty, no_of_cases

So your batch number is out of differentiation here.

Also even if you tweak in above to codes the packing slip by default has validation for duplicate item codes in packing_slip.js :

cur_frm.cscript.validate_duplicate_items = function(doc, ps_detail) {
	for(var i=0; i<ps_detail.length; i++) {
		for(var j=0; j<ps_detail.length; j++) {
			if(i!=j && ps_detail[i].item_code && ps_detail[i].item_code==ps_detail[j].item_code) {
				frappe.msgprint(__("You have entered duplicate items. Please rectify and try again."));
				frappe.validated = false;
		if(flt(ps_detail[i].qty)<=0) {
			frappe.msgprint(__("Invalid quantity specified for item {0}. Quantity should be greater than 0.", [ps_detail[i].item_code]));
			frappe.validated = false;

There can be two strategies to this now :

  1. You create your customization to this and do the needful in the code.
  2. You create your own app, and create your own packing slip doc type, process and print format. (second one is advisable as it will be fail safe for further erpnext updates, or else you will have to keep on merging and solving conflicts each time you pull new version of erpnext)


Parth Joshi

Thanks @joshiparthin for the information. I will evaluate your recommendations.