fix: plant floor design changes

This commit is contained in:
Rohit Waghchaure
2024-09-25 14:25:42 +05:30
parent e4e96d2a44
commit 3c1cdeb3ec
13 changed files with 213 additions and 152 deletions

View File

@@ -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"),

View File

@@ -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",

View File

@@ -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,

View File

@@ -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;

View File

@@ -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",

View File

@@ -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"),

View File

@@ -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",

View File

@@ -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):

View File

@@ -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>

View File

@@ -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"));
} }

View File

@@ -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;

View File

@@ -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>

View File

@@ -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) {