mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-01 19:29:10 +00:00
refactor: rename field against_pick_list
This commit is contained in:
@@ -265,7 +265,8 @@ frappe.ui.form.on('Pick List', {
|
|||||||
from_date: moment(frm.doc.creation).format('YYYY-MM-DD'),
|
from_date: moment(frm.doc.creation).format('YYYY-MM-DD'),
|
||||||
to_date: to_date,
|
to_date: to_date,
|
||||||
voucher_type: "Sales Order",
|
voucher_type: "Sales Order",
|
||||||
against_pick_list: frm.doc.name,
|
from_voucher_type: "Pick List",
|
||||||
|
from_voucher_no: frm.doc.name,
|
||||||
}
|
}
|
||||||
frappe.set_route("query-report", "Reserved Stock");
|
frappe.set_route("query-report", "Reserved Stock");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -242,7 +242,7 @@ class PickList(Document):
|
|||||||
for so, locations in so_details.items():
|
for so, locations in so_details.items():
|
||||||
so_doc = frappe.get_doc("Sales Order", so)
|
so_doc = frappe.get_doc("Sales Order", so)
|
||||||
create_stock_reservation_entries_for_so_items(
|
create_stock_reservation_entries_for_so_items(
|
||||||
sales_order=so_doc, items_details=locations, against_pick_list=True, notify=notify
|
sales_order=so_doc, items_details=locations, from_voucher_type="Pick List", notify=notify
|
||||||
)
|
)
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
@@ -253,7 +253,9 @@ class PickList(Document):
|
|||||||
cancel_stock_reservation_entries,
|
cancel_stock_reservation_entries,
|
||||||
)
|
)
|
||||||
|
|
||||||
cancel_stock_reservation_entries(against_pick_list=self.name, notify=notify)
|
cancel_stock_reservation_entries(
|
||||||
|
from_voucher_type="Pick List", from_voucher_no=self.name, notify=notify
|
||||||
|
)
|
||||||
|
|
||||||
def validate_picked_qty(self, data):
|
def validate_picked_qty(self, data):
|
||||||
over_delivery_receipt_allowance = 100 + flt(
|
over_delivery_receipt_allowance = 100 + flt(
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ def get_data():
|
|||||||
return {
|
return {
|
||||||
"fieldname": "pick_list",
|
"fieldname": "pick_list",
|
||||||
"non_standard_fieldnames": {
|
"non_standard_fieldnames": {
|
||||||
"Stock Reservation Entry": "against_pick_list",
|
"Stock Reservation Entry": "from_voucher_no",
|
||||||
},
|
},
|
||||||
"internal_links": {
|
"internal_links": {
|
||||||
"Sales Order": ["locations", "sales_order"],
|
"Sales Order": ["locations", "sales_order"],
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ frappe.ui.form.on('Stock Reservation Entry', {
|
|||||||
'qty', 'read_only', frm.doc.has_serial_no
|
'qty', 'read_only', frm.doc.has_serial_no
|
||||||
);
|
);
|
||||||
|
|
||||||
frm.set_df_property('sb_entries', 'allow_on_submit', frm.doc.against_pick_list ? 0 : 1);
|
frm.set_df_property('sb_entries', 'allow_on_submit', frm.doc.from_voucher_type == "Pick List" ? 0 : 1);
|
||||||
},
|
},
|
||||||
|
|
||||||
hide_rate_related_fields(frm) {
|
hide_rate_related_fields(frm) {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
"voucher_detail_no",
|
"voucher_detail_no",
|
||||||
"column_break_7dxj",
|
"column_break_7dxj",
|
||||||
"from_voucher_type",
|
"from_voucher_type",
|
||||||
"against_pick_list",
|
"from_voucher_no",
|
||||||
"from_voucher_detail_no",
|
"from_voucher_detail_no",
|
||||||
"section_break_xt4m",
|
"section_break_xt4m",
|
||||||
"stock_uom",
|
"stock_uom",
|
||||||
@@ -159,7 +159,7 @@
|
|||||||
"oldfieldname": "actual_qty",
|
"oldfieldname": "actual_qty",
|
||||||
"oldfieldtype": "Currency",
|
"oldfieldtype": "Currency",
|
||||||
"print_width": "150px",
|
"print_width": "150px",
|
||||||
"read_only_depends_on": "eval: ((doc.reservation_based_on == \"Serial and Batch\") || (doc.against_pick_list) || (doc.delivered_qty > 0))",
|
"read_only_depends_on": "eval: ((doc.reservation_based_on == \"Serial and Batch\") || (doc.from_voucher_type == \"Pick List\") || (doc.delivered_qty > 0))",
|
||||||
"width": "150px"
|
"width": "150px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -269,18 +269,7 @@
|
|||||||
"label": "Reservation Based On",
|
"label": "Reservation Based On",
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"options": "Qty\nSerial and Batch",
|
"options": "Qty\nSerial and Batch",
|
||||||
"read_only_depends_on": "eval: (doc.delivered_qty > 0 || doc.against_pick_list)"
|
"read_only_depends_on": "eval: (doc.delivered_qty > 0 || doc.from_voucher_type == \"Pick List\")"
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "against_pick_list",
|
|
||||||
"fieldtype": "Dynamic Link",
|
|
||||||
"label": "From Voucher No",
|
|
||||||
"no_copy": 1,
|
|
||||||
"options": "from_voucher_type",
|
|
||||||
"print_hide": 1,
|
|
||||||
"read_only": 1,
|
|
||||||
"report_hide": 1,
|
|
||||||
"search_index": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "column_break_7dxj",
|
"fieldname": "column_break_7dxj",
|
||||||
@@ -308,6 +297,17 @@
|
|||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"report_hide": 1
|
"report_hide": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "from_voucher_no",
|
||||||
|
"fieldtype": "Dynamic Link",
|
||||||
|
"label": "From Voucher No",
|
||||||
|
"no_copy": 1,
|
||||||
|
"options": "from_voucher_type",
|
||||||
|
"print_hide": 1,
|
||||||
|
"read_only": 1,
|
||||||
|
"report_hide": 1,
|
||||||
|
"search_index": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"hide_toolbar": 1,
|
"hide_toolbar": 1,
|
||||||
@@ -315,7 +315,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-10-19 16:26:46.598043",
|
"modified": "2023-10-19 16:41:16.545416",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Stock Reservation Entry",
|
"name": "Stock Reservation Entry",
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
|
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
# For license information, please see license.txt
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
from typing import Literal
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
@@ -113,7 +115,7 @@ class StockReservationEntry(Document):
|
|||||||
"""Auto pick Serial and Batch Nos to reserve when `Reservation Based On` is `Serial and Batch`."""
|
"""Auto pick Serial and Batch Nos to reserve when `Reservation Based On` is `Serial and Batch`."""
|
||||||
|
|
||||||
if (
|
if (
|
||||||
not self.against_pick_list
|
not self.from_voucher_type
|
||||||
and (self.get("_action") == "submit")
|
and (self.get("_action") == "submit")
|
||||||
and (self.has_serial_no or self.has_batch_no)
|
and (self.has_serial_no or self.has_batch_no)
|
||||||
and cint(frappe.db.get_single_value("Stock Settings", "auto_reserve_serial_and_batch"))
|
and cint(frappe.db.get_single_value("Stock Settings", "auto_reserve_serial_and_batch"))
|
||||||
@@ -317,7 +319,7 @@ class StockReservationEntry(Document):
|
|||||||
"""Updates total reserved qty in the Pick List."""
|
"""Updates total reserved qty in the Pick List."""
|
||||||
|
|
||||||
if (
|
if (
|
||||||
self.from_voucher_type == "Pick List" and self.against_pick_list and self.from_voucher_detail_no
|
self.from_voucher_type == "Pick List" and self.from_voucher_no and self.from_voucher_detail_no
|
||||||
):
|
):
|
||||||
sre = frappe.qb.DocType("Stock Reservation Entry")
|
sre = frappe.qb.DocType("Stock Reservation Entry")
|
||||||
reserved_qty = (
|
reserved_qty = (
|
||||||
@@ -326,7 +328,7 @@ class StockReservationEntry(Document):
|
|||||||
.where(
|
.where(
|
||||||
(sre.docstatus == 1)
|
(sre.docstatus == 1)
|
||||||
& (sre.from_voucher_type == "Pick List")
|
& (sre.from_voucher_type == "Pick List")
|
||||||
& (sre.against_pick_list == self.against_pick_list)
|
& (sre.from_voucher_no == self.from_voucher_no)
|
||||||
& (sre.from_voucher_detail_no == self.from_voucher_detail_no)
|
& (sre.from_voucher_detail_no == self.from_voucher_detail_no)
|
||||||
)
|
)
|
||||||
).run(as_list=True)[0][0] or 0
|
).run(as_list=True)[0][0] or 0
|
||||||
@@ -368,7 +370,7 @@ class StockReservationEntry(Document):
|
|||||||
).format(self.status, self.doctype)
|
).format(self.status, self.doctype)
|
||||||
frappe.throw(msg)
|
frappe.throw(msg)
|
||||||
|
|
||||||
if self.against_pick_list:
|
if self.from_voucher_type == "Pick List":
|
||||||
msg = _(
|
msg = _(
|
||||||
"Stock Reservation Entry created against a Pick List cannot be updated. If you need to make changes, we recommend canceling the existing entry and creating a new one."
|
"Stock Reservation Entry created against a Pick List cannot be updated. If you need to make changes, we recommend canceling the existing entry and creating a new one."
|
||||||
)
|
)
|
||||||
@@ -766,14 +768,14 @@ def has_reserved_stock(voucher_type: str, voucher_no: str, voucher_detail_no: st
|
|||||||
def create_stock_reservation_entries_for_so_items(
|
def create_stock_reservation_entries_for_so_items(
|
||||||
sales_order: object,
|
sales_order: object,
|
||||||
items_details: list[dict] = None,
|
items_details: list[dict] = None,
|
||||||
against_pick_list: bool = False,
|
from_voucher_type: Literal["Pick List", "Purchase Receipt"] = None,
|
||||||
notify=True,
|
notify=True,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Creates Stock Reservation Entries for Sales Order Items."""
|
"""Creates Stock Reservation Entries for Sales Order Items."""
|
||||||
|
|
||||||
from erpnext.selling.doctype.sales_order.sales_order import get_unreserved_qty
|
from erpnext.selling.doctype.sales_order.sales_order import get_unreserved_qty
|
||||||
|
|
||||||
if not against_pick_list and (
|
if not from_voucher_type and (
|
||||||
sales_order.get("_action") == "submit"
|
sales_order.get("_action") == "submit"
|
||||||
and sales_order.set_warehouse
|
and sales_order.set_warehouse
|
||||||
and cint(frappe.get_cached_value("Warehouse", sales_order.set_warehouse, "is_group"))
|
and cint(frappe.get_cached_value("Warehouse", sales_order.set_warehouse, "is_group"))
|
||||||
@@ -792,20 +794,20 @@ def create_stock_reservation_entries_for_so_items(
|
|||||||
|
|
||||||
items = []
|
items = []
|
||||||
if items_details:
|
if items_details:
|
||||||
item_field = "sales_order_item" if against_pick_list else "name"
|
item_field = "sales_order_item" if from_voucher_type == "Pick List" else "name"
|
||||||
|
|
||||||
for item in items_details:
|
for item in items_details:
|
||||||
so_item = frappe.get_doc("Sales Order Item", item.get(item_field))
|
so_item = frappe.get_doc("Sales Order Item", item.get(item_field))
|
||||||
so_item.warehouse = item.get("warehouse")
|
so_item.warehouse = item.get("warehouse")
|
||||||
so_item.qty_to_reserve = (
|
so_item.qty_to_reserve = (
|
||||||
item.get("picked_qty") - item.get("stock_reserved_qty", 0)
|
item.get("picked_qty") - item.get("stock_reserved_qty", 0)
|
||||||
if against_pick_list
|
if from_voucher_type == "Pick List"
|
||||||
else (flt(item.get("qty_to_reserve")) * flt(so_item.conversion_factor, 1))
|
else (flt(item.get("qty_to_reserve")) * flt(so_item.conversion_factor, 1))
|
||||||
)
|
)
|
||||||
so_item.serial_and_batch_bundle = item.get("serial_and_batch_bundle")
|
so_item.serial_and_batch_bundle = item.get("serial_and_batch_bundle")
|
||||||
|
|
||||||
if against_pick_list:
|
if from_voucher_type == "Pick List":
|
||||||
so_item.pick_list = item.get("parent")
|
so_item.from_voucher_no = item.get("parent")
|
||||||
so_item.from_voucher_detail_no = item.get("name")
|
so_item.from_voucher_detail_no = item.get("name")
|
||||||
|
|
||||||
items.append(so_item)
|
items.append(so_item)
|
||||||
@@ -819,7 +821,7 @@ def create_stock_reservation_entries_for_so_items(
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
# Stock should be reserved from the Pick List if has Picked Qty.
|
# Stock should be reserved from the Pick List if has Picked Qty.
|
||||||
if not against_pick_list and flt(item.picked_qty) > 0:
|
if not from_voucher_type == "Pick List" and flt(item.picked_qty) > 0:
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
_("Row #{0}: Item {1} has been picked, please reserve stock from the Pick List.").format(
|
_("Row #{0}: Item {1} has been picked, please reserve stock from the Pick List.").format(
|
||||||
item.idx, frappe.bold(item.item_code)
|
item.idx, frappe.bold(item.item_code)
|
||||||
@@ -929,9 +931,9 @@ def create_stock_reservation_entries_for_so_items(
|
|||||||
sre.stock_uom = item.stock_uom
|
sre.stock_uom = item.stock_uom
|
||||||
sre.project = sales_order.project
|
sre.project = sales_order.project
|
||||||
|
|
||||||
if against_pick_list:
|
if from_voucher_type:
|
||||||
sre.from_voucher_type = "Pick List"
|
sre.from_voucher_type = from_voucher_type
|
||||||
sre.against_pick_list = item.pick_list
|
sre.from_voucher_no = item.from_voucher_no
|
||||||
sre.from_voucher_detail_no = item.from_voucher_detail_no
|
sre.from_voucher_detail_no = item.from_voucher_detail_no
|
||||||
|
|
||||||
if item.serial_and_batch_bundle:
|
if item.serial_and_batch_bundle:
|
||||||
@@ -961,29 +963,37 @@ def cancel_stock_reservation_entries(
|
|||||||
voucher_type: str = None,
|
voucher_type: str = None,
|
||||||
voucher_no: str = None,
|
voucher_no: str = None,
|
||||||
voucher_detail_no: str = None,
|
voucher_detail_no: str = None,
|
||||||
against_pick_list: str = None,
|
from_voucher_type: Literal["Pick List", "Purchase Receipt"] = None,
|
||||||
|
from_voucher_no: str = None,
|
||||||
|
from_voucher_detail_no: str = None,
|
||||||
sre_list: list[dict] = None,
|
sre_list: list[dict] = None,
|
||||||
notify: bool = True,
|
notify: bool = True,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Cancel Stock Reservation Entries."""
|
"""Cancel Stock Reservation Entries."""
|
||||||
|
|
||||||
if not sre_list and against_pick_list:
|
if not sre_list:
|
||||||
sre = frappe.qb.DocType("Stock Reservation Entry")
|
if voucher_type and voucher_no:
|
||||||
sre_list = (
|
sre_list = get_stock_reservation_entries_for_voucher(
|
||||||
frappe.qb.from_(sre)
|
voucher_type, voucher_no, voucher_detail_no, fields=["name"]
|
||||||
.select(sre.name)
|
)
|
||||||
.where(
|
elif from_voucher_type and from_voucher_no:
|
||||||
(sre.docstatus == 1)
|
sre = frappe.qb.DocType("Stock Reservation Entry")
|
||||||
& (sre.against_pick_list == against_pick_list)
|
query = (
|
||||||
& (sre.status.notin(["Delivered", "Cancelled"]))
|
frappe.qb.from_(sre)
|
||||||
|
.select(sre.name)
|
||||||
|
.where(
|
||||||
|
(sre.docstatus == 1)
|
||||||
|
& (sre.from_voucher_type == from_voucher_type)
|
||||||
|
& (sre.from_voucher_no == from_voucher_no)
|
||||||
|
& (sre.status.notin(["Delivered", "Cancelled"]))
|
||||||
|
)
|
||||||
|
.orderby(sre.creation)
|
||||||
)
|
)
|
||||||
.orderby(sre.creation)
|
|
||||||
).run(as_dict=True)
|
|
||||||
|
|
||||||
elif not sre_list and (voucher_type and voucher_no):
|
if from_voucher_detail_no:
|
||||||
sre_list = get_stock_reservation_entries_for_voucher(
|
query = query.where(sre.from_voucher_detail_no == from_voucher_detail_no)
|
||||||
voucher_type, voucher_no, voucher_detail_no, fields=["name"]
|
|
||||||
)
|
sre_list = query.run(as_dict=True)
|
||||||
|
|
||||||
if sre_list:
|
if sre_list:
|
||||||
for sre in sre_list:
|
for sre in sre_list:
|
||||||
|
|||||||
@@ -556,7 +556,7 @@ class TestStockReservationEntry(FrappeTestCase):
|
|||||||
& (sre.voucher_no == location.sales_order)
|
& (sre.voucher_no == location.sales_order)
|
||||||
& (sre.voucher_detail_no == location.sales_order_item)
|
& (sre.voucher_detail_no == location.sales_order_item)
|
||||||
& (sre.from_voucher_type == "Pick List")
|
& (sre.from_voucher_type == "Pick List")
|
||||||
& (sre.against_pick_list == pl.name)
|
& (sre.from_voucher_no == pl.name)
|
||||||
& (sre.from_voucher_detail_no == location.name)
|
& (sre.from_voucher_detail_no == location.name)
|
||||||
)
|
)
|
||||||
).run(as_dict=True)
|
).run(as_dict=True)
|
||||||
|
|||||||
@@ -91,16 +91,30 @@ frappe.query_reports["Reserved Stock"] = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fieldname: "against_pick_list",
|
fieldname: "from_voucher_type",
|
||||||
label: __("Against Pick List"),
|
label: __("From Voucher Type"),
|
||||||
fieldtype: "Link",
|
fieldtype: "Link",
|
||||||
options: "Pick List",
|
options: "DocType",
|
||||||
|
get_query: () => ({
|
||||||
|
filters: {
|
||||||
|
name: ["in", ["Pick List", "Purchase Receipt"]],
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldname: "from_voucher_no",
|
||||||
|
label: __("From Voucher No"),
|
||||||
|
fieldtype: "Dynamic Link",
|
||||||
|
options: "from_voucher_type",
|
||||||
get_query: () => ({
|
get_query: () => ({
|
||||||
filters: {
|
filters: {
|
||||||
docstatus: 1,
|
docstatus: 1,
|
||||||
company: frappe.query_report.get_filter_value("company"),
|
company: frappe.query_report.get_filter_value("company"),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
get_options: function () {
|
||||||
|
return frappe.query_report.get_filter_value("from_voucher_type");
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fieldname: "reservation_based_on",
|
fieldname: "reservation_based_on",
|
||||||
|
|||||||
@@ -44,7 +44,8 @@ def get_data(filters):
|
|||||||
(sre.available_qty - sre.reserved_qty).as_("available_qty"),
|
(sre.available_qty - sre.reserved_qty).as_("available_qty"),
|
||||||
sre.voucher_type,
|
sre.voucher_type,
|
||||||
sre.voucher_no,
|
sre.voucher_no,
|
||||||
sre.against_pick_list,
|
sre.from_voucher_type,
|
||||||
|
sre.from_voucher_no,
|
||||||
sre.name.as_("stock_reservation_entry"),
|
sre.name.as_("stock_reservation_entry"),
|
||||||
sre.status,
|
sre.status,
|
||||||
sre.project,
|
sre.project,
|
||||||
@@ -65,7 +66,8 @@ def get_data(filters):
|
|||||||
"warehouse",
|
"warehouse",
|
||||||
"voucher_type",
|
"voucher_type",
|
||||||
"voucher_no",
|
"voucher_no",
|
||||||
"against_pick_list",
|
"from_voucher_type",
|
||||||
|
"from_voucher_no",
|
||||||
"reservation_based_on",
|
"reservation_based_on",
|
||||||
"status",
|
"status",
|
||||||
"project",
|
"project",
|
||||||
@@ -142,7 +144,6 @@ def get_columns():
|
|||||||
"fieldname": "voucher_type",
|
"fieldname": "voucher_type",
|
||||||
"label": _("Voucher Type"),
|
"label": _("Voucher Type"),
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"options": "Warehouse",
|
|
||||||
"width": 110,
|
"width": 110,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -153,11 +154,17 @@ def get_columns():
|
|||||||
"width": 120,
|
"width": 120,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "against_pick_list",
|
"fieldname": "from_voucher_type",
|
||||||
"label": _("Against Pick List"),
|
"label": _("From Voucher Type"),
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Data",
|
||||||
"options": "Pick List",
|
"width": 110,
|
||||||
"width": 130,
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "from_voucher_no",
|
||||||
|
"label": _("From Voucher No"),
|
||||||
|
"fieldtype": "Dynamic Link",
|
||||||
|
"options": "from_voucher_type",
|
||||||
|
"width": 120,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "stock_reservation_entry",
|
"fieldname": "stock_reservation_entry",
|
||||||
|
|||||||
Reference in New Issue
Block a user