mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-27 05:45:19 +00:00
Merge pull request #56915 from aerele/backport/pick-list-partial-transfer-v16
feat(stock): support partial transfer from pick list
This commit is contained in:
@@ -166,7 +166,8 @@ status_map = {
|
|||||||
"Pick List": [
|
"Pick List": [
|
||||||
["Draft", None],
|
["Draft", None],
|
||||||
["Open", "eval:self.docstatus == 1"],
|
["Open", "eval:self.docstatus == 1"],
|
||||||
["Completed", "stock_entry_exists"],
|
["Completed", "is_fully_transferred"],
|
||||||
|
["Partially Transferred", "is_partially_transferred"],
|
||||||
[
|
[
|
||||||
"Partly Delivered",
|
"Partly Delivered",
|
||||||
"eval:self.purpose == 'Delivery' and self.delivery_status == 'Partly Delivered'",
|
"eval:self.purpose == 'Delivery' and self.delivery_status == 'Partly Delivered'",
|
||||||
|
|||||||
@@ -489,3 +489,4 @@ erpnext.patches.v16_0.remove_mandatory_from_inv_dimension_fields
|
|||||||
erpnext.patches.v15_0.backfill_sla_link_filters_on_custom_field
|
erpnext.patches.v15_0.backfill_sla_link_filters_on_custom_field
|
||||||
erpnext.patches.v15_0.backfill_sla_link_filters_on_docfield
|
erpnext.patches.v15_0.backfill_sla_link_filters_on_docfield
|
||||||
erpnext.patches.v16_0.crm_settings_handle_allowed_users_for_frappe_crm
|
erpnext.patches.v16_0.crm_settings_handle_allowed_users_for_frappe_crm
|
||||||
|
erpnext.patches.v16_0.backfill_pick_list_transferred_qty
|
||||||
|
|||||||
58
erpnext/patches/v16_0/backfill_pick_list_transferred_qty.py
Normal file
58
erpnext/patches/v16_0/backfill_pick_list_transferred_qty.py
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import frappe
|
||||||
|
from frappe.query_builder.functions import Sum
|
||||||
|
from frappe.utils import flt
|
||||||
|
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
StockEntry = frappe.qb.DocType("Stock Entry")
|
||||||
|
StockEntryDetail = frappe.qb.DocType("Stock Entry Detail")
|
||||||
|
|
||||||
|
pick_lists = (
|
||||||
|
frappe.qb.from_(StockEntry)
|
||||||
|
.select(StockEntry.pick_list)
|
||||||
|
.distinct()
|
||||||
|
.where((StockEntry.pick_list.isnotnull()) & (StockEntry.docstatus == 1))
|
||||||
|
).run(pluck=True)
|
||||||
|
|
||||||
|
if not pick_lists:
|
||||||
|
return
|
||||||
|
|
||||||
|
rows = (
|
||||||
|
frappe.qb.from_(StockEntryDetail)
|
||||||
|
.join(StockEntry)
|
||||||
|
.on(StockEntryDetail.parent == StockEntry.name)
|
||||||
|
.select(
|
||||||
|
StockEntry.pick_list,
|
||||||
|
StockEntryDetail.item_code,
|
||||||
|
StockEntryDetail.s_warehouse,
|
||||||
|
Sum(StockEntryDetail.transfer_qty).as_("qty"),
|
||||||
|
)
|
||||||
|
.where((StockEntry.pick_list.isin(pick_lists)) & (StockEntry.docstatus == 1))
|
||||||
|
.groupby(StockEntry.pick_list, StockEntryDetail.item_code, StockEntryDetail.s_warehouse)
|
||||||
|
).run(as_dict=True)
|
||||||
|
|
||||||
|
transferred = {(r.pick_list, r.item_code, r.s_warehouse): flt(r.qty) for r in rows}
|
||||||
|
|
||||||
|
items = frappe.get_all(
|
||||||
|
"Pick List Item",
|
||||||
|
filters={"parent": ("in", pick_lists), "picked_qty": (">", 0)},
|
||||||
|
fields=["name", "parent", "item_code", "warehouse", "picked_qty"],
|
||||||
|
order_by="idx",
|
||||||
|
)
|
||||||
|
|
||||||
|
updates = {}
|
||||||
|
for row in items:
|
||||||
|
key = (row.parent, row.item_code, row.warehouse)
|
||||||
|
available = transferred.get(key, 0)
|
||||||
|
if available <= 0:
|
||||||
|
continue
|
||||||
|
qty = min(flt(row.picked_qty), available)
|
||||||
|
transferred[key] = available - qty
|
||||||
|
updates[row.name] = {"transferred_qty": qty}
|
||||||
|
|
||||||
|
if not updates:
|
||||||
|
return
|
||||||
|
|
||||||
|
frappe.db.auto_commit_on_many_writes = True
|
||||||
|
frappe.db.bulk_update("Pick List Item", updates)
|
||||||
|
frappe.db.auto_commit_on_many_writes = False
|
||||||
@@ -190,7 +190,7 @@
|
|||||||
"in_standard_filter": 1,
|
"in_standard_filter": 1,
|
||||||
"label": "Status",
|
"label": "Status",
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"options": "Draft\nOpen\nPartly Delivered\nCompleted\nCancelled",
|
"options": "Draft\nOpen\nPartly Delivered\nPartially Transferred\nCompleted\nCancelled",
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"report_hide": 1,
|
"report_hide": 1,
|
||||||
@@ -278,7 +278,7 @@
|
|||||||
],
|
],
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2026-02-06 18:14:18.361039",
|
"modified": "2026-07-06 18:17:18.000000",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Pick List",
|
"name": "Pick List",
|
||||||
|
|||||||
@@ -73,7 +73,9 @@ class PickList(TransactionBase):
|
|||||||
purpose: DF.Literal["Material Transfer for Manufacture", "Material Transfer", "Delivery"]
|
purpose: DF.Literal["Material Transfer for Manufacture", "Material Transfer", "Delivery"]
|
||||||
scan_barcode: DF.Data | None
|
scan_barcode: DF.Data | None
|
||||||
scan_mode: DF.Check
|
scan_mode: DF.Check
|
||||||
status: DF.Literal["Draft", "Open", "Partly Delivered", "Completed", "Cancelled"]
|
status: DF.Literal[
|
||||||
|
"Draft", "Open", "Partly Delivered", "Partially Transferred", "Completed", "Cancelled"
|
||||||
|
]
|
||||||
work_order: DF.Link | None
|
work_order: DF.Link | None
|
||||||
# end: auto-generated types
|
# end: auto-generated types
|
||||||
|
|
||||||
@@ -419,6 +421,34 @@ class PickList(TransactionBase):
|
|||||||
|
|
||||||
return stock_entry_exists(self.name)
|
return stock_entry_exists(self.name)
|
||||||
|
|
||||||
|
def get_transfer_status(self):
|
||||||
|
"""Return the pick list's transfer progress based on how much of the picked qty has been
|
||||||
|
moved into submitted Stock Entries (tracked on Pick List Item.transferred_qty).
|
||||||
|
|
||||||
|
Only applies to purposes that move stock via Stock Entry; the Delivery purpose is tracked
|
||||||
|
via delivery_status instead. Returns "Completed", "Partially Transferred" or None."""
|
||||||
|
if self.purpose == "Delivery":
|
||||||
|
return None
|
||||||
|
|
||||||
|
total_picked = sum(flt(row.picked_qty) for row in self.locations)
|
||||||
|
if not total_picked:
|
||||||
|
return None
|
||||||
|
|
||||||
|
total_transferred = sum(flt(row.transferred_qty) for row in self.locations)
|
||||||
|
if total_transferred <= 0:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if total_transferred >= total_picked:
|
||||||
|
return "Completed"
|
||||||
|
|
||||||
|
return "Partially Transferred"
|
||||||
|
|
||||||
|
def is_fully_transferred(self):
|
||||||
|
return self.get_transfer_status() == "Completed"
|
||||||
|
|
||||||
|
def is_partially_transferred(self):
|
||||||
|
return self.get_transfer_status() == "Partially Transferred"
|
||||||
|
|
||||||
def update_reference_qty(self):
|
def update_reference_qty(self):
|
||||||
packed_items = []
|
packed_items = []
|
||||||
so_items = []
|
so_items = []
|
||||||
@@ -1544,13 +1574,10 @@ def add_product_bundles_to_target(pick_list, target_doc, item_mapper, sales_orde
|
|||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def create_stock_entry(pick_list):
|
def create_stock_entry(pick_list: str | dict):
|
||||||
pick_list = frappe.get_doc(json.loads(pick_list))
|
pick_list = frappe.get_doc(frappe.parse_json(pick_list))
|
||||||
validate_item_locations(pick_list)
|
validate_item_locations(pick_list)
|
||||||
|
|
||||||
if stock_entry_exists(pick_list.get("name")):
|
|
||||||
return frappe.msgprint(_("Stock Entry has been already created against this Pick List"))
|
|
||||||
|
|
||||||
stock_entry = frappe.new_doc("Stock Entry")
|
stock_entry = frappe.new_doc("Stock Entry")
|
||||||
stock_entry.pick_list = pick_list.get("name")
|
stock_entry.pick_list = pick_list.get("name")
|
||||||
stock_entry.purpose = pick_list.get("purpose")
|
stock_entry.purpose = pick_list.get("purpose")
|
||||||
@@ -1564,6 +1591,9 @@ def create_stock_entry(pick_list):
|
|||||||
else:
|
else:
|
||||||
stock_entry = update_stock_entry_items_with_no_reference(pick_list, stock_entry)
|
stock_entry = update_stock_entry_items_with_no_reference(pick_list, stock_entry)
|
||||||
|
|
||||||
|
if not stock_entry.get("items"):
|
||||||
|
return frappe.msgprint(_("All picked items have already been transferred against this Pick List"))
|
||||||
|
|
||||||
stock_entry.set_missing_values()
|
stock_entry.set_missing_values()
|
||||||
|
|
||||||
return stock_entry.as_dict()
|
return stock_entry.as_dict()
|
||||||
@@ -1673,6 +1703,8 @@ def update_stock_entry_based_on_work_order(pick_list, stock_entry):
|
|||||||
stock_entry.project = work_order.project
|
stock_entry.project = work_order.project
|
||||||
|
|
||||||
for location in pick_list.locations:
|
for location in pick_list.locations:
|
||||||
|
if get_pending_transfer_stock_qty(location) <= 0:
|
||||||
|
continue
|
||||||
item = frappe._dict()
|
item = frappe._dict()
|
||||||
update_common_item_properties(item, location)
|
update_common_item_properties(item, location)
|
||||||
item.t_warehouse = wip_warehouse
|
item.t_warehouse = wip_warehouse
|
||||||
@@ -1684,6 +1716,8 @@ def update_stock_entry_based_on_work_order(pick_list, stock_entry):
|
|||||||
|
|
||||||
def update_stock_entry_based_on_material_request(pick_list, stock_entry):
|
def update_stock_entry_based_on_material_request(pick_list, stock_entry):
|
||||||
for location in pick_list.locations:
|
for location in pick_list.locations:
|
||||||
|
if get_pending_transfer_stock_qty(location) <= 0:
|
||||||
|
continue
|
||||||
target_warehouse = None
|
target_warehouse = None
|
||||||
if location.material_request_item:
|
if location.material_request_item:
|
||||||
target_warehouse = frappe.get_value(
|
target_warehouse = frappe.get_value(
|
||||||
@@ -1699,6 +1733,8 @@ def update_stock_entry_based_on_material_request(pick_list, stock_entry):
|
|||||||
|
|
||||||
def update_stock_entry_items_with_no_reference(pick_list, stock_entry):
|
def update_stock_entry_items_with_no_reference(pick_list, stock_entry):
|
||||||
for location in pick_list.locations:
|
for location in pick_list.locations:
|
||||||
|
if get_pending_transfer_stock_qty(location) <= 0:
|
||||||
|
continue
|
||||||
item = frappe._dict()
|
item = frappe._dict()
|
||||||
update_common_item_properties(item, location)
|
update_common_item_properties(item, location)
|
||||||
|
|
||||||
@@ -1707,11 +1743,18 @@ def update_stock_entry_items_with_no_reference(pick_list, stock_entry):
|
|||||||
return stock_entry
|
return stock_entry
|
||||||
|
|
||||||
|
|
||||||
|
def get_pending_transfer_stock_qty(location):
|
||||||
|
"""Stock qty of this pick list row still to be moved into a Stock Entry."""
|
||||||
|
return flt(location.picked_qty) - flt(location.transferred_qty)
|
||||||
|
|
||||||
|
|
||||||
def update_common_item_properties(item, location):
|
def update_common_item_properties(item, location):
|
||||||
|
pending_stock_qty = get_pending_transfer_stock_qty(location)
|
||||||
item.item_code = location.item_code
|
item.item_code = location.item_code
|
||||||
|
item.item_name = location.item_name
|
||||||
item.s_warehouse = location.warehouse
|
item.s_warehouse = location.warehouse
|
||||||
item.transfer_qty = location.picked_qty
|
item.transfer_qty = pending_stock_qty
|
||||||
item.qty = flt(location.picked_qty / (location.conversion_factor or 1), location.precision("qty"))
|
item.qty = flt(pending_stock_qty / (location.conversion_factor or 1), location.precision("qty"))
|
||||||
item.uom = location.uom
|
item.uom = location.uom
|
||||||
item.conversion_factor = location.conversion_factor
|
item.conversion_factor = location.conversion_factor
|
||||||
item.stock_uom = location.stock_uom
|
item.stock_uom = location.stock_uom
|
||||||
@@ -1719,6 +1762,7 @@ def update_common_item_properties(item, location):
|
|||||||
item.serial_no = location.serial_no
|
item.serial_no = location.serial_no
|
||||||
item.batch_no = location.batch_no
|
item.batch_no = location.batch_no
|
||||||
item.material_request_item = location.material_request_item
|
item.material_request_item = location.material_request_item
|
||||||
|
item.pick_list_item = location.name
|
||||||
|
|
||||||
|
|
||||||
def get_rejected_warehouses():
|
def get_rejected_warehouses():
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ frappe.listview_settings["Pick List"] = {
|
|||||||
Draft: "red",
|
Draft: "red",
|
||||||
Open: "orange",
|
Open: "orange",
|
||||||
"Partly Delivered": "orange",
|
"Partly Delivered": "orange",
|
||||||
|
"Partially Transferred": "yellow",
|
||||||
Completed: "green",
|
Completed: "green",
|
||||||
Cancelled: "red",
|
Cancelled: "red",
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ from erpnext.stock.doctype.pick_list.pick_list import (
|
|||||||
create_delivery,
|
create_delivery,
|
||||||
create_delivery_note,
|
create_delivery_note,
|
||||||
create_dn_for_pick_lists,
|
create_dn_for_pick_lists,
|
||||||
|
create_stock_entry,
|
||||||
)
|
)
|
||||||
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
|
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
|
||||||
from erpnext.stock.doctype.serial_and_batch_bundle.test_serial_and_batch_bundle import (
|
from erpnext.stock.doctype.serial_and_batch_bundle.test_serial_and_batch_bundle import (
|
||||||
@@ -1221,6 +1222,64 @@ class TestPickList(ERPNextTestSuite):
|
|||||||
pl.reload()
|
pl.reload()
|
||||||
self.assertEqual(pl.status, "Cancelled")
|
self.assertEqual(pl.status, "Cancelled")
|
||||||
|
|
||||||
|
def test_pick_list_partial_transfer_status(self):
|
||||||
|
"""Partial Stock Entries from a Pick List should track transferred_qty and drive the
|
||||||
|
Partially Transferred / Completed status, and allow further transfers for the remainder."""
|
||||||
|
from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
|
||||||
|
|
||||||
|
item = make_item(properties={"is_stock_item": 1}).name
|
||||||
|
source_warehouse = "_Test Warehouse - _TC"
|
||||||
|
target_warehouse = create_warehouse("_Test Transfer Target Warehouse")
|
||||||
|
make_stock_entry(item=item, to_warehouse=source_warehouse, qty=10)
|
||||||
|
|
||||||
|
pick_list = frappe.get_doc(
|
||||||
|
{
|
||||||
|
"doctype": "Pick List",
|
||||||
|
"company": "_Test Company",
|
||||||
|
"purpose": "Material Transfer",
|
||||||
|
"pick_manually": 1,
|
||||||
|
"locations": [
|
||||||
|
{
|
||||||
|
"item_code": item,
|
||||||
|
"qty": 10,
|
||||||
|
"stock_qty": 10,
|
||||||
|
"conversion_factor": 1,
|
||||||
|
"warehouse": source_warehouse,
|
||||||
|
"picked_qty": 10,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
pick_list.submit()
|
||||||
|
self.assertEqual(pick_list.status, "Open")
|
||||||
|
|
||||||
|
# Transfer 4 of the 10 picked units.
|
||||||
|
se1 = frappe.get_doc(create_stock_entry(pick_list.as_dict()))
|
||||||
|
self.assertEqual(se1.items[0].qty, 10)
|
||||||
|
se1.items[0].qty = 4
|
||||||
|
se1.items[0].t_warehouse = target_warehouse
|
||||||
|
se1.submit()
|
||||||
|
|
||||||
|
pick_list.reload()
|
||||||
|
self.assertEqual(pick_list.locations[0].transferred_qty, 4)
|
||||||
|
self.assertEqual(pick_list.status, "Partially Transferred")
|
||||||
|
|
||||||
|
# The next Stock Entry should only offer the remaining 6 units.
|
||||||
|
se2 = frappe.get_doc(create_stock_entry(pick_list.as_dict()))
|
||||||
|
self.assertEqual(se2.items[0].qty, 6)
|
||||||
|
se2.items[0].t_warehouse = target_warehouse
|
||||||
|
se2.submit()
|
||||||
|
|
||||||
|
pick_list.reload()
|
||||||
|
self.assertEqual(pick_list.locations[0].transferred_qty, 10)
|
||||||
|
self.assertEqual(pick_list.status, "Completed")
|
||||||
|
|
||||||
|
# Cancelling the last entry rolls transferred_qty and status back.
|
||||||
|
se2.cancel()
|
||||||
|
pick_list.reload()
|
||||||
|
self.assertEqual(pick_list.locations[0].transferred_qty, 4)
|
||||||
|
self.assertEqual(pick_list.status, "Partially Transferred")
|
||||||
|
|
||||||
def test_pick_list_validation(self):
|
def test_pick_list_validation(self):
|
||||||
warehouse = "_Test Warehouse - _TC"
|
warehouse = "_Test Warehouse - _TC"
|
||||||
item = make_item("Test Non Serialized Pick List Item", properties={"is_stock_item": 1}).name
|
item = make_item("Test Non Serialized Pick List Item", properties={"is_stock_item": 1}).name
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
"conversion_factor",
|
"conversion_factor",
|
||||||
"stock_uom",
|
"stock_uom",
|
||||||
"delivered_qty",
|
"delivered_qty",
|
||||||
|
"transferred_qty",
|
||||||
"available_quantity_section",
|
"available_quantity_section",
|
||||||
"actual_qty",
|
"actual_qty",
|
||||||
"column_break_kyek",
|
"column_break_kyek",
|
||||||
@@ -255,6 +256,16 @@
|
|||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"report_hide": 1
|
"report_hide": 1
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "transferred_qty",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"label": "Transferred Qty (in Stock UOM)",
|
||||||
|
"no_copy": 1,
|
||||||
|
"print_hide": 1,
|
||||||
|
"read_only": 1,
|
||||||
|
"report_hide": 1
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "available_quantity_section",
|
"fieldname": "available_quantity_section",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
@@ -285,7 +296,7 @@
|
|||||||
],
|
],
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2026-03-17 16:25:10.358013",
|
"modified": "2026-07-06 18:17:18.000000",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Pick List Item",
|
"name": "Pick List Item",
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ class PickListItem(Document):
|
|||||||
stock_qty: DF.Float
|
stock_qty: DF.Float
|
||||||
stock_reserved_qty: DF.Float
|
stock_reserved_qty: DF.Float
|
||||||
stock_uom: DF.Link | None
|
stock_uom: DF.Link | None
|
||||||
|
transferred_qty: DF.Float
|
||||||
uom: DF.Link | None
|
uom: DF.Link | None
|
||||||
use_serial_batch_fields: DF.Check
|
use_serial_batch_fields: DF.Check
|
||||||
warehouse: DF.Link | None
|
warehouse: DF.Link | None
|
||||||
|
|||||||
@@ -178,6 +178,15 @@ class StockEntry(StockController, SubcontractingInwardController):
|
|||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
self.status_updater = [
|
||||||
|
{
|
||||||
|
"source_dt": "Stock Entry Detail",
|
||||||
|
"target_dt": "Pick List Item",
|
||||||
|
"join_field": "pick_list_item",
|
||||||
|
"target_field": "transferred_qty",
|
||||||
|
"source_field": "transfer_qty",
|
||||||
|
}
|
||||||
|
]
|
||||||
if self.purchase_order:
|
if self.purchase_order:
|
||||||
self.subcontract_data = frappe._dict(
|
self.subcontract_data = frappe._dict(
|
||||||
{
|
{
|
||||||
@@ -571,6 +580,7 @@ class StockEntry(StockController, SubcontractingInwardController):
|
|||||||
self.validate_closed_subcontracting_order()
|
self.validate_closed_subcontracting_order()
|
||||||
self.update_subcontract_order_supplied_items()
|
self.update_subcontract_order_supplied_items()
|
||||||
self.update_subcontracting_order_status()
|
self.update_subcontracting_order_status()
|
||||||
|
self.update_pick_list_status()
|
||||||
self.cancel_stock_reserve_for_wip_and_fg()
|
self.cancel_stock_reserve_for_wip_and_fg()
|
||||||
|
|
||||||
if self.work_order and self.purpose == "Material Consumption for Manufacture":
|
if self.work_order and self.purpose == "Material Consumption for Manufacture":
|
||||||
@@ -4054,6 +4064,9 @@ class StockEntry(StockController, SubcontractingInwardController):
|
|||||||
def update_pick_list_status(self):
|
def update_pick_list_status(self):
|
||||||
from erpnext.stock.doctype.pick_list.pick_list import update_pick_list_status
|
from erpnext.stock.doctype.pick_list.pick_list import update_pick_list_status
|
||||||
|
|
||||||
|
if self.pick_list:
|
||||||
|
self.update_qty()
|
||||||
|
|
||||||
update_pick_list_status(self.pick_list)
|
update_pick_list_status(self.pick_list)
|
||||||
|
|
||||||
def set_missing_values(self):
|
def set_missing_values(self):
|
||||||
|
|||||||
@@ -72,6 +72,7 @@
|
|||||||
"col_break6",
|
"col_break6",
|
||||||
"material_request",
|
"material_request",
|
||||||
"material_request_item",
|
"material_request_item",
|
||||||
|
"pick_list_item",
|
||||||
"original_item",
|
"original_item",
|
||||||
"reference_section",
|
"reference_section",
|
||||||
"against_stock_entry",
|
"against_stock_entry",
|
||||||
@@ -423,6 +424,16 @@
|
|||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "pick_list_item",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"hidden": 1,
|
||||||
|
"label": "Pick List Item",
|
||||||
|
"no_copy": 1,
|
||||||
|
"options": "Pick List Item",
|
||||||
|
"print_hide": 1,
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "original_item",
|
"fieldname": "original_item",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
@@ -678,7 +689,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2026-07-03 12:11:53.714931",
|
"modified": "2026-07-06 18:17:18.000000",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Stock Entry Detail",
|
"name": "Stock Entry Detail",
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ class StockEntryDetail(Document):
|
|||||||
parent: DF.Data
|
parent: DF.Data
|
||||||
parentfield: DF.Data
|
parentfield: DF.Data
|
||||||
parenttype: DF.Data
|
parenttype: DF.Data
|
||||||
|
pick_list_item: DF.Link | None
|
||||||
po_detail: DF.Data | None
|
po_detail: DF.Data | None
|
||||||
project: DF.Link | None
|
project: DF.Link | None
|
||||||
putaway_rule: DF.Link | None
|
putaway_rule: DF.Link | None
|
||||||
|
|||||||
Reference in New Issue
Block a user