mirror of
https://github.com/frappe/erpnext.git
synced 2026-03-19 15:02:12 +00:00
* feat: Disassembly Order (#42655)
(cherry picked from commit 663a08e4cd)
# Conflicts:
# erpnext/stock/doctype/stock_entry_type/stock_entry_type.json
* chore: fix conflicts
---------
Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
This commit is contained in:
@@ -2053,6 +2053,55 @@ class TestWorkOrder(FrappeTestCase):
|
|||||||
"BOM",
|
"BOM",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_disassemby_order(self):
|
||||||
|
fg_item = "Test Disassembly Item"
|
||||||
|
source_warehouse = "Stores - _TC"
|
||||||
|
raw_materials = ["Test Disassembly RM Item 1", "Test Disassembly RM Item 2"]
|
||||||
|
|
||||||
|
make_item(fg_item, {"is_stock_item": 1})
|
||||||
|
for item in raw_materials:
|
||||||
|
make_item(item, {"is_stock_item": 1})
|
||||||
|
test_stock_entry.make_stock_entry(
|
||||||
|
item_code=item,
|
||||||
|
target=source_warehouse,
|
||||||
|
qty=1,
|
||||||
|
basic_rate=100,
|
||||||
|
)
|
||||||
|
|
||||||
|
make_bom(item=fg_item, source_warehouse=source_warehouse, raw_materials=raw_materials)
|
||||||
|
|
||||||
|
wo = make_wo_order_test_record(
|
||||||
|
item=fg_item,
|
||||||
|
qty=1,
|
||||||
|
source_warehouse=source_warehouse,
|
||||||
|
skip_transfer=1,
|
||||||
|
)
|
||||||
|
|
||||||
|
stock_entry = frappe.get_doc(make_stock_entry(wo.name, "Manufacture", 1))
|
||||||
|
for row in stock_entry.items:
|
||||||
|
if row.item_code in raw_materials:
|
||||||
|
row.s_warehouse = source_warehouse
|
||||||
|
|
||||||
|
stock_entry.submit()
|
||||||
|
|
||||||
|
wo.reload()
|
||||||
|
self.assertEqual(wo.status, "Completed")
|
||||||
|
|
||||||
|
stock_entry = frappe.get_doc(make_stock_entry(wo.name, "Disassemble", 1))
|
||||||
|
stock_entry.save()
|
||||||
|
|
||||||
|
self.assertEqual(stock_entry.purpose, "Disassemble")
|
||||||
|
|
||||||
|
for row in stock_entry.items:
|
||||||
|
if row.item_code == fg_item:
|
||||||
|
self.assertTrue(row.s_warehouse)
|
||||||
|
self.assertFalse(row.t_warehouse)
|
||||||
|
else:
|
||||||
|
self.assertFalse(row.s_warehouse)
|
||||||
|
self.assertTrue(row.t_warehouse)
|
||||||
|
|
||||||
|
stock_entry.submit()
|
||||||
|
|
||||||
|
|
||||||
def make_operation(**kwargs):
|
def make_operation(**kwargs):
|
||||||
kwargs = frappe._dict(kwargs)
|
kwargs = frappe._dict(kwargs)
|
||||||
@@ -2370,6 +2419,7 @@ def make_wo_order_test_record(**args):
|
|||||||
wo_order.batch_size = args.batch_size or 0
|
wo_order.batch_size = args.batch_size or 0
|
||||||
|
|
||||||
if args.source_warehouse:
|
if args.source_warehouse:
|
||||||
|
wo_order.source_warehouse = args.source_warehouse
|
||||||
for item in wo_order.get("required_items"):
|
for item in wo_order.get("required_items"):
|
||||||
item.source_warehouse = args.source_warehouse
|
item.source_warehouse = args.source_warehouse
|
||||||
|
|
||||||
|
|||||||
@@ -183,13 +183,30 @@ frappe.ui.form.on("Work Order", {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (frm.doc.status == "Completed") {
|
||||||
|
if (frm.doc.__onload.backflush_raw_materials_based_on == "Material Transferred for Manufacture") {
|
||||||
|
frm.add_custom_button(
|
||||||
|
__("BOM"),
|
||||||
|
() => {
|
||||||
|
frm.trigger("make_bom");
|
||||||
|
},
|
||||||
|
__("Create")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
frm.doc.status == "Completed" &&
|
frm.doc.docstatus === 1 &&
|
||||||
frm.doc.__onload.backflush_raw_materials_based_on == "Material Transferred for Manufacture"
|
["Closed", "Completed"].includes(frm.doc.status) &&
|
||||||
|
frm.doc.produced_qty > 0
|
||||||
) {
|
) {
|
||||||
frm.add_custom_button(__("Create BOM"), () => {
|
frm.add_custom_button(
|
||||||
frm.trigger("make_bom");
|
__("Disassembly Order"),
|
||||||
});
|
() => {
|
||||||
|
frm.trigger("make_disassembly_order");
|
||||||
|
},
|
||||||
|
__("Create")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
frm.trigger("add_custom_button_to_return_components");
|
frm.trigger("add_custom_button_to_return_components");
|
||||||
@@ -337,6 +354,23 @@ frappe.ui.form.on("Work Order", {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
make_disassembly_order(frm) {
|
||||||
|
erpnext.work_order
|
||||||
|
.show_prompt_for_qty_input(frm, "Disassemble")
|
||||||
|
.then((data) => {
|
||||||
|
return frappe.xcall("erpnext.manufacturing.doctype.work_order.work_order.make_stock_entry", {
|
||||||
|
work_order_id: frm.doc.name,
|
||||||
|
purpose: "Disassemble",
|
||||||
|
qty: data.qty,
|
||||||
|
target_warehouse: data.target_warehouse,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then((stock_entry) => {
|
||||||
|
frappe.model.sync(stock_entry);
|
||||||
|
frappe.set_route("Form", stock_entry.doctype, stock_entry.name);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
show_progress_for_items: function (frm) {
|
show_progress_for_items: function (frm) {
|
||||||
var bars = [];
|
var bars = [];
|
||||||
var message = "";
|
var message = "";
|
||||||
@@ -745,6 +779,10 @@ erpnext.work_order = {
|
|||||||
|
|
||||||
get_max_transferable_qty: (frm, purpose) => {
|
get_max_transferable_qty: (frm, purpose) => {
|
||||||
let max = 0;
|
let max = 0;
|
||||||
|
if (purpose === "Disassemble") {
|
||||||
|
return flt(frm.doc.produced_qty);
|
||||||
|
}
|
||||||
|
|
||||||
if (frm.doc.skip_transfer) {
|
if (frm.doc.skip_transfer) {
|
||||||
max = flt(frm.doc.qty) - flt(frm.doc.produced_qty);
|
max = flt(frm.doc.qty) - flt(frm.doc.produced_qty);
|
||||||
} else {
|
} else {
|
||||||
@@ -759,15 +797,38 @@ erpnext.work_order = {
|
|||||||
|
|
||||||
show_prompt_for_qty_input: function (frm, purpose) {
|
show_prompt_for_qty_input: function (frm, purpose) {
|
||||||
let max = this.get_max_transferable_qty(frm, purpose);
|
let max = this.get_max_transferable_qty(frm, purpose);
|
||||||
|
|
||||||
|
let fields = [
|
||||||
|
{
|
||||||
|
fieldtype: "Float",
|
||||||
|
label: __("Qty for {0}", [__(purpose)]),
|
||||||
|
fieldname: "qty",
|
||||||
|
description: __("Max: {0}", [max]),
|
||||||
|
default: max,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
if (purpose === "Disassemble") {
|
||||||
|
fields.push({
|
||||||
|
fieldtype: "Link",
|
||||||
|
options: "Warehouse",
|
||||||
|
fieldname: "target_warehouse",
|
||||||
|
label: __("Target Warehouse"),
|
||||||
|
default: frm.doc.source_warehouse || frm.doc.wip_warehouse,
|
||||||
|
get_query() {
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
company: frm.doc.company,
|
||||||
|
is_group: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
frappe.prompt(
|
frappe.prompt(
|
||||||
{
|
fields,
|
||||||
fieldtype: "Float",
|
|
||||||
label: __("Qty for {0}", [__(purpose)]),
|
|
||||||
fieldname: "qty",
|
|
||||||
description: __("Max: {0}", [max]),
|
|
||||||
default: max,
|
|
||||||
},
|
|
||||||
(data) => {
|
(data) => {
|
||||||
max += (frm.doc.qty * (frm.doc.__onload.overproduction_percentage || 0.0)) / 100;
|
max += (frm.doc.qty * (frm.doc.__onload.overproduction_percentage || 0.0)) / 100;
|
||||||
|
|
||||||
|
|||||||
@@ -1359,7 +1359,7 @@ def set_work_order_ops(name):
|
|||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def make_stock_entry(work_order_id, purpose, qty=None):
|
def make_stock_entry(work_order_id, purpose, qty=None, target_warehouse=None):
|
||||||
work_order = frappe.get_doc("Work Order", work_order_id)
|
work_order = frappe.get_doc("Work Order", work_order_id)
|
||||||
if not frappe.db.get_value("Warehouse", work_order.wip_warehouse, "is_group"):
|
if not frappe.db.get_value("Warehouse", work_order.wip_warehouse, "is_group"):
|
||||||
wip_warehouse = work_order.wip_warehouse
|
wip_warehouse = work_order.wip_warehouse
|
||||||
@@ -1389,9 +1389,16 @@ def make_stock_entry(work_order_id, purpose, qty=None):
|
|||||||
stock_entry.to_warehouse = work_order.fg_warehouse
|
stock_entry.to_warehouse = work_order.fg_warehouse
|
||||||
stock_entry.project = work_order.project
|
stock_entry.project = work_order.project
|
||||||
|
|
||||||
|
if purpose == "Disassemble":
|
||||||
|
stock_entry.from_warehouse = work_order.fg_warehouse
|
||||||
|
stock_entry.to_warehouse = target_warehouse or work_order.source_warehouse
|
||||||
|
|
||||||
stock_entry.set_stock_entry_type()
|
stock_entry.set_stock_entry_type()
|
||||||
stock_entry.get_items()
|
stock_entry.get_items()
|
||||||
stock_entry.set_serial_no_batch_for_finished_good()
|
|
||||||
|
if purpose != "Disassemble":
|
||||||
|
stock_entry.set_serial_no_batch_for_finished_good()
|
||||||
|
|
||||||
return stock_entry.as_dict()
|
return stock_entry.as_dict()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -372,4 +372,5 @@ erpnext.patches.v15_0.update_asset_repair_field_in_stock_entry
|
|||||||
erpnext.patches.v15_0.update_total_number_of_booked_depreciations
|
erpnext.patches.v15_0.update_total_number_of_booked_depreciations
|
||||||
erpnext.patches.v15_0.do_not_use_batchwise_valuation
|
erpnext.patches.v15_0.do_not_use_batchwise_valuation
|
||||||
erpnext.patches.v15_0.drop_index_posting_datetime_from_sle
|
erpnext.patches.v15_0.drop_index_posting_datetime_from_sle
|
||||||
|
erpnext.patches.v15_0.add_disassembly_order_stock_entry_type #1
|
||||||
erpnext.patches.v15_0.set_standard_stock_entry_type
|
erpnext.patches.v15_0.set_standard_stock_entry_type
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import frappe
|
||||||
|
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
if not frappe.db.exists("Stock Entry Type", "Disassemble"):
|
||||||
|
frappe.get_doc(
|
||||||
|
{
|
||||||
|
"doctype": "Stock Entry Type",
|
||||||
|
"name": "Disassemble",
|
||||||
|
"purpose": "Disassemble",
|
||||||
|
"is_standard": 1,
|
||||||
|
}
|
||||||
|
).insert(ignore_permissions=True)
|
||||||
@@ -11,6 +11,7 @@ def execute():
|
|||||||
"Manufacture",
|
"Manufacture",
|
||||||
"Repack",
|
"Repack",
|
||||||
"Send to Subcontractor",
|
"Send to Subcontractor",
|
||||||
|
"Disassemble",
|
||||||
]:
|
]:
|
||||||
if frappe.db.exists("Stock Entry Type", stock_entry_type):
|
if frappe.db.exists("Stock Entry Type", stock_entry_type):
|
||||||
frappe.db.set_value("Stock Entry Type", stock_entry_type, "is_standard", 1)
|
frappe.db.set_value("Stock Entry Type", stock_entry_type, "is_standard", 1)
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ def install(country=None):
|
|||||||
"purpose": "Repack",
|
"purpose": "Repack",
|
||||||
"is_standard": 1,
|
"is_standard": 1,
|
||||||
},
|
},
|
||||||
|
{"doctype": "Stock Entry Type", "name": "Disassemble", "purpose": "Disassemble", "is_standard": 1},
|
||||||
{
|
{
|
||||||
"doctype": "Stock Entry Type",
|
"doctype": "Stock Entry Type",
|
||||||
"name": "Send to Subcontractor",
|
"name": "Send to Subcontractor",
|
||||||
|
|||||||
@@ -127,7 +127,7 @@
|
|||||||
"label": "Purpose",
|
"label": "Purpose",
|
||||||
"oldfieldname": "purpose",
|
"oldfieldname": "purpose",
|
||||||
"oldfieldtype": "Select",
|
"oldfieldtype": "Select",
|
||||||
"options": "Material Issue\nMaterial Receipt\nMaterial Transfer\nMaterial Transfer for Manufacture\nMaterial Consumption for Manufacture\nManufacture\nRepack\nSend to Subcontractor",
|
"options": "Material Issue\nMaterial Receipt\nMaterial Transfer\nMaterial Transfer for Manufacture\nMaterial Consumption for Manufacture\nManufacture\nRepack\nSend to Subcontractor\nDisassemble",
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"search_index": 1
|
"search_index": 1
|
||||||
},
|
},
|
||||||
@@ -143,7 +143,7 @@
|
|||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "eval:in_list([\"Material Transfer for Manufacture\", \"Manufacture\", \"Material Consumption for Manufacture\"], doc.purpose)",
|
"depends_on": "eval:in_list([\"Material Transfer for Manufacture\", \"Manufacture\", \"Material Consumption for Manufacture\", \"Disassemble\"], doc.purpose)",
|
||||||
"fieldname": "work_order",
|
"fieldname": "work_order",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Work Order",
|
"label": "Work Order",
|
||||||
@@ -242,7 +242,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "0",
|
"default": "0",
|
||||||
"depends_on": "eval:in_list([\"Material Issue\", \"Material Transfer\", \"Manufacture\", \"Repack\", \"Send to Subcontractor\", \"Material Transfer for Manufacture\", \"Material Consumption for Manufacture\"], doc.purpose)",
|
"depends_on": "eval:in_list([\"Material Issue\", \"Material Transfer\", \"Manufacture\", \"Repack\", \"Send to Subcontractor\", \"Material Transfer for Manufacture\", \"Material Consumption for Manufacture\", \"Disassemble\"], doc.purpose)",
|
||||||
"fieldname": "from_bom",
|
"fieldname": "from_bom",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "From BOM",
|
"label": "From BOM",
|
||||||
@@ -697,7 +697,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2024-08-13 19:02:42.386955",
|
"modified": "2024-08-13 19:05:42.386955",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Stock Entry",
|
"name": "Stock Entry",
|
||||||
|
|||||||
@@ -132,6 +132,7 @@ class StockEntry(StockController):
|
|||||||
"Manufacture",
|
"Manufacture",
|
||||||
"Repack",
|
"Repack",
|
||||||
"Send to Subcontractor",
|
"Send to Subcontractor",
|
||||||
|
"Disassemble",
|
||||||
]
|
]
|
||||||
remarks: DF.Text | None
|
remarks: DF.Text | None
|
||||||
sales_invoice_no: DF.Link | None
|
sales_invoice_no: DF.Link | None
|
||||||
@@ -337,6 +338,7 @@ class StockEntry(StockController):
|
|||||||
"Repack",
|
"Repack",
|
||||||
"Send to Subcontractor",
|
"Send to Subcontractor",
|
||||||
"Material Consumption for Manufacture",
|
"Material Consumption for Manufacture",
|
||||||
|
"Disassemble",
|
||||||
]
|
]
|
||||||
|
|
||||||
if self.purpose not in valid_purposes:
|
if self.purpose not in valid_purposes:
|
||||||
@@ -616,6 +618,7 @@ class StockEntry(StockController):
|
|||||||
"Manufacture",
|
"Manufacture",
|
||||||
"Material Transfer for Manufacture",
|
"Material Transfer for Manufacture",
|
||||||
"Material Consumption for Manufacture",
|
"Material Consumption for Manufacture",
|
||||||
|
"Disassemble",
|
||||||
):
|
):
|
||||||
# check if work order is entered
|
# check if work order is entered
|
||||||
|
|
||||||
@@ -1703,11 +1706,63 @@ class StockEntry(StockController):
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def get_items_for_disassembly(self):
|
||||||
|
"""Get items for Disassembly Order"""
|
||||||
|
|
||||||
|
if not self.work_order:
|
||||||
|
frappe.throw(_("The Work Order is mandatory for Disassembly Order"))
|
||||||
|
|
||||||
|
items = self.get_items_from_manufacture_entry()
|
||||||
|
|
||||||
|
s_warehouse = ""
|
||||||
|
if self.work_order:
|
||||||
|
s_warehouse = frappe.db.get_value("Work Order", self.work_order, "fg_warehouse")
|
||||||
|
|
||||||
|
for row in items:
|
||||||
|
child_row = self.append("items", {})
|
||||||
|
for field, value in row.items():
|
||||||
|
if value is not None:
|
||||||
|
child_row.set(field, value)
|
||||||
|
|
||||||
|
child_row.s_warehouse = (self.from_warehouse or s_warehouse) if row.is_finished_item else ""
|
||||||
|
child_row.t_warehouse = self.to_warehouse if not row.is_finished_item else ""
|
||||||
|
child_row.is_finished_item = 0 if row.is_finished_item else 1
|
||||||
|
|
||||||
|
def get_items_from_manufacture_entry(self):
|
||||||
|
return frappe.get_all(
|
||||||
|
"Stock Entry",
|
||||||
|
fields=[
|
||||||
|
"`tabStock Entry Detail`.`item_code`",
|
||||||
|
"`tabStock Entry Detail`.`item_name`",
|
||||||
|
"`tabStock Entry Detail`.`description`",
|
||||||
|
"`tabStock Entry Detail`.`qty`",
|
||||||
|
"`tabStock Entry Detail`.`transfer_qty`",
|
||||||
|
"`tabStock Entry Detail`.`stock_uom`",
|
||||||
|
"`tabStock Entry Detail`.`uom`",
|
||||||
|
"`tabStock Entry Detail`.`basic_rate`",
|
||||||
|
"`tabStock Entry Detail`.`conversion_factor`",
|
||||||
|
"`tabStock Entry Detail`.`is_finished_item`",
|
||||||
|
"`tabStock Entry Detail`.`batch_no`",
|
||||||
|
"`tabStock Entry Detail`.`serial_no`",
|
||||||
|
"`tabStock Entry Detail`.`use_serial_batch_fields`",
|
||||||
|
],
|
||||||
|
filters=[
|
||||||
|
["Stock Entry", "purpose", "=", "Manufacture"],
|
||||||
|
["Stock Entry", "work_order", "=", self.work_order],
|
||||||
|
["Stock Entry", "docstatus", "=", 1],
|
||||||
|
["Stock Entry Detail", "docstatus", "=", 1],
|
||||||
|
],
|
||||||
|
order_by="`tabStock Entry Detail`.`idx` desc, `tabStock Entry Detail`.`is_finished_item` desc",
|
||||||
|
)
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_items(self):
|
def get_items(self):
|
||||||
self.set("items", [])
|
self.set("items", [])
|
||||||
self.validate_work_order()
|
self.validate_work_order()
|
||||||
|
|
||||||
|
if self.purpose == "Disassemble":
|
||||||
|
return self.get_items_for_disassembly()
|
||||||
|
|
||||||
if not self.posting_date or not self.posting_time:
|
if not self.posting_date or not self.posting_time:
|
||||||
frappe.throw(_("Posting date and posting time is mandatory"))
|
frappe.throw(_("Posting date and posting time is mandatory"))
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Purpose",
|
"label": "Purpose",
|
||||||
"options": "\nMaterial Issue\nMaterial Receipt\nMaterial Transfer\nMaterial Transfer for Manufacture\nMaterial Consumption for Manufacture\nManufacture\nRepack\nSend to Subcontractor",
|
"options": "\nMaterial Issue\nMaterial Receipt\nMaterial Transfer\nMaterial Transfer for Manufacture\nMaterial Consumption for Manufacture\nManufacture\nRepack\nSend to Subcontractor\nDisassemble",
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"set_only_once": 1
|
"set_only_once": 1
|
||||||
},
|
},
|
||||||
@@ -37,10 +37,11 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2024-08-20 15:35:45.696958",
|
"modified": "2024-08-24 16:00:22.696958",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Stock Entry Type",
|
"name": "Stock Entry Type",
|
||||||
|
"naming_rule": "Set by user",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ class StockEntryType(Document):
|
|||||||
"Manufacture",
|
"Manufacture",
|
||||||
"Repack",
|
"Repack",
|
||||||
"Send to Subcontractor",
|
"Send to Subcontractor",
|
||||||
|
"Disassemble",
|
||||||
]
|
]
|
||||||
# end: auto-generated types
|
# end: auto-generated types
|
||||||
|
|
||||||
@@ -45,5 +46,6 @@ class StockEntryType(Document):
|
|||||||
"Manufacture",
|
"Manufacture",
|
||||||
"Repack",
|
"Repack",
|
||||||
"Send to Subcontractor",
|
"Send to Subcontractor",
|
||||||
|
"Disassemble",
|
||||||
]:
|
]:
|
||||||
frappe.throw(f"Stock Entry Type {self.name} cannot be set as standard")
|
frappe.throw(f"Stock Entry Type {self.name} cannot be set as standard")
|
||||||
|
|||||||
Reference in New Issue
Block a user