Skip to content

Commit

Permalink
Merge branch '14.0--wms-consolidation-branch' of github.com:camptocam…
Browse files Browse the repository at this point in the history
…p/wms into merge-branch-2477-BSCOS-4214-26a8f722
  • Loading branch information
JuMiSanAr committed Mar 15, 2024
2 parents d57fee6 + 2e230a1 commit e86488b
Show file tree
Hide file tree
Showing 30 changed files with 229 additions and 38 deletions.
5 changes: 3 additions & 2 deletions shopfloor/actions/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class DataAction(Component):
def location(self, record, **kw):
parser = self._location_parser
data = self._jsonify(record.with_context(location=record.id), parser, **kw)
if "with_operation_progress" in kw:
if kw.get("with_operation_progress"):
lines_blacklist = (
kw.get("progress_lines_blacklist")
or self.env["stock.move.line"].browse()
Expand Down Expand Up @@ -46,7 +46,7 @@ def _get_picking_parser(self, record, **kw):
# and it may reduce performance significatively
# when dealing with a large number of pickings.
# Thus, we make it optional.
if "with_progress" in kw:
if kw.get("with_progress"):
parser.append("progress")
return parser

Expand All @@ -72,6 +72,7 @@ def _picking_parser(self, **kw):
"bulk_line_count",
"total_weight:weight",
"scheduled_date",
"priority",
]

@ensure_model("stock.quant.package")
Expand Down
1 change: 1 addition & 0 deletions shopfloor/actions/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ def picking(self):
"scheduled_date": {"type": "string", "nullable": False, "required": True},
"progress": {"type": "float", "nullable": True},
"location_dest": self._schema_dict_of(self.location(), required=False),
"priority": {"type": "string", "nullable": True, "required": False},
}

def move_line(self, with_packaging=False, with_picking=False):
Expand Down
1 change: 1 addition & 0 deletions shopfloor/models/stock_move_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class StockMoveLine(models.Model):
# we search lines based on their location in some workflows
location_id = fields.Many2one(index=True)
package_id = fields.Many2one(index=True)
result_package_id = fields.Many2one(index=True)

# allow domain on picking_id.xxx without too much perf penalty
picking_id = fields.Many2one(auto_join=True)
Expand Down
11 changes: 11 additions & 0 deletions shopfloor/models/stock_picking.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,14 @@ def split_assigned_move_lines(self, move_lines=None):
)
assigned_moves._action_assign()
return new_picking.id

def _put_in_pack(self, move_line_ids, create_package_level=True):
"""
Marks the corresponding move lines as 'shopfloor_checkout_done'
when the package is created in the backend.
"""
new_package = super()._put_in_pack(move_line_ids, create_package_level)
lines = move_line_ids.filtered(lambda p: p.result_package_id == new_package)
lines.write({"shopfloor_checkout_done": True})
return new_package
18 changes: 3 additions & 15 deletions shopfloor/services/checkout.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,22 +103,13 @@ def _response_for_select_package(self, picking, lines, message=None):
data={
"selected_move_lines": self._data_for_move_lines(lines.sorted()),
"picking": self.data.picking(picking),
"packing_info": self._data_for_packing_info(picking),
"no_package_enabled": not self.options.get(
"checkout__disable_no_package"
),
},
message=message,
)

def _data_for_packing_info(self, picking):
"""Return the packing information
Intended to be extended.
"""
# TODO: This could be avoided if included in the picking parser.
return ""

def _response_for_select_dest_package(self, picking, move_lines, message=None):
packages = picking.mapped("move_line_ids.result_package_id").filtered(
"packaging_id"
Expand Down Expand Up @@ -363,7 +354,7 @@ def _domain_for_list_stock_picking(self):
]

def _order_for_list_stock_picking(self):
return "scheduled_date asc, id asc"
return "priority desc, scheduled_date asc, id asc"

def list_stock_picking(self):
"""List stock.picking records available
Expand Down Expand Up @@ -1478,11 +1469,8 @@ def done(self, picking_id, confirmation=False):
},
)
lines_done = self._lines_checkout_done(picking)
dest_location = picking.location_dest_id
child_locations = self.env["stock.location"].search(
[("id", "child_of", dest_location.id), ("usage", "!=", "view")]
)
if len(child_locations) > 0 and child_locations != dest_location:
dest_location = lines_done.move_id.location_dest_id
if len(dest_location) != 1 or dest_location.usage == "view":
return self._response_for_select_child_location(
picking,
)
Expand Down
7 changes: 5 additions & 2 deletions shopfloor/services/cluster_picking.py
Original file line number Diff line number Diff line change
Expand Up @@ -776,8 +776,11 @@ def scan_destination_pack(self, picking_batch_id, move_line_id, barcode, quantit
qty_done=quantity,
)
move_line.write({"qty_done": quantity, "result_package_id": bin_package.id})

zero_check = move_line.picking_id.picking_type_id.shopfloor_zero_check
# Only apply zero check if the product is of type "product".
zero_check = (
move_line.product_id.type == "product"
and move_line.picking_id.picking_type_id.shopfloor_zero_check
)
if zero_check and move_line.location_id.planned_qty_in_location_is_empty():
return self._response_for_zero_check(batch, move_line)

Expand Down
28 changes: 21 additions & 7 deletions shopfloor/services/zone_picking.py
Original file line number Diff line number Diff line change
Expand Up @@ -667,12 +667,15 @@ def _scan_source_package(
)
else:
change_package_lot = self._actions_for("change.package.lot")
move_line = first(move_lines)
response = change_package_lot.change_package(
first(move_lines),
move_line,
package,
# FIXME we may need to pass the quantity being done
self._response_for_set_line_destination,
self._response_for_change_pack_lot,
response_ok_func=functools.partial(
self._response_for_set_line_destination,
qty_done=self._get_prefill_qty(move_line, qty=0),
),
response_error_func=self._response_for_change_pack_lot,
)
else:
response = self._list_move_lines(sublocation or self.zone_location)
Expand Down Expand Up @@ -959,7 +962,11 @@ def _set_destination_location(

location_changed = True
# Zero check
zero_check = self.picking_type.shopfloor_zero_check
# Only apply zero check if the product is of type "product".
zero_check = (
move_line.product_id.type == "product"
and self.picking_type.shopfloor_zero_check
)
if zero_check and move_line.location_id.planned_qty_in_location_is_empty():
response = self._response_for_zero_check(move_line)
return (location_changed, response)
Expand Down Expand Up @@ -1042,7 +1049,11 @@ def _set_destination_package(self, move_line, quantity, package):
return (package_changed, response)
package_changed = True
# Zero check
zero_check = self.picking_type.shopfloor_zero_check
# Only apply zero check if the product is of type "product".
zero_check = (
move_line.product_id.type == "product"
and self.picking_type.shopfloor_zero_check
)
if zero_check and move_line.location_id.planned_qty_in_location_is_empty():
response = self._response_for_zero_check(move_line)
return (package_changed, response)
Expand Down Expand Up @@ -1434,7 +1445,10 @@ def change_pack_lot(self, move_line_id, barcode):
# pre-configured callable used to generate the response as the
# change.package.lot component is not aware of the needed response type
# and related parameters for zone picking scenario
response_ok_func = functools.partial(self._response_for_set_line_destination)
response_ok_func = functools.partial(
self._response_for_set_line_destination,
qty_done=self._get_prefill_qty(move_line),
)
response_error_func = functools.partial(self._response_for_change_pack_lot)
response = None
change_package_lot = self._actions_for("change.package.lot")
Expand Down
2 changes: 2 additions & 0 deletions shopfloor/tests/test_actions_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ def test_data_picking(self):
"partner": {"id": self.customer.id, "name": self.customer.name},
"carrier": {"id": carrier.id, "name": carrier.name},
"ship_carrier": None,
"priority": "0",
}
self.assertEqual(data.pop("scheduled_date").split("T")[0], "2020-08-03")
self.assertDictEqual(data, expected)
Expand All @@ -179,6 +180,7 @@ def test_data_picking_with_progress(self):
"carrier": {"id": carrier.id, "name": carrier.name},
"ship_carrier": None,
"progress": 0.0,
"priority": "0",
}
self.assertEqual(data.pop("scheduled_date").split("T")[0], "2020-08-03")
self.assertDictEqual(data, expected)
Expand Down
1 change: 0 additions & 1 deletion shopfloor/tests/test_checkout_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ def _assert_select_package_qty_above(self, response, picking):
self._move_line_data(ml) for ml in picking.move_line_ids.sorted()
],
"picking": self._picking_summary_data(picking),
"packing_info": "",
"no_package_enabled": True,
},
message={
Expand Down
28 changes: 27 additions & 1 deletion shopfloor/tests/test_checkout_done.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,34 @@ def test_done_partial_confirm(self):
"done", params={"picking_id": self.picking.id, "confirmation": True}
)

self.assertRecordValues(self.picking, [{"state": "assigned"}])
self.assertRecordValues(self.picking, [{"state": "done"}])

self.assert_response(
response,
next_state="select_document",
message=self.service.msg_store.transfer_done_success(self.picking),
data={"restrict_scan_first": False},
)

def test_done_ask_destination_location(self):
"""Check asking for destination location for view type location."""
view_location = (
self.env["stock.location"]
.sudo()
.create(
{
"name": "Test Location Usage View",
"location_id": self.picking.move_lines.location_dest_id.id,
"usage": "view",
}
)
)
self.picking.move_lines.location_dest_id = view_location
response = self.service.dispatch(
"done", params={"picking_id": self.picking.id, "confirmation": True}
)

self.assertRecordValues(self.picking, [{"state": "assigned"}])
self.assert_response(
response,
next_state="select_child_location",
Expand Down
1 change: 0 additions & 1 deletion shopfloor/tests/test_checkout_list_delivery_packaging.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@ def test_list_delivery_packaging_not_available(self):
"selected_move_lines": [
self._move_line_data(ml) for ml in selected_lines.sorted()
],
"packing_info": self.service._data_for_packing_info(self.picking),
"no_package_enabled": not self.service.options.get(
"checkout__disable_no_package"
),
Expand Down
26 changes: 25 additions & 1 deletion shopfloor/tests/test_checkout_scan_package_action.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,6 @@ def test_scan_package_action_scan_package_keep_source_package_error(self):
data={
"picking": self.data.picking(picking),
"selected_move_lines": self.data.move_lines(selected_lines),
"packing_info": self.service._data_for_packing_info(picking),
"no_package_enabled": not self.service.options.get(
"checkout__disable_no_package"
),
Expand Down Expand Up @@ -455,3 +454,28 @@ def test_scan_package_action_scan_not_found(self):
selected_line,
message={"message_type": "error", "body": "Barcode not found"},
)

def test_put_in_pack(self):
picking = self._create_picking(
lines=[(self.product_a, 10), (self.product_b, 20)]
)
self._fill_stock_for_moves(picking.move_lines)
picking.action_assign()

# Test that the move lines are marked as 'shopfloor_checkout_done'
# when putting them in a pack in the backend.
picking._put_in_pack(picking.move_line_ids)
self.assertTrue(
all(line.shopfloor_checkout_done for line in picking.move_line_ids)
)

# Check that we return those lines to the frontend.
res = self.service.dispatch(
"summary",
params={
"picking_id": picking.id,
},
)
returned_lines = res["data"]["summary"]["picking"]["move_lines"]
expected_line_ids = [line["id"] for line in returned_lines]
self.assertEqual(expected_line_ids, picking.move_line_ids.ids)
1 change: 0 additions & 1 deletion shopfloor/tests/test_checkout_select_package_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ def _assert_selected_response(
self._move_line_data(ml) for ml in selected_lines.sorted()
],
"picking": self._picking_summary_data(picking),
"packing_info": packing_info,
"no_package_enabled": no_package_enabled,
},
message=message,
Expand Down
2 changes: 2 additions & 0 deletions shopfloor/tests/test_zone_picking_change_pack_lot.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ def test_change_pack_lot_change_pack_ok(self):
message=self.service.msg_store.package_replaced_by_package(
previous_package, self.free_package
),
qty_done=self.service._get_prefill_qty(move_line),
)

def test_change_pack_lot_change_lot_ok(self):
Expand Down Expand Up @@ -137,4 +138,5 @@ def test_change_pack_lot_change_lot_ok(self):
message=self.service.msg_store.lot_replaced_by_lot(
previous_lot, self.free_lot
),
qty_done=self.service._get_prefill_qty(move_line),
)
1 change: 1 addition & 0 deletions shopfloor/tests/test_zone_picking_select_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ def test_scan_source_barcode_package_can_replace_in_line(self):
message=self.service.msg_store.package_replaced_by_package(
package1, package1b
),
qty_done=self.service._get_prefill_qty(move_lines[0]),
)
# Check the package has been changed on the move line
self.assertEqual(self.picking1.package_level_ids[0].package_id, package1b)
Expand Down
1 change: 1 addition & 0 deletions shopfloor/views/shopfloor_menu.xml
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
name="scan_location_or_pack_first"
attrs="{'invisible': [('scan_location_or_pack_first_is_possible', '=', False)]}"
>
<field name="scenario_key" invisible="1" />
<field name="scan_location_or_pack_first_is_possible" invisible="1" />
<field name="scan_location_or_pack_first" />
<div
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@ const ManualProductTransfer = {
}
if ("qty_done" in data) return data.qty_done;
if ("quantity" in data) return data.quantity;
if ("move_lines" in data) {
return data.move_lines.reduce((total, val) => total + val.qty_done, 0);
}
return 0;
},
lot: function () {
Expand Down
18 changes: 16 additions & 2 deletions shopfloor_mobile/static/wms/src/scenario/checkout.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ const Checkout = {
</div>
<div v-if="state_is('select_package')">
<v-alert type="info" tile v-if="state.data.packing_info" class="packing-info">
<p v-text="state.data.packing_info" />
<v-alert type="info" tile v-if="state.data.picking.note" class="packing-info">
<p v-text="state.data.picking.note" />
</v-alert>
<item-detail-card
v-if="state.data.picking.carrier"
Expand Down Expand Up @@ -293,6 +293,20 @@ const Checkout = {
{path: "origin"},
{path: "carrier.name", label: "Carrier"},
{path: "move_line_count", label: "Lines"},
{
path: "priority",
render_component: "priority-widget",
render_options: function (record) {
const priority = parseInt(record.priority);
// We need to pass the label to the component as an option instead of using "display_no_value"
// because pickings with no priority will still have a string value of "0"
// and the label would always be displayed.
return {
priority,
label: priority ? "Priority: " : null,
};
},
},
],
},
};
Expand Down
6 changes: 6 additions & 0 deletions shopfloor_mobile/static/wms/src/scenario/cluster_picking.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import {ScenarioBaseMixin} from "/shopfloor_mobile_base/static/wms/src/scenario/mixins.js";
import {process_registry} from "/shopfloor_mobile_base/static/wms/src/services/process_registry.js";

// TODO: consider replacing the dynamic "autofocus" in the searchbar by an event.
// At the moment, we need autofocus to be disabled if there's a user popup.
const ClusterPicking = {
mixins: [ScenarioBaseMixin],
template: `
Expand All @@ -18,6 +20,7 @@ const ClusterPicking = {
v-if="state.on_scan"
v-on:found="on_scan"
:input_placeholder="search_input_placeholder"
:autofocus="!screen_info.user_popup"
/>
<get-work
v-if="state_is('start')"
Expand All @@ -30,6 +33,9 @@ const ClusterPicking = {
v-on:confirm="state.on_confirm"
v-on:cancel="state.on_cancel"
/>
<v-alert type="info" tile v-if="state_is('start_line') && state.data.picking.note" class="packing-info">
<p v-text="state.data.picking.note" />
</v-alert>
<batch-picking-line-detail
v-if="state_in(['start_line', 'scan_destination', 'change_pack_lot', 'stock_issue'])"
:line="state.data"
Expand Down
Loading

0 comments on commit e86488b

Please sign in to comment.