mirror of
https://github.com/frappe/erpnext.git
synced 2026-04-29 11:38:32 +00:00
feat: option to enable serial / batch features
(cherry picked from commit 82c3da5b1e)
# Conflicts:
# erpnext/patches.txt
This commit is contained in:
committed by
Mergify
parent
83f2fadbcf
commit
93a597410e
@@ -16,6 +16,7 @@ erpnext.assets.AssetCapitalization = class AssetCapitalization extends erpnext.s
|
|||||||
|
|
||||||
refresh() {
|
refresh() {
|
||||||
this.show_general_ledger();
|
this.show_general_ledger();
|
||||||
|
erpnext.toggle_serial_batch_fields(this.frm);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(this.frm.doc.stock_items && this.frm.doc.stock_items.length) ||
|
(this.frm.doc.stock_items && this.frm.doc.stock_items.length) ||
|
||||||
|
|||||||
@@ -468,4 +468,8 @@ erpnext.patches.v15_0.replace_http_with_https_in_sales_partner
|
|||||||
erpnext.patches.v15_0.delete_quotation_lost_record_detail
|
erpnext.patches.v15_0.delete_quotation_lost_record_detail
|
||||||
erpnext.patches.v16_0.add_portal_redirects
|
erpnext.patches.v16_0.add_portal_redirects
|
||||||
erpnext.patches.v16_0.complete_onboarding_steps_for_older_sites #2
|
erpnext.patches.v16_0.complete_onboarding_steps_for_older_sites #2
|
||||||
|
<<<<<<< HEAD
|
||||||
erpnext.patches.v16_0.update_order_qty_and_requested_qty_based_on_mr_and_po
|
erpnext.patches.v16_0.update_order_qty_and_requested_qty_based_on_mr_and_po
|
||||||
|
=======
|
||||||
|
erpnext.patches.v16_0.enable_serial_batch_setting
|
||||||
|
>>>>>>> 82c3da5b1e (feat: option to enable serial / batch features)
|
||||||
|
|||||||
9
erpnext/patches/v16_0/enable_serial_batch_setting.py
Normal file
9
erpnext/patches/v16_0/enable_serial_batch_setting.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import frappe
|
||||||
|
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
if not frappe.get_all("Serial No", limit=1) and not frappe.get_all("Batch", limit=1):
|
||||||
|
return
|
||||||
|
|
||||||
|
frappe.db.set_single_value("Stock Settings", "enable_serial_and_batch_no_for_item", 1)
|
||||||
|
frappe.db.set_default("enable_serial_and_batch_no_for_item", 1)
|
||||||
@@ -580,6 +580,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
|
|||||||
this.validate_has_items();
|
this.validate_has_items();
|
||||||
erpnext.utils.view_serial_batch_nos(this.frm);
|
erpnext.utils.view_serial_batch_nos(this.frm);
|
||||||
this.set_route_options_for_new_doc();
|
this.set_route_options_for_new_doc();
|
||||||
|
erpnext.toggle_serial_batch_fields(this.frm);
|
||||||
}
|
}
|
||||||
|
|
||||||
set_route_options_for_new_doc() {
|
set_route_options_for_new_doc() {
|
||||||
|
|||||||
@@ -19,6 +19,71 @@ $.extend(erpnext, {
|
|||||||
return currency_list;
|
return currency_list;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
toggle_serial_batch_fields(frm) {
|
||||||
|
let hide_fields = cint(frappe.user_defaults?.enable_serial_and_batch_no_for_item) === 0 ? 1 : 0;
|
||||||
|
let fields = ["serial_and_batch_bundle", "use_serial_batch_fields", "serial_no", "batch_no"];
|
||||||
|
|
||||||
|
if (
|
||||||
|
[
|
||||||
|
"Stock Entry",
|
||||||
|
"Purchase Receipt",
|
||||||
|
"Purchase Invoice",
|
||||||
|
"Stock Reconciliation",
|
||||||
|
"Subcontracting Receipt",
|
||||||
|
].includes(frm.doc.doctype)
|
||||||
|
) {
|
||||||
|
fields.push("add_serial_batch_bundle");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (["Stock Reconciliation"].includes(frm.doc.doctype)) {
|
||||||
|
fields.push("reconcile_all_serial_batch");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (["Sales Invoice", "Delivery Note", "Pick List"].includes(frm.doc.doctype)) {
|
||||||
|
fields.push("pick_serial_and_batch");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (["Purchase Receipt", "Purchase Invoice", "Subcontracting Receipt"].includes(frm.doc.doctype)) {
|
||||||
|
fields.push("add_serial_batch_for_rejected_qty", "rejected_serial_and_batch_bundle");
|
||||||
|
}
|
||||||
|
|
||||||
|
let child_name = "items";
|
||||||
|
if (frm.doc.doctype === "Pick List") {
|
||||||
|
child_name = "locations";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frm.doc.doctype === "Asset Capitalization") {
|
||||||
|
child_name = "stock_items";
|
||||||
|
}
|
||||||
|
|
||||||
|
fields.forEach((field) => {
|
||||||
|
frm.fields_dict[child_name].grid.update_docfield_property(field, "hidden", hide_fields);
|
||||||
|
|
||||||
|
frm.fields_dict[child_name].grid.update_docfield_property(
|
||||||
|
field,
|
||||||
|
"in_list_view",
|
||||||
|
hide_fields ? 0 : 1
|
||||||
|
);
|
||||||
|
|
||||||
|
if (
|
||||||
|
frm.doc.doctype === "Subcontracting Receipt" &&
|
||||||
|
!["add_serial_batch_for_rejected_qty", "rejected_serial_and_batch_bundle"].includes(field)
|
||||||
|
) {
|
||||||
|
frm.fields_dict["supplied_items"].grid.update_docfield_property(field, "hidden", hide_fields);
|
||||||
|
|
||||||
|
frm.fields_dict["supplied_items"].grid.update_docfield_property(
|
||||||
|
field,
|
||||||
|
"in_list_view",
|
||||||
|
hide_fields ? 0 : 1
|
||||||
|
);
|
||||||
|
|
||||||
|
frm.fields_dict["supplied_items"].grid.reset_grid();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
frm.fields_dict[child_name].grid.reset_grid();
|
||||||
|
},
|
||||||
|
|
||||||
toggle_naming_series: function () {
|
toggle_naming_series: function () {
|
||||||
if (
|
if (
|
||||||
cur_frm &&
|
cur_frm &&
|
||||||
|
|||||||
@@ -221,6 +221,8 @@ def set_defaults_for_tests():
|
|||||||
frappe.db.set_default(key, value)
|
frappe.db.set_default(key, value)
|
||||||
frappe.db.set_single_value("Stock Settings", "auto_insert_price_list_rate_if_missing", 0)
|
frappe.db.set_single_value("Stock Settings", "auto_insert_price_list_rate_if_missing", 0)
|
||||||
|
|
||||||
|
frappe.db.set_single_value("Stock Settings", "enable_serial_and_batch_no_for_item", 1)
|
||||||
|
|
||||||
|
|
||||||
def insert_record(records):
|
def insert_record(records):
|
||||||
from frappe.desk.page.setup_wizard.setup_wizard import make_records
|
from frappe.desk.page.setup_wizard.setup_wizard import make_records
|
||||||
|
|||||||
@@ -84,7 +84,25 @@ frappe.ui.form.on("Item", {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
toggle_has_serial_batch_fields(frm) {
|
||||||
|
let hide_fields = cint(frappe.user_defaults?.enable_serial_and_batch_no_for_item) === 0 ? 1 : 0;
|
||||||
|
|
||||||
|
frm.toggle_display(["serial_no_series", "batch_number_series", "create_new_batch"], !hide_fields);
|
||||||
|
frm.toggle_enable(["has_serial_no", "has_batch_no"], !hide_fields);
|
||||||
|
|
||||||
|
if (hide_fields) {
|
||||||
|
let description = __(
|
||||||
|
"To enable the Serial No and Batch No feature, please check the 'Enable Serial / Batch No for Item' checkbox in Stock Settings."
|
||||||
|
);
|
||||||
|
|
||||||
|
frm.set_df_property("has_serial_no", "description", description);
|
||||||
|
frm.set_df_property("has_batch_no", "description", description);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
refresh: function (frm) {
|
refresh: function (frm) {
|
||||||
|
frm.trigger("toggle_has_serial_batch_fields");
|
||||||
|
|
||||||
if (frm.doc.is_stock_item) {
|
if (frm.doc.is_stock_item) {
|
||||||
frm.add_custom_button(
|
frm.add_custom_button(
|
||||||
__("Stock Balance"),
|
__("Stock Balance"),
|
||||||
|
|||||||
@@ -452,6 +452,7 @@
|
|||||||
"fieldname": "batch_number_series",
|
"fieldname": "batch_number_series",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"label": "Batch Number Series",
|
"label": "Batch Number Series",
|
||||||
|
"show_description_on_click": 1,
|
||||||
"translatable": 1
|
"translatable": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -493,7 +494,8 @@
|
|||||||
"description": "Example: ABCD.#####\nIf series is set and Serial No is not mentioned in transactions, then automatic serial number will be created based on this series. If you always want to explicitly mention Serial Nos for this item. leave this blank.",
|
"description": "Example: ABCD.#####\nIf series is set and Serial No is not mentioned in transactions, then automatic serial number will be created based on this series. If you always want to explicitly mention Serial Nos for this item. leave this blank.",
|
||||||
"fieldname": "serial_no_series",
|
"fieldname": "serial_no_series",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"label": "Serial Number Series"
|
"label": "Serial Number Series",
|
||||||
|
"show_description_on_click": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"collapsible": 1,
|
"collapsible": 1,
|
||||||
@@ -985,7 +987,7 @@
|
|||||||
"image_field": "image",
|
"image_field": "image",
|
||||||
"links": [],
|
"links": [],
|
||||||
"make_attachments_public": 1,
|
"make_attachments_public": 1,
|
||||||
"modified": "2026-02-05 17:20:35.605734",
|
"modified": "2026-03-05 16:29:31.653447",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Item",
|
"name": "Item",
|
||||||
|
|||||||
@@ -218,6 +218,7 @@ class Item(Document):
|
|||||||
self.validate_auto_reorder_enabled_in_stock_settings()
|
self.validate_auto_reorder_enabled_in_stock_settings()
|
||||||
self.cant_change()
|
self.cant_change()
|
||||||
self.validate_item_tax_net_rate_range()
|
self.validate_item_tax_net_rate_range()
|
||||||
|
self.validate_allow_to_set_serial_batch()
|
||||||
|
|
||||||
if not self.is_new():
|
if not self.is_new():
|
||||||
self.old_item_group = frappe.db.get_value(self.doctype, self.name, "item_group")
|
self.old_item_group = frappe.db.get_value(self.doctype, self.name, "item_group")
|
||||||
@@ -226,6 +227,18 @@ class Item(Document):
|
|||||||
self.update_variants()
|
self.update_variants()
|
||||||
self.update_item_price()
|
self.update_item_price()
|
||||||
|
|
||||||
|
def validate_allow_to_set_serial_batch(self):
|
||||||
|
if not self.has_serial_no and not self.has_batch_no:
|
||||||
|
return
|
||||||
|
|
||||||
|
if not frappe.db.get_single_value("Stock Settings", "enable_serial_and_batch_no_for_item"):
|
||||||
|
frappe.throw(
|
||||||
|
_(
|
||||||
|
"Please check the 'Enable Serial and Batch No for Item' checkbox in the {0} to set Serial No or Batch No for the item."
|
||||||
|
).format(get_link_to_form("Stock Settings", "Stock Settings")),
|
||||||
|
title=_("Serial and Batch No for Item Disabled"),
|
||||||
|
)
|
||||||
|
|
||||||
def validate_description(self):
|
def validate_description(self):
|
||||||
"""Clean HTML description if set"""
|
"""Clean HTML description if set"""
|
||||||
if (
|
if (
|
||||||
|
|||||||
@@ -119,6 +119,8 @@ frappe.ui.form.on("Pick List", {
|
|||||||
refresh: (frm) => {
|
refresh: (frm) => {
|
||||||
frm.trigger("add_get_items_button");
|
frm.trigger("add_get_items_button");
|
||||||
frm.trigger("update_warehouse_property");
|
frm.trigger("update_warehouse_property");
|
||||||
|
erpnext.toggle_serial_batch_fields(frm);
|
||||||
|
|
||||||
if (frm.doc.docstatus === 1) {
|
if (frm.doc.docstatus === 1) {
|
||||||
const status_completed = frm.doc.status === "Completed";
|
const status_completed = frm.doc.status === "Completed";
|
||||||
|
|
||||||
|
|||||||
@@ -107,6 +107,7 @@ class SerialandBatchBundle(Document):
|
|||||||
self.autoname()
|
self.autoname()
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
|
self.validate_allow_to_set_serial_batch()
|
||||||
if self.docstatus == 1 and self.voucher_detail_no:
|
if self.docstatus == 1 and self.voucher_detail_no:
|
||||||
self.validate_voucher_detail_no()
|
self.validate_voucher_detail_no()
|
||||||
|
|
||||||
@@ -143,6 +144,15 @@ class SerialandBatchBundle(Document):
|
|||||||
self.calculate_qty_and_amount()
|
self.calculate_qty_and_amount()
|
||||||
self.set_child_details()
|
self.set_child_details()
|
||||||
|
|
||||||
|
def validate_allow_to_set_serial_batch(self):
|
||||||
|
if not frappe.db.get_single_value("Stock Settings", "enable_serial_and_batch_no_for_item"):
|
||||||
|
frappe.throw(
|
||||||
|
_(
|
||||||
|
"Please check the 'Enable Serial and Batch No for Item' checkbox in the {0} to make Serial and Batch Bundle for the item."
|
||||||
|
).format(get_link_to_form("Stock Settings", "Stock Settings")),
|
||||||
|
title=_("Serial and Batch No for Item Disabled"),
|
||||||
|
)
|
||||||
|
|
||||||
def validate_serial_no_status(self):
|
def validate_serial_no_status(self):
|
||||||
serial_nos = [d.serial_no for d in self.entries if d.serial_no]
|
serial_nos = [d.serial_no for d in self.entries if d.serial_no]
|
||||||
invalid_serial_nos = frappe.get_all(
|
invalid_serial_nos = frappe.get_all(
|
||||||
|
|||||||
@@ -245,6 +245,7 @@ frappe.ui.form.on("Stock Entry", {
|
|||||||
refresh: function (frm) {
|
refresh: function (frm) {
|
||||||
frm.trigger("get_items_from_transit_entry");
|
frm.trigger("get_items_from_transit_entry");
|
||||||
frm.trigger("toggle_warehouse_fields");
|
frm.trigger("toggle_warehouse_fields");
|
||||||
|
erpnext.toggle_serial_batch_fields(frm);
|
||||||
|
|
||||||
if (!frm.doc.docstatus && !frm.doc.subcontracting_inward_order) {
|
if (!frm.doc.docstatus && !frm.doc.subcontracting_inward_order) {
|
||||||
frm.trigger("validate_purpose_consumption");
|
frm.trigger("validate_purpose_consumption");
|
||||||
|
|||||||
@@ -76,6 +76,8 @@ frappe.ui.form.on("Stock Reconciliation", {
|
|||||||
},
|
},
|
||||||
|
|
||||||
refresh: function (frm) {
|
refresh: function (frm) {
|
||||||
|
erpnext.toggle_serial_batch_fields(frm);
|
||||||
|
|
||||||
if (frm.doc.docstatus < 1) {
|
if (frm.doc.docstatus < 1) {
|
||||||
frm.add_custom_button(__("Fetch Items from Warehouse"), function () {
|
frm.add_custom_button(__("Fetch Items from Warehouse"), function () {
|
||||||
frm.events.get_items(frm);
|
frm.events.get_items(frm);
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
"allow_internal_transfer_at_arms_length_price",
|
"allow_internal_transfer_at_arms_length_price",
|
||||||
"validate_material_transfer_warehouses",
|
"validate_material_transfer_warehouses",
|
||||||
"serial_and_batch_item_settings_tab",
|
"serial_and_batch_item_settings_tab",
|
||||||
|
"enable_serial_and_batch_no_for_item",
|
||||||
"section_break_7",
|
"section_break_7",
|
||||||
"allow_existing_serial_no",
|
"allow_existing_serial_no",
|
||||||
"do_not_use_batchwise_valuation",
|
"do_not_use_batchwise_valuation",
|
||||||
@@ -48,9 +49,8 @@
|
|||||||
"use_serial_batch_fields",
|
"use_serial_batch_fields",
|
||||||
"do_not_update_serial_batch_on_creation_of_auto_bundle",
|
"do_not_update_serial_batch_on_creation_of_auto_bundle",
|
||||||
"allow_negative_stock_for_batch",
|
"allow_negative_stock_for_batch",
|
||||||
"serial_and_batch_bundle_section",
|
|
||||||
"set_serial_and_batch_bundle_naming_based_on_naming_series",
|
|
||||||
"section_break_gnhq",
|
"section_break_gnhq",
|
||||||
|
"set_serial_and_batch_bundle_naming_based_on_naming_series",
|
||||||
"use_naming_series",
|
"use_naming_series",
|
||||||
"column_break_wslv",
|
"column_break_wslv",
|
||||||
"naming_series_prefix",
|
"naming_series_prefix",
|
||||||
@@ -158,6 +158,7 @@
|
|||||||
"label": "Convert Item Description to Clean HTML in Transactions"
|
"label": "Convert Item Description to Clean HTML in Transactions"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"depends_on": "enable_serial_and_batch_no_for_item",
|
||||||
"fieldname": "section_break_7",
|
"fieldname": "section_break_7",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Serial & Batch Item Settings"
|
"label": "Serial & Batch Item Settings"
|
||||||
@@ -487,11 +488,6 @@
|
|||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Auto Reserve Stock"
|
"label": "Auto Reserve Stock"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "serial_and_batch_bundle_section",
|
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"label": "Serial and Batch Bundle"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"default": "0",
|
"default": "0",
|
||||||
"fieldname": "set_serial_and_batch_bundle_naming_based_on_naming_series",
|
"fieldname": "set_serial_and_batch_bundle_naming_based_on_naming_series",
|
||||||
@@ -499,6 +495,7 @@
|
|||||||
"label": "Set Serial and Batch Bundle Naming Based on Naming Series"
|
"label": "Set Serial and Batch Bundle Naming Based on Naming Series"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"depends_on": "enable_serial_and_batch_no_for_item",
|
||||||
"fieldname": "section_break_gnhq",
|
"fieldname": "section_break_gnhq",
|
||||||
"fieldtype": "Section Break"
|
"fieldtype": "Section Break"
|
||||||
},
|
},
|
||||||
@@ -554,6 +551,11 @@
|
|||||||
"fieldname": "allow_negative_stock_for_batch",
|
"fieldname": "allow_negative_stock_for_batch",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Allow Negative Stock for Batch"
|
"label": "Allow Negative Stock for Batch"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "enable_serial_and_batch_no_for_item",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Enable Serial / Batch No for Item"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"hide_toolbar": 1,
|
"hide_toolbar": 1,
|
||||||
@@ -562,7 +564,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2026-02-25 09:56:34.105949",
|
"modified": "2026-02-25 10:56:34.105949",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Stock Settings",
|
"name": "Stock Settings",
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ class StockSettings(Document):
|
|||||||
disable_serial_no_and_batch_selector: DF.Check
|
disable_serial_no_and_batch_selector: DF.Check
|
||||||
do_not_update_serial_batch_on_creation_of_auto_bundle: DF.Check
|
do_not_update_serial_batch_on_creation_of_auto_bundle: DF.Check
|
||||||
do_not_use_batchwise_valuation: DF.Check
|
do_not_use_batchwise_valuation: DF.Check
|
||||||
|
enable_serial_and_batch_no_for_item: DF.Check
|
||||||
enable_stock_reservation: DF.Check
|
enable_stock_reservation: DF.Check
|
||||||
item_group: DF.Link | None
|
item_group: DF.Link | None
|
||||||
item_naming_by: DF.Literal["Item Code", "Naming Series"]
|
item_naming_by: DF.Literal["Item Code", "Naming Series"]
|
||||||
@@ -82,6 +83,7 @@ class StockSettings(Document):
|
|||||||
"default_warehouse",
|
"default_warehouse",
|
||||||
"set_qty_in_transactions_based_on_serial_no_input",
|
"set_qty_in_transactions_based_on_serial_no_input",
|
||||||
"use_serial_batch_fields",
|
"use_serial_batch_fields",
|
||||||
|
"enable_serial_and_batch_no_for_item",
|
||||||
"set_serial_and_batch_bundle_naming_based_on_naming_series",
|
"set_serial_and_batch_bundle_naming_based_on_naming_series",
|
||||||
]:
|
]:
|
||||||
frappe.db.set_default(key, self.get(key, ""))
|
frappe.db.set_default(key, self.get(key, ""))
|
||||||
@@ -104,6 +106,7 @@ class StockSettings(Document):
|
|||||||
)
|
)
|
||||||
|
|
||||||
self.validate_warehouses()
|
self.validate_warehouses()
|
||||||
|
self.validate_serial_and_batch_no_settings()
|
||||||
self.cant_change_valuation_method()
|
self.cant_change_valuation_method()
|
||||||
self.validate_clean_description_html()
|
self.validate_clean_description_html()
|
||||||
self.validate_pending_reposts()
|
self.validate_pending_reposts()
|
||||||
@@ -112,6 +115,25 @@ class StockSettings(Document):
|
|||||||
self.change_precision_for_for_sales()
|
self.change_precision_for_for_sales()
|
||||||
self.change_precision_for_purchase()
|
self.change_precision_for_purchase()
|
||||||
|
|
||||||
|
def validate_serial_and_batch_no_settings(self):
|
||||||
|
doc_before_save = self.get_doc_before_save()
|
||||||
|
if not doc_before_save:
|
||||||
|
return
|
||||||
|
|
||||||
|
if doc_before_save.enable_serial_and_batch_no_for_item == self.enable_serial_and_batch_no_for_item:
|
||||||
|
return
|
||||||
|
|
||||||
|
if (
|
||||||
|
doc_before_save.enable_serial_and_batch_no_for_item
|
||||||
|
and not self.enable_serial_and_batch_no_for_item
|
||||||
|
):
|
||||||
|
if frappe.get_all("Serial and Batch Bundle", filters={"docstatus": 1}, limit=1, pluck="name"):
|
||||||
|
frappe.throw(
|
||||||
|
_(
|
||||||
|
"Cannot disable Serial and Batch No for Item, as there are existing records for serial / batch."
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def validate_warehouses(self):
|
def validate_warehouses(self):
|
||||||
warehouse_fields = ["default_warehouse", "sample_retention_warehouse"]
|
warehouse_fields = ["default_warehouse", "sample_retention_warehouse"]
|
||||||
for field in warehouse_fields:
|
for field in warehouse_fields:
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ frappe.ui.form.on("Subcontracting Receipt", {
|
|||||||
refresh: (frm) => {
|
refresh: (frm) => {
|
||||||
frappe.dynamic_link = { doc: frm.doc, fieldname: "supplier", doctype: "Supplier" };
|
frappe.dynamic_link = { doc: frm.doc, fieldname: "supplier", doctype: "Supplier" };
|
||||||
|
|
||||||
|
erpnext.toggle_serial_batch_fields(frm);
|
||||||
if (frm.doc.docstatus === 1) {
|
if (frm.doc.docstatus === 1) {
|
||||||
frm.add_custom_button(
|
frm.add_custom_button(
|
||||||
__("Stock Ledger"),
|
__("Stock Ledger"),
|
||||||
|
|||||||
Reference in New Issue
Block a user