Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Zone picking show when location will be empty #91

Merged
Merged
9 changes: 7 additions & 2 deletions shopfloor/services/zone_picking.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,9 +226,14 @@ def _data_for_move_lines(self, zone_location, picking_type, move_lines):
"move_lines": self.data.move_lines(move_lines, with_picking=True),
}
for data_move_line in data["move_lines"]:
# TODO: this could be expensive, think about a better way
# to retrieve if location will be empty.
# Maybe group lines by location and compute only once.
move_line = self.env["stock.move.line"].browse(data_move_line["id"])
# `location_will_be_empty` flag states if, by processing this move line
# and picking the product, the location will be emptied.
data_move_line[
"empty_location_src"
"location_will_be_empty"
] = move_line.location_id.planned_qty_in_location_is_empty(move_line)
return data

Expand Down Expand Up @@ -1557,7 +1562,7 @@ def _schema_for_move_lines(self):
@property
def _schema_for_move_lines_empty_location(self):
schema = self._schema_for_move_lines
schema["move_lines"]["schema"]["schema"]["empty_location_src"] = {
schema["move_lines"]["schema"]["schema"]["location_will_be_empty"] = {
"type": "boolean",
"nullable": False,
"required": True,
Expand Down
2 changes: 1 addition & 1 deletion shopfloor/tests/test_zone_picking_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ def _assert_response_select_line(
for data_move_line in data["move_lines"]:
move_line = self.env["stock.move.line"].browse(data_move_line["id"])
data_move_line[
"empty_location_src"
"location_will_be_empty"
] = move_line.location_id.planned_qty_in_location_is_empty(move_line)
self.assert_response(
response, next_state=state, data=data, message=message, popup=popup,
Expand Down
2 changes: 1 addition & 1 deletion shopfloor/tests/test_zone_picking_select_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ def test_list_move_lines_empty_location(self):
for m in data_move_lines
if m["location_src"]["barcode"] == "ZONE_SUBLOCATION_1"
][0]
self.assertTrue(data_move_line["empty_location_src"])
self.assertTrue(data_move_line["location_will_be_empty"])
# Same check with the internal method
move_line = self.env["stock.move.line"].browse(data_move_line["id"])
location_src = move_line.location_id
Expand Down
1 change: 1 addition & 0 deletions shopfloor_mobile/readme/ROADMAP.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
* Document demo mode
* Find / create a nice icon
* Finish base translations (move all UI strings to translatable terms)
* Use SCSS
2 changes: 1 addition & 1 deletion shopfloor_mobile/static/wms/src/components/list.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ Vue.component("list", {
},
template: `
<div :class="klass">
<v-card class="list-group"
<v-card :class="['list-group', opts.card_klass]"
v-for="(group, gindex) in listable" :key="make_component_key([$options._componentTag, 'group', gindex])"
:color="group.group_color || opts.group_color">
<v-card-title v-if="group.title">{{ group.title }}</v-card-title>
Expand Down
5 changes: 3 additions & 2 deletions shopfloor_mobile/static/wms/src/components/manual_select.js
Original file line number Diff line number Diff line change
Expand Up @@ -232,14 +232,15 @@ Vue.component("manual-select", {
},
template: `
<div :class="klass">
<v-card class="select-group"
<v-card :class="['select-group', opts.card_klass]"
:color="group.group_color || opts.group_color"
v-for="(group, gindex) in selectable"
:key="make_component_key([$options._componentTag, 'group', gindex])">
<v-card-title v-if="group.title">{{ group.title }}</v-card-title>
<v-list v-if="has_records">
<div :class="['list-item-wrapper', is_selected(rec) ? selected_color_klass() : '']" v-for="(rec, index) in group.records"">
<v-list-item :key="make_component_key(['group-rec', gindex, index, rec.id])">
<v-list-item :key="make_component_key(['group-rec', gindex, index, rec.id])"
:class="list_item_options.list_item_klass_maker ? list_item_options.list_item_klass_maker(rec) : ''">
<v-list-item-content>
<component
:is="opts.list_item_component"
Expand Down
13 changes: 12 additions & 1 deletion shopfloor_mobile/static/wms/src/components/misc.js
Original file line number Diff line number Diff line change
Expand Up @@ -437,5 +437,16 @@ Vue.component("btn-fullscreen", {
this.fullscreen_on = false;
},
},
template: `<btn-action @click="fullscreen_on ? leave_fullscreen() : go_fullscreen()">{{ btn_label }}</btn-action>`,
template: `
<btn-action @click="fullscreen_on ? leave_fullscreen() : go_fullscreen()">
<v-icon>{{ fullscreen_on ? 'mdi-fullscreen-exit' : 'mdi-fullscreen' }}</v-icon> {{ btn_label }}
</btn-action>
`,
});

Vue.component("empty-location-icon", {
mixins: [ItemDetailMixin],
template: `
<v-icon color="orange" :class="$options._componentTag" v-if="record.location_will_be_empty">mdi-alert-rhombus-outline</v-icon>
`,
});
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

export var PriorityWidget = Vue.component("priority-widget", {
props: {
record: Object,
options: Object,
},
computed: {
Expand Down
7 changes: 7 additions & 0 deletions shopfloor_mobile/static/wms/src/css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ ul.packaging span:first-child {
font-size: 1.3em;
line-height: 1.4em;
}
.v-card.loud-labels .label,
.detail.item-detail-card .field-detail.loud-label .label,
.detail.item-detail-card.loud-labels .v-card__text.details .label,
.detail.item-detail-card.loud .v-card__text.details .label {
Expand Down Expand Up @@ -519,6 +520,12 @@ I tested only w/ checkout/select_package for now
margin-right: 1.2em;
}

.v-list-item.location-will-be-empty .field-detail.location_will_be_empty {
position: absolute;
top: 5px;
right: 5px;
}

@media screen and (max-width: 320px) {
#app header.has-main-doc .app-bar-actions {
display: none;
Expand Down
4 changes: 4 additions & 0 deletions shopfloor_mobile/static/wms/src/demo/demo.zone_picking.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ const move_lines = demotools.makePickingLines(
{lines_count: 30, line_random_pack: true, picking_auto: true}
);
const select_line_move_lines = _.orderBy(move_lines, ["priority"], ["desc"]);
_.forEach(select_line_move_lines, function(line, i) {
// Simulate random flag
line.location_will_be_empty = i % 3 == 0;
});

const list_move_lines = {
next_state: "select_line",
Expand Down
32 changes: 32 additions & 0 deletions shopfloor_mobile/static/wms/src/scenario/zone_picking.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,18 @@ const template_mobile = `
:items="select_line_table_items()"
:key="make_state_component_key(['data-table'])"
class="elevation-1">

<template v-slot:item.quantity="{ item }">
<packaging-qty-picker-display
:options="utils.misc.move_line_qty_picker_options(item['_origin'])"
/>
</template>
<template v-slot:item.priority="{ item }">
<priority-widget :options="{priority: parseInt(item.priority || '0', 10)}" />
</template>
<template v-slot:item.location_will_be_empty="{ item }">
<empty-location-icon :record="item" />
</template>
</v-data-table>

<div class="button-list button-vertical-list full">
Expand Down Expand Up @@ -254,6 +266,7 @@ const ZonePicking = {
item_data[field.path] = field.renderer(record, field);
}
});
item_data["_origin"] = record;
return item_data;
});
return items;
Expand All @@ -262,11 +275,17 @@ const ZonePicking = {
let options = {
key_title: "location_src.name",
group_color: this.utils.colors.color_for("screen_step_todo"),
card_klass: "loud-labels",
title_action_field: {action_val_path: "product.barcode"},
showActions: false,
list_item_options: {
bold_title: true,
fields: this.move_line_list_fields(),
list_item_klass_maker: function(rec) {
return rec.location_will_be_empty
? "location-will-be-empty"
: "";
},
},
};
return options;
Expand All @@ -277,6 +296,14 @@ const ZonePicking = {
{path: "product.display_name", label: table_mode ? "Product" : null},
{path: "package_src.name", label: "Pack"},
{path: "lot.name", label: "Lot"},
{
path: "quantity",
label: "Qty",
render_component: "packaging-qty-picker-display",
render_options: function(record) {
return self.utils.misc.move_line_qty_picker_options(record);
},
},
{path: "package_src.weight", label: "Weight"},
{
path: "picking.scheduled_date",
Expand All @@ -293,6 +320,11 @@ const ZonePicking = {
return {priority: parseInt(record.priority || "0", 10)};
},
},
{
path: "location_will_be_empty",
render_component: "empty-location-icon",
display_no_value: true,
},
];
if (table_mode) {
fields.unshift({path: "location_src.name", label: "Location"});
Expand Down