test: test case to check workstation type
This commit is contained in:
parent
105c272816
commit
7bd06e6fbc
@ -5,7 +5,7 @@ import copy
|
||||
|
||||
import frappe
|
||||
from frappe.tests.utils import FrappeTestCase, change_settings, timeout
|
||||
from frappe.utils import add_days, add_months, cint, flt, now, today
|
||||
from frappe.utils import add_days, add_months, add_to_date, cint, flt, now, today
|
||||
|
||||
from erpnext.manufacturing.doctype.job_card.job_card import JobCardCancelError
|
||||
from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom
|
||||
@ -1480,6 +1480,166 @@ class TestWorkOrder(FrappeTestCase):
|
||||
for row in return_ste_doc.items:
|
||||
self.assertEqual(row.qty, 2)
|
||||
|
||||
def test_workstation_type_for_work_order(self):
|
||||
prepare_data_for_workstation_type_check()
|
||||
|
||||
workstation_types = ["Workstation Type 1", "Workstation Type 2", "Workstation Type 3"]
|
||||
planned_start_date = "2022-11-14 10:00:00"
|
||||
|
||||
wo_order = make_wo_order_test_record(
|
||||
item="Test FG Item For Workstation Type", planned_start_date=planned_start_date, qty=2
|
||||
)
|
||||
|
||||
job_cards = frappe.get_all(
|
||||
"Job Card",
|
||||
fields=[
|
||||
"`tabJob Card`.`name`",
|
||||
"`tabJob Card`.`workstation_type`",
|
||||
"`tabJob Card`.`workstation`",
|
||||
"`tabJob Card Time Log`.`from_time`",
|
||||
"`tabJob Card Time Log`.`to_time`",
|
||||
"`tabJob Card Time Log`.`time_in_mins`",
|
||||
],
|
||||
filters=[
|
||||
["Job Card", "work_order", "=", wo_order.name],
|
||||
["Job Card Time Log", "docstatus", "=", 1],
|
||||
],
|
||||
order_by="`tabJob Card`.`creation` desc",
|
||||
)
|
||||
|
||||
workstations_to_check = ["Workstation 1", "Workstation 3", "Workstation 5"]
|
||||
for index, row in enumerate(job_cards):
|
||||
if index != 0:
|
||||
planned_start_date = add_to_date(planned_start_date, minutes=40)
|
||||
|
||||
self.assertEqual(row.workstation_type, workstation_types[index])
|
||||
self.assertEqual(row.from_time, planned_start_date)
|
||||
self.assertEqual(row.to_time, add_to_date(planned_start_date, minutes=30))
|
||||
self.assertEqual(row.workstation, workstations_to_check[index])
|
||||
|
||||
planned_start_date = "2022-11-14 10:00:00"
|
||||
|
||||
wo_order = make_wo_order_test_record(
|
||||
item="Test FG Item For Workstation Type", planned_start_date=planned_start_date, qty=2
|
||||
)
|
||||
|
||||
job_cards = frappe.get_all(
|
||||
"Job Card",
|
||||
fields=[
|
||||
"`tabJob Card`.`name`",
|
||||
"`tabJob Card`.`workstation_type`",
|
||||
"`tabJob Card`.`workstation`",
|
||||
"`tabJob Card Time Log`.`from_time`",
|
||||
"`tabJob Card Time Log`.`to_time`",
|
||||
"`tabJob Card Time Log`.`time_in_mins`",
|
||||
],
|
||||
filters=[
|
||||
["Job Card", "work_order", "=", wo_order.name],
|
||||
["Job Card Time Log", "docstatus", "=", 1],
|
||||
],
|
||||
order_by="`tabJob Card`.`creation` desc",
|
||||
)
|
||||
|
||||
workstations_to_check = ["Workstation 2", "Workstation 4", "Workstation 6"]
|
||||
for index, row in enumerate(job_cards):
|
||||
if index != 0:
|
||||
planned_start_date = add_to_date(planned_start_date, minutes=40)
|
||||
|
||||
self.assertEqual(row.workstation_type, workstation_types[index])
|
||||
self.assertEqual(row.from_time, planned_start_date)
|
||||
self.assertEqual(row.to_time, add_to_date(planned_start_date, minutes=30))
|
||||
self.assertEqual(row.workstation, workstations_to_check[index])
|
||||
|
||||
|
||||
def prepare_data_for_workstation_type_check():
|
||||
from erpnext.manufacturing.doctype.operation.test_operation import make_operation
|
||||
from erpnext.manufacturing.doctype.workstation.test_workstation import make_workstation
|
||||
from erpnext.manufacturing.doctype.workstation_type.test_workstation_type import (
|
||||
create_workstation_type,
|
||||
)
|
||||
|
||||
workstation_types = ["Workstation Type 1", "Workstation Type 2", "Workstation Type 3"]
|
||||
for workstation_type in workstation_types:
|
||||
create_workstation_type(workstation_type=workstation_type)
|
||||
|
||||
operations = ["Cutting", "Sewing", "Packing"]
|
||||
for operation in operations:
|
||||
make_operation(
|
||||
{
|
||||
"operation": operation,
|
||||
}
|
||||
)
|
||||
|
||||
workstations = [
|
||||
{
|
||||
"workstation": "Workstation 1",
|
||||
"workstation_type": "Workstation Type 1",
|
||||
},
|
||||
{
|
||||
"workstation": "Workstation 2",
|
||||
"workstation_type": "Workstation Type 1",
|
||||
},
|
||||
{
|
||||
"workstation": "Workstation 3",
|
||||
"workstation_type": "Workstation Type 2",
|
||||
},
|
||||
{
|
||||
"workstation": "Workstation 4",
|
||||
"workstation_type": "Workstation Type 2",
|
||||
},
|
||||
{
|
||||
"workstation": "Workstation 5",
|
||||
"workstation_type": "Workstation Type 3",
|
||||
},
|
||||
{
|
||||
"workstation": "Workstation 6",
|
||||
"workstation_type": "Workstation Type 3",
|
||||
},
|
||||
]
|
||||
|
||||
for row in workstations:
|
||||
make_workstation(row)
|
||||
|
||||
fg_item = make_item(
|
||||
"Test FG Item For Workstation Type",
|
||||
{
|
||||
"is_stock_item": 1,
|
||||
},
|
||||
)
|
||||
|
||||
rm_item = make_item(
|
||||
"Test RM Item For Workstation Type",
|
||||
{
|
||||
"is_stock_item": 1,
|
||||
},
|
||||
)
|
||||
|
||||
if not frappe.db.exists("BOM", {"item": fg_item.name}):
|
||||
bom_doc = make_bom(
|
||||
item=fg_item.name,
|
||||
source_warehouse="Stores - _TC",
|
||||
raw_materials=[rm_item.name],
|
||||
do_not_submit=True,
|
||||
)
|
||||
|
||||
submit_bom = False
|
||||
for index, operation in enumerate(operations):
|
||||
if not frappe.db.exists("BOM Operation", {"parent": bom_doc.name, "operation": operation}):
|
||||
bom_doc.append(
|
||||
"operations",
|
||||
{
|
||||
"operation": operation,
|
||||
"time_in_mins": 30,
|
||||
"hour_rate": 100,
|
||||
"workstation_type": workstation_types[index],
|
||||
},
|
||||
)
|
||||
|
||||
submit_bom = True
|
||||
|
||||
if submit_bom:
|
||||
bom_doc.submit()
|
||||
|
||||
|
||||
def prepare_data_for_backflush_based_on_materials_transferred():
|
||||
batch_item_doc = make_item(
|
||||
|
@ -107,6 +107,7 @@ def make_workstation(*args, **kwargs):
|
||||
doc = frappe.get_doc({"doctype": "Workstation", "workstation_name": workstation_name})
|
||||
doc.hour_rate_rent = args.get("hour_rate_rent")
|
||||
doc.hour_rate_labour = args.get("hour_rate_labour")
|
||||
doc.workstation_type = args.get("workstation_type")
|
||||
doc.insert()
|
||||
|
||||
return doc
|
||||
|
@ -2,7 +2,7 @@
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
frappe.ui.form.on("Workstation", {
|
||||
onload: function(frm) {
|
||||
onload(frm) {
|
||||
if(frm.is_new())
|
||||
{
|
||||
frappe.call({
|
||||
@ -15,6 +15,18 @@ frappe.ui.form.on("Workstation", {
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
workstation_type(frm) {
|
||||
if (frm.doc.workstation_type) {
|
||||
frm.call({
|
||||
method: "set_data_based_on_workstation_type",
|
||||
doc: frm.doc,
|
||||
callback: function(r) {
|
||||
frm.refresh_fields();
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -32,7 +32,11 @@ class OverlapError(frappe.ValidationError):
|
||||
|
||||
|
||||
class Workstation(Document):
|
||||
def validate(self):
|
||||
def before_save(self):
|
||||
self.set_data_based_on_workstation_type()
|
||||
self.set_hour_rate()
|
||||
|
||||
def set_hour_rate(self):
|
||||
self.hour_rate = (
|
||||
flt(self.hour_rate_labour)
|
||||
+ flt(self.hour_rate_electricity)
|
||||
@ -40,6 +44,30 @@ class Workstation(Document):
|
||||
+ flt(self.hour_rate_rent)
|
||||
)
|
||||
|
||||
@frappe.whitelist()
|
||||
def set_data_based_on_workstation_type(self):
|
||||
if self.workstation_type:
|
||||
fields = [
|
||||
"hour_rate_labour",
|
||||
"hour_rate_electricity",
|
||||
"hour_rate_consumable",
|
||||
"hour_rate_rent",
|
||||
"hour_rate",
|
||||
"description",
|
||||
]
|
||||
|
||||
data = frappe.get_cached_value("Workstation Type", self.workstation_type, fields, as_dict=True)
|
||||
|
||||
if not data:
|
||||
return
|
||||
|
||||
for field in fields:
|
||||
if self.get(field):
|
||||
continue
|
||||
|
||||
if value := data.get(field):
|
||||
self.set(field, value)
|
||||
|
||||
def on_update(self):
|
||||
self.validate_overlap_for_operation_timings()
|
||||
self.update_bom_operation()
|
||||
|
@ -1,9 +1,21 @@
|
||||
# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
|
||||
# import frappe
|
||||
import frappe
|
||||
from frappe.tests.utils import FrappeTestCase
|
||||
|
||||
|
||||
class TestWorkstationType(FrappeTestCase):
|
||||
pass
|
||||
|
||||
|
||||
def create_workstation_type(**args):
|
||||
args = frappe._dict(args)
|
||||
|
||||
if workstation_type := frappe.db.exists("Workstation Type", args.workstation_type):
|
||||
return frappe.get_doc("Workstation Type", workstation_type)
|
||||
else:
|
||||
doc = frappe.new_doc("Workstation Type")
|
||||
doc.update(args)
|
||||
doc.insert()
|
||||
return doc
|
||||
|
@ -19,9 +19,7 @@
|
||||
"section_break_8",
|
||||
"hour_rate",
|
||||
"description_tab",
|
||||
"description",
|
||||
"holiday_tab",
|
||||
"holiday_list"
|
||||
"description"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
@ -81,12 +79,6 @@
|
||||
"oldfieldtype": "Currency",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "holiday_list",
|
||||
"fieldtype": "Link",
|
||||
"label": "Holiday List",
|
||||
"options": "Holiday List"
|
||||
},
|
||||
{
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Small Text",
|
||||
@ -106,11 +98,6 @@
|
||||
"fieldtype": "Tab Break",
|
||||
"label": "Description"
|
||||
},
|
||||
{
|
||||
"fieldname": "holiday_tab",
|
||||
"fieldtype": "Tab Break",
|
||||
"label": "Holiday"
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_8",
|
||||
"fieldtype": "Section Break"
|
||||
@ -118,7 +105,7 @@
|
||||
],
|
||||
"icon": "icon-wrench",
|
||||
"links": [],
|
||||
"modified": "2022-11-04 17:30:33.397719",
|
||||
"modified": "2022-11-16 23:11:36.224249",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Workstation Type",
|
||||
|
@ -3,10 +3,20 @@
|
||||
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import flt
|
||||
|
||||
|
||||
class WorkstationType(Document):
|
||||
pass
|
||||
def before_save(self):
|
||||
self.set_hour_rate()
|
||||
|
||||
def set_hour_rate(self):
|
||||
self.hour_rate = (
|
||||
flt(self.hour_rate_labour)
|
||||
+ flt(self.hour_rate_electricity)
|
||||
+ flt(self.hour_rate_consumable)
|
||||
+ flt(self.hour_rate_rent)
|
||||
)
|
||||
|
||||
|
||||
def get_workstations(workstation_type):
|
||||
|
@ -73,168 +73,6 @@
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Bill of Materials",
|
||||
"link_count": 0,
|
||||
"onboard": 0,
|
||||
"type": "Card Break"
|
||||
},
|
||||
{
|
||||
"dependencies": "",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Item",
|
||||
"link_count": 0,
|
||||
"link_to": "Item",
|
||||
"link_type": "DocType",
|
||||
"onboard": 1,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Item",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Bill of Materials",
|
||||
"link_count": 0,
|
||||
"link_to": "BOM",
|
||||
"link_type": "DocType",
|
||||
"onboard": 1,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Workstation",
|
||||
"link_count": 0,
|
||||
"link_to": "Workstation",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Operation",
|
||||
"link_count": 0,
|
||||
"link_to": "Operation",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Routing",
|
||||
"link_count": 0,
|
||||
"link_to": "Routing",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Work Order",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Production Planning Report",
|
||||
"link_count": 0,
|
||||
"link_to": "Production Planning Report",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Work Order",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Work Order Summary",
|
||||
"link_count": 0,
|
||||
"link_to": "Work Order Summary",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Quality Inspection",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Quality Inspection Summary",
|
||||
"link_count": 0,
|
||||
"link_to": "Quality Inspection Summary",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Downtime Entry",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Downtime Analysis",
|
||||
"link_count": 0,
|
||||
"link_to": "Downtime Analysis",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Job Card",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Job Card Summary",
|
||||
"link_count": 0,
|
||||
"link_to": "Job Card Summary",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "BOM",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "BOM Search",
|
||||
"link_count": 0,
|
||||
"link_to": "BOM Search",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "BOM",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "BOM Stock Report",
|
||||
"link_count": 0,
|
||||
"link_to": "BOM Stock Report",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Work Order",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Production Analytics",
|
||||
"link_count": 0,
|
||||
"link_to": "Production Analytics",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "BOM",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "BOM Operations Time",
|
||||
"link_count": 0,
|
||||
"link_to": "BOM Operations Time",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
@ -400,9 +238,181 @@
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Bill of Materials",
|
||||
"link_count": 15,
|
||||
"onboard": 0,
|
||||
"type": "Card Break"
|
||||
},
|
||||
{
|
||||
"dependencies": "",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Item",
|
||||
"link_count": 0,
|
||||
"link_to": "Item",
|
||||
"link_type": "DocType",
|
||||
"onboard": 1,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Item",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Bill of Materials",
|
||||
"link_count": 0,
|
||||
"link_to": "BOM",
|
||||
"link_type": "DocType",
|
||||
"onboard": 1,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Workstation Type",
|
||||
"link_count": 0,
|
||||
"link_to": "Workstation Type",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Workstation",
|
||||
"link_count": 0,
|
||||
"link_to": "Workstation",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Operation",
|
||||
"link_count": 0,
|
||||
"link_to": "Operation",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Work Order",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Routing",
|
||||
"link_count": 0,
|
||||
"link_to": "Routing",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Work Order",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Production Planning Report",
|
||||
"link_count": 0,
|
||||
"link_to": "Production Planning Report",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Quality Inspection",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Work Order Summary",
|
||||
"link_count": 0,
|
||||
"link_to": "Work Order Summary",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Downtime Entry",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Quality Inspection Summary",
|
||||
"link_count": 0,
|
||||
"link_to": "Quality Inspection Summary",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Job Card",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Downtime Analysis",
|
||||
"link_count": 0,
|
||||
"link_to": "Downtime Analysis",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "BOM",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Job Card Summary",
|
||||
"link_count": 0,
|
||||
"link_to": "Job Card Summary",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "BOM",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "BOM Search",
|
||||
"link_count": 0,
|
||||
"link_to": "BOM Search",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Work Order",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "BOM Stock Report",
|
||||
"link_count": 0,
|
||||
"link_to": "BOM Stock Report",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "BOM",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Production Analytics",
|
||||
"link_count": 0,
|
||||
"link_to": "Production Analytics",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "BOM Operations Time",
|
||||
"link_count": 0,
|
||||
"link_to": "BOM Operations Time",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
}
|
||||
],
|
||||
"modified": "2022-06-15 15:18:57.062935",
|
||||
"modified": "2022-11-14 14:53:34.616862",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "Manufacturing",
|
||||
|
Loading…
x
Reference in New Issue
Block a user