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 packed_item.py
:
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, d.name] not in parent_items:
parent_items.append([d.item_code, d.name])
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):
"""
Returns
* '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 ps.name = 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;
return;
}
}
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 :
- You create your customization to this and do the needful in the code.
- 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)
Regards,
Parth Joshi