mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-20 21:49:18 +00:00
fix: plant floor design changes
This commit is contained in:
@@ -90,69 +90,10 @@ frappe.ui.form.on("BOM Creator", {
|
|||||||
},
|
},
|
||||||
{ fieldtype: "Section Break" },
|
{ fieldtype: "Section Break" },
|
||||||
{
|
{
|
||||||
label: __("Track Operations"),
|
label: __("Routing"),
|
||||||
fieldtype: "Check",
|
|
||||||
fieldname: "track_operations",
|
|
||||||
onchange: (r) => {
|
|
||||||
let track_operations = dialog.get_value("track_operations");
|
|
||||||
if (r.type === "input" && !track_operations) {
|
|
||||||
dialog.set_value("track_semi_finished_goods", 0);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ fieldtype: "Column Break" },
|
|
||||||
{
|
|
||||||
label: __("Track Semi Finished Goods"),
|
|
||||||
fieldtype: "Check",
|
|
||||||
fieldname: "track_semi_finished_goods",
|
|
||||||
depends_on: "eval:doc.track_operations",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldtype: "Section Break",
|
|
||||||
label: __("Final Product Operation"),
|
|
||||||
depends_on: "eval:doc.track_semi_finished_goods",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: __("Operation"),
|
|
||||||
fieldtype: "Link",
|
fieldtype: "Link",
|
||||||
fieldname: "operation",
|
fieldname: "routing",
|
||||||
options: "Operation",
|
options: "Routing",
|
||||||
default: "Assembly",
|
|
||||||
mandatory_depends_on: "eval:doc.track_semi_finished_goods",
|
|
||||||
depends_on: "eval:doc.track_semi_finished_goods",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: __("Operation Time (in mins)"),
|
|
||||||
fieldtype: "Float",
|
|
||||||
fieldname: "operation_time",
|
|
||||||
mandatory_depends_on: "eval:doc.track_semi_finished_goods",
|
|
||||||
depends_on: "eval:doc.track_semi_finished_goods",
|
|
||||||
},
|
|
||||||
{ fieldtype: "Column Break" },
|
|
||||||
{
|
|
||||||
label: __("Workstation Type"),
|
|
||||||
fieldtype: "Link",
|
|
||||||
fieldname: "workstation_type",
|
|
||||||
options: "Workstation",
|
|
||||||
depends_on: "eval:doc.track_semi_finished_goods",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: __("Workstation"),
|
|
||||||
fieldtype: "Link",
|
|
||||||
fieldname: "workstation",
|
|
||||||
options: "Workstation",
|
|
||||||
depends_on: "eval:doc.track_semi_finished_goods",
|
|
||||||
get_query() {
|
|
||||||
let workstation_type = dialog.get_value("workstation_type");
|
|
||||||
|
|
||||||
if (workstation_type) {
|
|
||||||
return {
|
|
||||||
filters: {
|
|
||||||
workstation_type: dialog.get_value("workstation_type"),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
primary_action_label: __("Create"),
|
primary_action_label: __("Create"),
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
"qty",
|
"qty",
|
||||||
"project",
|
"project",
|
||||||
"uom",
|
"uom",
|
||||||
|
"section_break_xvld",
|
||||||
|
"routing",
|
||||||
"raw_materials_tab",
|
"raw_materials_tab",
|
||||||
"currency_detail",
|
"currency_detail",
|
||||||
"rm_cost_as_per",
|
"rm_cost_as_per",
|
||||||
@@ -393,6 +395,17 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "column_break_buha",
|
"fieldname": "column_break_buha",
|
||||||
"fieldtype": "Column Break"
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "section_break_xvld",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Operations Routing"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "routing",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Routing",
|
||||||
|
"options": "Routing"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"hide_toolbar": 1,
|
"hide_toolbar": 1,
|
||||||
@@ -404,7 +417,7 @@
|
|||||||
"link_fieldname": "bom_creator"
|
"link_fieldname": "bom_creator"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"modified": "2024-09-20 09:05:52.945112",
|
"modified": "2024-09-26 17:07:32.111198",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "BOM Creator",
|
"name": "BOM Creator",
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ BOM_ITEM_FIELDS = [
|
|||||||
"stock_uom",
|
"stock_uom",
|
||||||
"conversion_factor",
|
"conversion_factor",
|
||||||
"do_not_explode",
|
"do_not_explode",
|
||||||
|
"operation",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@@ -64,6 +65,7 @@ class BOMCreator(Document):
|
|||||||
raw_material_cost: DF.Currency
|
raw_material_cost: DF.Currency
|
||||||
remarks: DF.TextEditor | None
|
remarks: DF.TextEditor | None
|
||||||
rm_cost_as_per: DF.Literal["Valuation Rate", "Last Purchase Rate", "Price List"]
|
rm_cost_as_per: DF.Literal["Valuation Rate", "Last Purchase Rate", "Price List"]
|
||||||
|
routing: DF.Link | None
|
||||||
set_rate_based_on_warehouse: DF.Check
|
set_rate_based_on_warehouse: DF.Check
|
||||||
skip_material_transfer: DF.Check
|
skip_material_transfer: DF.Check
|
||||||
source_warehouse: DF.Link | None
|
source_warehouse: DF.Link | None
|
||||||
@@ -409,6 +411,11 @@ class BOMCreator(Document):
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
elif row.item_code == self.item_code and self.routing:
|
||||||
|
bom.routing = self.routing
|
||||||
|
bom.with_operations = 1
|
||||||
|
bom.transfer_material_against = "Work Order"
|
||||||
|
|
||||||
for field in BOM_FIELDS:
|
for field in BOM_FIELDS:
|
||||||
if self.get(field):
|
if self.get(field):
|
||||||
bom.set(field, self.get(field))
|
bom.set(field, self.get(field))
|
||||||
@@ -595,6 +602,7 @@ def add_sub_assembly(**kwargs):
|
|||||||
{
|
{
|
||||||
"item_code": row.item_code,
|
"item_code": row.item_code,
|
||||||
"qty": row.qty,
|
"qty": row.qty,
|
||||||
|
"operation": row.operation,
|
||||||
"fg_item": bom_item.item_code,
|
"fg_item": bom_item.item_code,
|
||||||
"uom": item_info.stock_uom,
|
"uom": item_info.stock_uom,
|
||||||
"fg_reference_id": name,
|
"fg_reference_id": name,
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ frappe.ui.form.on("Plant Floor", {
|
|||||||
refresh(frm) {
|
refresh(frm) {
|
||||||
frm.trigger("prepare_stock_dashboard");
|
frm.trigger("prepare_stock_dashboard");
|
||||||
frm.trigger("prepare_workstation_dashboard");
|
frm.trigger("prepare_workstation_dashboard");
|
||||||
|
frm.trigger("update_realtime_status");
|
||||||
|
|
||||||
if (!frm.is_new()) {
|
if (!frm.is_new()) {
|
||||||
frm.trigger("add_workstation");
|
frm.trigger("add_workstation");
|
||||||
@@ -58,6 +59,12 @@ frappe.ui.form.on("Plant Floor", {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
update_realtime_status(frm) {
|
||||||
|
frappe.realtime.on("update_workstation_status", (data) => {
|
||||||
|
frappe.visual_plant_floor.update_status(data);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
prepare_stock_dashboard(frm) {
|
prepare_stock_dashboard(frm) {
|
||||||
if (!frm.doc.warehouse) {
|
if (!frm.doc.warehouse) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -72,7 +72,7 @@
|
|||||||
"hide_toolbar": 1,
|
"hide_toolbar": 1,
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2024-09-19 18:06:36.481625",
|
"modified": "2024-09-25 10:27:41.139634",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Plant Floor",
|
"name": "Plant Floor",
|
||||||
|
|||||||
@@ -190,11 +190,11 @@ class WorkstationDashboard {
|
|||||||
setup_menu_actions() {
|
setup_menu_actions() {
|
||||||
let me = this;
|
let me = this;
|
||||||
this.job_cards.forEach((data) => {
|
this.job_cards.forEach((data) => {
|
||||||
me.menu_actions = me.$wrapper.find(`.menu-actions[data-job-card='${data.name}']`);
|
me.menu_btns = me.$wrapper.find(`.job-card-link[data-name='${data.name}']`);
|
||||||
$(me.menu_actions).find(".btn-start").hide();
|
|
||||||
$(me.menu_actions).find(".btn-resume").hide();
|
$(me.menu_btns).find(".btn-resume").hide();
|
||||||
$(me.menu_actions).find(".btn-pause").hide();
|
$(me.menu_btns).find(".btn-pause").hide();
|
||||||
$(me.menu_actions).find(".btn-complete").hide();
|
$(me.menu_btns).find(".btn-complete .btn").attr("disabled", true);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
data.for_quantity + data.process_loss_qty > data.total_completed_qty &&
|
data.for_quantity + data.process_loss_qty > data.total_completed_qty &&
|
||||||
@@ -203,15 +203,18 @@ class WorkstationDashboard {
|
|||||||
!data.finished_good)
|
!data.finished_good)
|
||||||
) {
|
) {
|
||||||
if (!data.time_logs?.length) {
|
if (!data.time_logs?.length) {
|
||||||
$(me.menu_actions).find(".btn-start").show();
|
$(me.menu_btns).find(".btn-start").show();
|
||||||
} else if (data.is_paused) {
|
} else if (data.is_paused) {
|
||||||
$(me.menu_actions).find(".btn-resume").show();
|
$(me.menu_btns).find(".btn-start").hide();
|
||||||
|
$(me.menu_btns).find(".btn-resume").show();
|
||||||
} else if (data.for_quantity - data.manufactured_qty > 0) {
|
} else if (data.for_quantity - data.manufactured_qty > 0) {
|
||||||
|
$(me.menu_btns).find(".btn-start").hide();
|
||||||
if (!data.is_paused) {
|
if (!data.is_paused) {
|
||||||
$(me.menu_actions).find(".btn-pause").show();
|
$(me.menu_btns).find(".btn-pause").show();
|
||||||
}
|
}
|
||||||
|
|
||||||
$(me.menu_actions).find(".btn-complete").show();
|
$(me.menu_btns).find(".btn-complete").show();
|
||||||
|
$(me.menu_btns).find(".btn-complete .btn").attr("disabled", false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -243,26 +246,26 @@ class WorkstationDashboard {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.$wrapper.find(".btn-start").on("click", (e) => {
|
this.$wrapper.find(".btn-start").on("click", (e) => {
|
||||||
let job_card = $(e.currentTarget).closest("ul").attr("data-job-card");
|
let job_card = $(e.currentTarget).closest("div").attr("data-job-card");
|
||||||
this.start_job(job_card);
|
this.start_job(job_card);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$wrapper.find(".btn-pause").on("click", (e) => {
|
this.$wrapper.find(".btn-pause").on("click", (e) => {
|
||||||
let job_card = $(e.currentTarget).closest("ul").attr("data-job-card");
|
let job_card = $(e.currentTarget).closest("div").attr("data-job-card");
|
||||||
me.update_job_card(job_card, "pause_job", {
|
me.update_job_card(job_card, "pause_job", {
|
||||||
end_time: frappe.datetime.now_datetime(),
|
end_time: frappe.datetime.now_datetime(),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$wrapper.find(".btn-resume").on("click", (e) => {
|
this.$wrapper.find(".btn-resume").on("click", (e) => {
|
||||||
let job_card = $(e.currentTarget).closest("ul").attr("data-job-card");
|
let job_card = $(e.currentTarget).closest("div").attr("data-job-card");
|
||||||
me.update_job_card(job_card, "resume_job", {
|
me.update_job_card(job_card, "resume_job", {
|
||||||
start_time: frappe.datetime.now_datetime(),
|
start_time: frappe.datetime.now_datetime(),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$wrapper.find(".btn-complete").on("click", (e) => {
|
this.$wrapper.find(".btn-complete").on("click", (e) => {
|
||||||
let job_card = $(e.currentTarget).closest("ul").attr("data-job-card");
|
let job_card = $(e.currentTarget).closest("div").attr("data-job-card");
|
||||||
let for_quantity = $(e.currentTarget).attr("data-qty");
|
let for_quantity = $(e.currentTarget).attr("data-qty");
|
||||||
me.complete_job(job_card, for_quantity);
|
me.complete_job(job_card, for_quantity);
|
||||||
});
|
});
|
||||||
@@ -315,6 +318,12 @@ class WorkstationDashboard {
|
|||||||
let me = this;
|
let me = this;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
{
|
||||||
|
label: __("Start Time"),
|
||||||
|
fieldname: "start_time",
|
||||||
|
fieldtype: "Datetime",
|
||||||
|
default: frappe.datetime.now_datetime(),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: __("Employee"),
|
label: __("Employee"),
|
||||||
fieldname: "employee",
|
fieldname: "employee",
|
||||||
@@ -337,12 +346,6 @@ class WorkstationDashboard {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
label: __("Start Time"),
|
|
||||||
fieldname: "start_time",
|
|
||||||
fieldtype: "Datetime",
|
|
||||||
default: frappe.datetime.now_datetime(),
|
|
||||||
},
|
|
||||||
{ fieldtype: "Section Break" },
|
{ fieldtype: "Section Break" },
|
||||||
{
|
{
|
||||||
label: __("Employees"),
|
label: __("Employees"),
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
"workstation_name",
|
"workstation_name",
|
||||||
"workstation_type",
|
"workstation_type",
|
||||||
"plant_floor",
|
"plant_floor",
|
||||||
|
"disabled",
|
||||||
"column_break_3",
|
"column_break_3",
|
||||||
"production_capacity",
|
"production_capacity",
|
||||||
"warehouse",
|
"warehouse",
|
||||||
@@ -240,13 +241,20 @@
|
|||||||
"fieldname": "section_break_mqqv",
|
"fieldname": "section_break_mqqv",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hide_border": 1
|
"hide_border": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "disabled",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Disabled"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"hide_toolbar": 1,
|
||||||
"icon": "icon-wrench",
|
"icon": "icon-wrench",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"image_field": "on_status_image",
|
"image_field": "on_status_image",
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2024-06-20 14:17:13.806609",
|
"modified": "2024-09-26 13:41:12.279344",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Workstation",
|
"name": "Workstation",
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ class Workstation(Document):
|
|||||||
)
|
)
|
||||||
|
|
||||||
description: DF.Text | None
|
description: DF.Text | None
|
||||||
|
disabled: DF.Check
|
||||||
holiday_list: DF.Link | None
|
holiday_list: DF.Link | None
|
||||||
hour_rate: DF.Currency
|
hour_rate: DF.Currency
|
||||||
hour_rate_consumable: DF.Currency
|
hour_rate_consumable: DF.Currency
|
||||||
@@ -71,6 +72,11 @@ class Workstation(Document):
|
|||||||
self.set_data_based_on_workstation_type()
|
self.set_data_based_on_workstation_type()
|
||||||
self.set_hour_rate()
|
self.set_hour_rate()
|
||||||
self.set_total_working_hours()
|
self.set_total_working_hours()
|
||||||
|
self.disabled_workstation()
|
||||||
|
|
||||||
|
def disabled_workstation(self):
|
||||||
|
if self.disabled:
|
||||||
|
self.status = "Off"
|
||||||
|
|
||||||
def set_total_working_hours(self):
|
def set_total_working_hours(self):
|
||||||
self.total_working_hours = 0.0
|
self.total_working_hours = 0.0
|
||||||
@@ -124,6 +130,28 @@ class Workstation(Document):
|
|||||||
self.validate_overlap_for_operation_timings()
|
self.validate_overlap_for_operation_timings()
|
||||||
self.update_bom_operation()
|
self.update_bom_operation()
|
||||||
|
|
||||||
|
if self.plant_floor:
|
||||||
|
self.publish_workstation_status()
|
||||||
|
|
||||||
|
def publish_workstation_status(self):
|
||||||
|
if not self._doc_before_save:
|
||||||
|
return
|
||||||
|
|
||||||
|
if self._doc_before_save.get("status") == self.status:
|
||||||
|
return
|
||||||
|
|
||||||
|
data = get_workstations(plant_floor=self.plant_floor, workstation_name=self.name)[0]
|
||||||
|
|
||||||
|
color_map = get_color_map()
|
||||||
|
data["old_color"] = color_map.get(self._doc_before_save.get("status"), "red")
|
||||||
|
|
||||||
|
frappe.publish_realtime(
|
||||||
|
"update_workstation_status",
|
||||||
|
data,
|
||||||
|
doctype="Plant Floor",
|
||||||
|
docname=self.plant_floor,
|
||||||
|
)
|
||||||
|
|
||||||
def validate_overlap_for_operation_timings(self):
|
def validate_overlap_for_operation_timings(self):
|
||||||
"""Check if there is no overlap in setting Workstation Operating Hours"""
|
"""Check if there is no overlap in setting Workstation Operating Hours"""
|
||||||
for d in self.get("working_hours"):
|
for d in self.get("working_hours"):
|
||||||
@@ -238,10 +266,13 @@ def get_job_cards(workstation, job_card=None):
|
|||||||
user_employee = frappe.db.get_value("Employee", {"user_id": frappe.session.user}, "name")
|
user_employee = frappe.db.get_value("Employee", {"user_id": frappe.session.user}, "name")
|
||||||
|
|
||||||
for row in jc_data:
|
for row in jc_data:
|
||||||
|
if row.status == "Open":
|
||||||
|
row.status = "Not Started"
|
||||||
|
|
||||||
item_code = row.finished_good or row.production_item
|
item_code = row.finished_good or row.production_item
|
||||||
row.fg_uom = frappe.get_cached_value("Item", item_code, "stock_uom")
|
row.fg_uom = frappe.get_cached_value("Item", item_code, "stock_uom")
|
||||||
|
|
||||||
row.status_color = get_status_color(row.status)
|
row.status_colour = get_status_color(row.status)
|
||||||
row.job_card_link = f"""
|
row.job_card_link = f"""
|
||||||
<a class="ellipsis" data-doctype="Job Card" data-name="{row.name}" href="/app/job-card/{row.name}" title="" data-original-title="{row.name}">{row.name}</a>
|
<a class="ellipsis" data-doctype="Job Card" data-name="{row.name}" href="/app/job-card/{row.name}" title="" data-original-title="{row.name}">{row.name}</a>
|
||||||
"""
|
"""
|
||||||
@@ -423,8 +454,8 @@ def get_workstations(**kwargs):
|
|||||||
_workstation.on_status_image,
|
_workstation.on_status_image,
|
||||||
_workstation.off_status_image,
|
_workstation.off_status_image,
|
||||||
)
|
)
|
||||||
.orderby(_workstation.workstation_type, _workstation.name)
|
.orderby(_workstation.creation, _workstation.workstation_type, _workstation.name)
|
||||||
.where(_workstation.plant_floor == kwargs.plant_floor)
|
.where((_workstation.plant_floor == kwargs.plant_floor) & (_workstation.disabled == 0))
|
||||||
)
|
)
|
||||||
|
|
||||||
if kwargs.workstation:
|
if kwargs.workstation:
|
||||||
@@ -436,9 +467,28 @@ def get_workstations(**kwargs):
|
|||||||
if kwargs.workstation_status:
|
if kwargs.workstation_status:
|
||||||
query = query.where(_workstation.status == kwargs.workstation_status)
|
query = query.where(_workstation.status == kwargs.workstation_status)
|
||||||
|
|
||||||
|
if kwargs.workstation_name:
|
||||||
|
query = query.where(_workstation.name == kwargs.workstation_name)
|
||||||
|
|
||||||
data = query.run(as_dict=True)
|
data = query.run(as_dict=True)
|
||||||
|
|
||||||
color_map = {
|
color_map = get_color_map()
|
||||||
|
|
||||||
|
for d in data:
|
||||||
|
d.workstation_name = get_link_to_form("Workstation", d.name)
|
||||||
|
d.status_image = d.on_status_image
|
||||||
|
d.workstation_off = ""
|
||||||
|
d.color = color_map.get(d.status, "red")
|
||||||
|
d.workstation_link = get_url_to_form("Workstation", d.name)
|
||||||
|
if d.status != "Production":
|
||||||
|
d.status_image = d.off_status_image
|
||||||
|
d.workstation_off = "workstation-off"
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def get_color_map():
|
||||||
|
return {
|
||||||
"Production": "green",
|
"Production": "green",
|
||||||
"Off": "gray",
|
"Off": "gray",
|
||||||
"Idle": "gray",
|
"Idle": "gray",
|
||||||
@@ -447,16 +497,6 @@ def get_workstations(**kwargs):
|
|||||||
"Setup": "blue",
|
"Setup": "blue",
|
||||||
}
|
}
|
||||||
|
|
||||||
for d in data:
|
|
||||||
d.workstation_name = get_link_to_form("Workstation", d.name)
|
|
||||||
d.status_image = d.on_status_image
|
|
||||||
d.color = color_map.get(d.status, "red")
|
|
||||||
d.workstation_link = get_url_to_form("Workstation", d.name)
|
|
||||||
if d.status != "Production":
|
|
||||||
d.status_image = d.off_status_image
|
|
||||||
|
|
||||||
return data
|
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def update_job_card(job_card, method, **kwargs):
|
def update_job_card(job_card, method, **kwargs):
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
<div class="row form-dashboard-section job-card-link form-links border-gray-200" data-name="{{d.name}}">
|
<div class="row form-dashboard-section job-card-link form-links border-gray-200" data-name="{{d.name}}">
|
||||||
<div class="row form-section" style="width:100%;margin-top:10px">
|
<div class="row form-section" style="width:100%;margin-top:10px">
|
||||||
<div class="form-column col-sm-2">
|
<div class="form-column col-sm-2">
|
||||||
<div class="frappe-control bold" data-doctype="Job Card" data-name="{{d.name}}" title="{{__('Job Card ID')}}">
|
<div class="frappe-control bold indicator {{d.status_colour}}" data-doctype="Job Card" data-name="{{d.name}}" title="{{__(d.status)}}">
|
||||||
{{ d.job_card_link }}
|
{{ d.job_card_link }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -52,17 +52,30 @@
|
|||||||
{% } %} -->
|
{% } %} -->
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="form-column col-sm-2">
|
<div class="form-column col-sm-1 btn-start" data-job-card="{{d.name}}">
|
||||||
<div class="frappe-control indicator-pill no-indicator-dot whitespace-nowrap job-card-status {{d.status_color}}" title="{{__('Status')}}">
|
<button class="btn btn-default">
|
||||||
{% if(d.status === "Open") { %}
|
<span class="menu-item-label" data-label="Start">{{ __('Start') }}</span>
|
||||||
{{__("Not Started")}}
|
</button>
|
||||||
{% } else { %}
|
|
||||||
{{ __(d.status) }}
|
|
||||||
{% } %}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-column col-sm-1 btn-resume" data-job-card="{{d.name}}">
|
||||||
|
<button class="btn btn-default ">
|
||||||
|
<span class="menu-item-label" data-label="Start">{{ __('Resume') }}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="form-column col-sm-1 btn-pause" data-job-card="{{d.name}}">
|
||||||
|
<button class="btn btn-default">
|
||||||
|
<span class="menu-item-label" data-label="Start">{{ __('Pause') }}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="form-column col-sm-1 btn-complete" data-job-card="{{d.name}}" data-qty="{{d.for_quantity}}">
|
||||||
|
<button class="btn btn-default">
|
||||||
|
<span class="menu-item-label" data-label="Start">{{ __('Complete') }}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="form-column col-sm-1">
|
<div class="form-column col-sm-1">
|
||||||
<div class="menu-btn-group">
|
<div class="menu-btn-group" style="margin-left: 15px;">
|
||||||
<button type="button" class="btn btn-default icon-btn" data-toggle="dropdown" aria-expanded="false" aria-label="{{ __("Menu") }}">
|
<button type="button" class="btn btn-default icon-btn" data-toggle="dropdown" aria-expanded="false" aria-label="{{ __("Menu") }}">
|
||||||
<span>
|
<span>
|
||||||
<span class="menu-btn-group-label">
|
<span class="menu-btn-group-label">
|
||||||
@@ -74,26 +87,6 @@
|
|||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
<ul class="dropdown-menu dropdown-menu-right menu-actions" role="menu" data-job-card="{{d.name}}">
|
<ul class="dropdown-menu dropdown-menu-right menu-actions" role="menu" data-job-card="{{d.name}}">
|
||||||
<li>
|
|
||||||
<a class="grey-link dropdown-item btn-start" href="#" onclick="return false;">
|
|
||||||
<span class="menu-item-label" data-label="Start">{{ __('Start') }}</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a class="grey-link dropdown-item btn-resume" href="#" onclick="return false;">
|
|
||||||
<span class="menu-item-label" data-label="Resume">{{ __('Resume') }}</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a class="grey-link dropdown-item btn-pause" href="#" onclick="return false;">
|
|
||||||
<span class="menu-item-label" data-label="Pause">{{ __('Pause') }}</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a class="grey-link dropdown-item btn-complete" href="#" onclick="return false;" data-qty="{{d.for_quantity}}">
|
|
||||||
<span class="menu-item-label" data-label="Complete">{{ __('Complete') }}</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
<li>
|
||||||
<a class="grey-link dropdown-item btn-transfer-materials" href="#" onclick="return false;">
|
<a class="grey-link dropdown-item btn-transfer-materials" href="#" onclick="return false;">
|
||||||
<span class="menu-item-label" data-label="Transfer Materials">{{ __('Transfer Materials') }}</span>
|
<span class="menu-item-label" data-label="Transfer Materials">{{ __('Transfer Materials') }}</span>
|
||||||
|
|||||||
@@ -419,6 +419,18 @@ class BOMConfigurator {
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
} else if (this.frm.doc.routing && is_root) {
|
||||||
|
fields.push(
|
||||||
|
...[
|
||||||
|
{ fieldtype: "Section Break" },
|
||||||
|
{
|
||||||
|
label: __("Operation"),
|
||||||
|
fieldname: "operation",
|
||||||
|
fieldtype: "Link",
|
||||||
|
options: "Operation",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fields.push(
|
fields.push(
|
||||||
@@ -474,6 +486,16 @@ class BOMConfigurator {
|
|||||||
dialog.set_primary_action(__("Add"), () => {
|
dialog.set_primary_action(__("Add"), () => {
|
||||||
let bom_item = dialog.get_values();
|
let bom_item = dialog.get_values();
|
||||||
|
|
||||||
|
if (!bom_item.item_code) {
|
||||||
|
frappe.throw(__("Sub Assembly Item is mandatory"));
|
||||||
|
}
|
||||||
|
|
||||||
|
bom_item.items.forEach((d) => {
|
||||||
|
if (!d.item_code) {
|
||||||
|
frappe.throw(__("Item is mandatory in Raw Materials table."));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (dialog.operation && !dialog.workstation_type && !dialog.workstation) {
|
if (dialog.operation && !dialog.workstation_type && !dialog.workstation) {
|
||||||
frappe.throw(__("Either Workstation or Workstation Type is mandatory"));
|
frappe.throw(__("Either Workstation or Workstation Type is mandatory"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -152,6 +152,30 @@ class VisualPlantFloor {
|
|||||||
this.render_plant_visualization();
|
this.render_plant_visualization();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update_status(data) {
|
||||||
|
let workstation_card$ = this.wrapper.find(`.workstation-wrapper[data-workstation="${data.name}"]`);
|
||||||
|
workstation_card$.find(".workstation-image-container").empty();
|
||||||
|
|
||||||
|
if (data.status_image) {
|
||||||
|
workstation_card$
|
||||||
|
.find(".workstation-image-container")
|
||||||
|
.append(`<img class="workstation-image-cls" src="${data.status_image}" />`);
|
||||||
|
} else {
|
||||||
|
workstation_card$
|
||||||
|
.find(".workstation-image-container")
|
||||||
|
.append(
|
||||||
|
`<div class="workstation-image-cls workstation-abbr" style="margin:6px; height:82px">${frappe.get_abbr(
|
||||||
|
data.name,
|
||||||
|
2
|
||||||
|
)}</div>`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
workstation_card$.find(".indicator-pill").removeClass(data.old_color);
|
||||||
|
workstation_card$.find(".indicator-pill").addClass(data.color);
|
||||||
|
workstation_card$.find(".workstation-status-title").text(data.status);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
frappe.ui.VisualPlantFloor = VisualPlantFloor;
|
frappe.ui.VisualPlantFloor = VisualPlantFloor;
|
||||||
|
|||||||
@@ -1,30 +1,20 @@
|
|||||||
{% $.each(workstations, (idx, row) => { %}
|
{% $.each(workstations, (idx, row) => { %}
|
||||||
<div class="workstation-wrapper">
|
<div class="workstation-wrapper" data-workstation="{{row.name}}">
|
||||||
<div class="workstation-status text-right">
|
<div class="workstation-status text-left" style="">
|
||||||
{% if(row.status == "Production") { %}
|
<span class="indicator-pill no-indicator-dot whitespace-nowrap {{row.color}}" style="margin: 8px 0px 0px 8px;">
|
||||||
<div class="ring-container">
|
<span class="workstation-status-title" style="font-size:9px">{{row.status}}</span>
|
||||||
<div class="ringring"></div>
|
|
||||||
<div class="circle"></div>
|
|
||||||
</div>
|
|
||||||
{% } %}
|
|
||||||
<span class="indicator-pill no-indicator-dot whitespace-nowrap {{row.color}}" style="margin: 3px 4px 0px 0px;">
|
|
||||||
<span style="font-size:13px">{{row.status}}</span>
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="workstation-image">
|
<div class="workstation-image {{row.workstation_off}}" onclick="location.href='{{row.workstation_link}}'">
|
||||||
<div class="flex items-center justify-center h-32 border-b-grey text-6xl text-grey-100">
|
<div class="workstation-image-container flex items-center justify-center h-32 border-b-grey text-6xl text-grey-100">
|
||||||
<a class="workstation-image-link" href="{{row.workstation_link}}">
|
{% if(row.status_image) { %}
|
||||||
{% if(row.status_image) { %}
|
<img class="workstation-image-cls" src="{{row.status_image}}">
|
||||||
<img class="workstation-image-cls" src="{{row.status_image}}">
|
{% } else { %}
|
||||||
{% } else { %}
|
<div class="workstation-image-cls workstation-abbr" style="margin:6px; height:82px">{{frappe.get_abbr(row.name, 2)}}</div>
|
||||||
<div class="workstation-image-cls workstation-abbr">{{frappe.get_abbr(row.name, 2)}}</div>
|
{% } %}
|
||||||
{% } %}
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="workstation-card" style="display: grid;">
|
|
||||||
<span class="ellipsis" title="{{row.name}}">
|
<span class="ellipsis" title="{{row.name}}">
|
||||||
{{row.workstation_name}}
|
<div style="font-size:9px; text-align:center;padding-bottom:8px">{{row.workstation_name}}</div>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -552,8 +552,16 @@ body[data-route="pos"] {
|
|||||||
padding-bottom: 25px;
|
padding-bottom: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.workstation-image {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workstation-image-container {
|
||||||
|
height: 3.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.workstation-image-cls {
|
.workstation-image-cls {
|
||||||
height: 9rem;
|
padding-top: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plant-floor-filter {
|
.plant-floor-filter {
|
||||||
@@ -565,7 +573,11 @@ body[data-route="pos"] {
|
|||||||
.plant-floor-container {
|
.plant-floor-container {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(5, minmax(0, 1fr));
|
grid-template-columns: repeat(5, minmax(0, 1fr));
|
||||||
gap: var(--margin-lg);
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workstation-off {
|
||||||
|
opacity: 0.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 620px) {
|
@media screen and (max-width: 620px) {
|
||||||
|
|||||||
Reference in New Issue
Block a user