mirror of
https://github.com/frappe/erpnext.git
synced 2026-10-29 22:57:42 +00:00
Merge pull request #62960 from aerele/fix/pick-list-bundle-second-delivery-note
fix(stock): map only undelivered bundles from a pick list and ask about drafts before creating the delivery note
This commit is contained in:
@@ -35,9 +35,13 @@ erpnext.utils.confirm_if_drafts_exist = async function (source_doc, target_docty
|
||||
};
|
||||
|
||||
if (frappe.model.add_mapped_doc_guard) {
|
||||
frappe.model.add_mapped_doc_guard((mapped_doc, opts) =>
|
||||
erpnext.utils.confirm_if_drafts_exist(opts.frm && opts.frm.doc, mapped_doc.doctype)
|
||||
);
|
||||
frappe.model.add_mapped_doc_guard((mapped_doc, opts) => {
|
||||
// a mapper that saved the target already created the draft, so ask before calling it instead
|
||||
if (mapped_doc.name && !mapped_doc.__islocal) {
|
||||
return true;
|
||||
}
|
||||
return erpnext.utils.confirm_if_drafts_exist(opts.frm && opts.frm.doc, mapped_doc.doctype);
|
||||
});
|
||||
}
|
||||
|
||||
function get_draft_warning(source_doc, target_doctype, drafts) {
|
||||
|
||||
@@ -360,8 +360,12 @@ def add_product_bundles_to_target(
|
||||
)
|
||||
)
|
||||
|
||||
pending_qty = pick_list._compute_picked_qty_for_bundle(so_row, bundle_items, pending_only=True)
|
||||
if not pending_qty:
|
||||
continue
|
||||
|
||||
target_bundle_item = map_child_doc(sales_order_item, target_doc, item_mapper)
|
||||
target_bundle_item.qty = pick_list._compute_picked_qty_for_bundle(so_row, bundle_items)
|
||||
target_bundle_item.qty = pending_qty
|
||||
target_bundle_item.against_pick_list = pick_list.name
|
||||
update_child_item(sales_order_item, target_bundle_item, target_doc)
|
||||
|
||||
|
||||
@@ -241,7 +241,11 @@ frappe.ui.form.on("Pick List", {
|
||||
frm.clear_table("locations");
|
||||
frm.trigger("add_get_items_button");
|
||||
},
|
||||
create_delivery(frm, doctype) {
|
||||
async create_delivery(frm, doctype) {
|
||||
if (!(await erpnext.utils.confirm_if_drafts_exist(frm.doc, doctype))) {
|
||||
return;
|
||||
}
|
||||
|
||||
frappe.model.open_mapped_doc({
|
||||
method: "erpnext.stock.doctype.pick_list.mapper.create_delivery",
|
||||
args: {
|
||||
|
||||
@@ -1080,8 +1080,8 @@ class PickList(TransactionBase):
|
||||
}
|
||||
return product_bundle_qty_map
|
||||
|
||||
def _compute_picked_qty_for_bundle(self, bundle_row, bundle_items) -> int:
|
||||
"""Compute how many full bundles can be created from picked items."""
|
||||
def _compute_picked_qty_for_bundle(self, bundle_row, bundle_items, pending_only=False) -> int:
|
||||
"""Compute how many full bundles can be created from picked (or picked but undelivered) items."""
|
||||
precision = frappe.get_precision("Stock Ledger Entry", "qty_after_transaction")
|
||||
possible_bundles = {}
|
||||
for item in self.locations:
|
||||
@@ -1089,8 +1089,9 @@ class PickList(TransactionBase):
|
||||
continue
|
||||
|
||||
if qty_in_bundle := bundle_items.get(item.item_code):
|
||||
qty = flt(item.picked_qty) - (flt(item.delivered_qty) if pending_only else 0)
|
||||
possible_bundles.setdefault(item.product_bundle_item, 0)
|
||||
possible_bundles[item.product_bundle_item] += item.picked_qty / qty_in_bundle
|
||||
possible_bundles[item.product_bundle_item] += qty / qty_in_bundle
|
||||
|
||||
return int(flt(min(possible_bundles.values()), precision or 6)) if possible_bundles else 0
|
||||
|
||||
|
||||
@@ -2197,6 +2197,29 @@ class TestPickList(ERPNextTestSuite):
|
||||
so.reload()
|
||||
self.assertEqual(so.per_delivered, 100)
|
||||
|
||||
def test_second_delivery_note_maps_only_undelivered_bundles(self):
|
||||
warehouse = "_Test Warehouse - _TC"
|
||||
bundle, components = create_product_bundle([5, 2], warehouse=warehouse)
|
||||
so = make_sales_order(item_code=bundle, qty=4, rate=42)
|
||||
pl = create_pick_list(so.name).save().submit()
|
||||
|
||||
first_dn = create_delivery_note(pl.name)
|
||||
first_dn.items[0].qty = 1
|
||||
first_dn.save().submit()
|
||||
|
||||
second_dn = create_delivery_note(pl.name)
|
||||
self.assertEqual(second_dn.items[0].qty, 3)
|
||||
packed_qty = {row.item_code: row.qty for row in second_dn.packed_items}
|
||||
self.assertEqual(packed_qty, {components[0]: 15, components[1]: 6})
|
||||
|
||||
second_dn.submit()
|
||||
so.reload()
|
||||
self.assertEqual(so.items[0].delivered_qty, 4)
|
||||
self.assertEqual(so.per_delivered, 100)
|
||||
pl.reload()
|
||||
self.assertEqual(pl.per_delivered, 100)
|
||||
self.assertEqual(pl.status, "Completed")
|
||||
|
||||
def test_pick_list_status(self):
|
||||
warehouse = "_Test Warehouse - _TC"
|
||||
item = make_item(properties={"is_stock_item": 1}).name
|
||||
|
||||
Reference in New Issue
Block a user