odoo-addon-shopfloor 18.0.0.1.2__py3-none-any.whl → 18.0.0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- odoo/addons/shopfloor/README.rst +1 -1
- odoo/addons/shopfloor/__manifest__.py +1 -1
- odoo/addons/shopfloor/actions/message.py +3 -3
- odoo/addons/shopfloor/models/stock_move_line.py +2 -2
- odoo/addons/shopfloor/models/stock_picking.py +2 -5
- odoo/addons/shopfloor/services/checkout.py +64 -54
- odoo/addons/shopfloor/services/cluster_picking.py +3 -2
- odoo/addons/shopfloor/services/delivery.py +14 -15
- odoo/addons/shopfloor/services/zone_picking.py +3 -2
- odoo/addons/shopfloor/static/description/index.html +1 -1
- odoo/addons/shopfloor/tests/__init__.py +32 -31
- odoo/addons/shopfloor/tests/common.py +3 -1
- odoo/addons/shopfloor/tests/test_checkout_auto_post.py +9 -8
- odoo/addons/shopfloor/tests/test_checkout_base.py +1 -1
- odoo/addons/shopfloor/tests/test_checkout_cancel_line.py +12 -8
- odoo/addons/shopfloor/tests/test_checkout_done.py +5 -5
- odoo/addons/shopfloor/tests/test_checkout_list_delivery_packaging.py +0 -2
- odoo/addons/shopfloor/tests/test_checkout_list_package.py +19 -12
- odoo/addons/shopfloor/tests/test_checkout_new_package.py +7 -7
- odoo/addons/shopfloor/tests/test_checkout_no_package.py +6 -6
- odoo/addons/shopfloor/tests/test_checkout_scan.py +1 -1
- odoo/addons/shopfloor/tests/test_checkout_scan_dest_location.py +2 -2
- odoo/addons/shopfloor/tests/test_checkout_scan_line.py +3 -1
- odoo/addons/shopfloor/tests/test_checkout_scan_package_action.py +14 -14
- odoo/addons/shopfloor/tests/test_checkout_scan_package_action_no_prefill_qty.py +9 -9
- odoo/addons/shopfloor/tests/test_checkout_select_line.py +1 -1
- odoo/addons/shopfloor/tests/test_checkout_select_package_base.py +6 -4
- odoo/addons/shopfloor/tests/test_checkout_set_qty.py +12 -11
- odoo/addons/shopfloor/tests/test_checkout_summary.py +2 -2
- odoo/addons/shopfloor/tests/test_delivery_base.py +3 -3
- odoo/addons/shopfloor/tests/test_delivery_done.py +1 -2
- odoo/addons/shopfloor/tests/test_delivery_reset_qty_done_line.py +2 -2
- odoo/addons/shopfloor/tests/test_delivery_reset_qty_done_pack.py +2 -2
- odoo/addons/shopfloor/tests/test_delivery_scan_deliver.py +11 -11
- odoo/addons/shopfloor/tests/test_delivery_set_qty_done_line.py +1 -1
- odoo/addons/shopfloor/tests/test_delivery_set_qty_done_pack.py +1 -1
- {odoo_addon_shopfloor-18.0.0.1.2.dist-info → odoo_addon_shopfloor-18.0.0.2.0.dist-info}/METADATA +2 -2
- {odoo_addon_shopfloor-18.0.0.1.2.dist-info → odoo_addon_shopfloor-18.0.0.2.0.dist-info}/RECORD +40 -40
- {odoo_addon_shopfloor-18.0.0.1.2.dist-info → odoo_addon_shopfloor-18.0.0.2.0.dist-info}/WHEEL +1 -1
- {odoo_addon_shopfloor-18.0.0.1.2.dist-info → odoo_addon_shopfloor-18.0.0.2.0.dist-info}/top_level.txt +0 -0
odoo/addons/shopfloor/README.rst
CHANGED
@@ -11,7 +11,7 @@ Shopfloor
|
|
11
11
|
!! This file is generated by oca-gen-addon-readme !!
|
12
12
|
!! changes will be overwritten. !!
|
13
13
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
14
|
-
!! source digest: sha256:
|
14
|
+
!! source digest: sha256:534d443b8feb0fd2548ede9663e260ceb8dcfb20686a39d06022ee92bcc6d209
|
15
15
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
16
16
|
|
17
17
|
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
|
@@ -6,7 +6,7 @@
|
|
6
6
|
{
|
7
7
|
"name": "Shopfloor",
|
8
8
|
"summary": "manage warehouse operations with barcode scanners",
|
9
|
-
"version": "18.0.0.
|
9
|
+
"version": "18.0.0.2.0",
|
10
10
|
"development_status": "Beta",
|
11
11
|
"category": "Inventory",
|
12
12
|
"website": "https://github.com/OCA/stock-logistics-shopfloor",
|
@@ -742,7 +742,7 @@ class MessageAction(Component):
|
|
742
742
|
"body": _("The picked quantity must be a value above zero."),
|
743
743
|
}
|
744
744
|
|
745
|
-
def
|
745
|
+
def selected_lines_qty_picked_higher_than_allowed(self, line):
|
746
746
|
"""
|
747
747
|
:param line: The selected line
|
748
748
|
"""
|
@@ -753,12 +753,12 @@ class MessageAction(Component):
|
|
753
753
|
"higher than the maximum allowed. "
|
754
754
|
"(%(product_name)s : %(quantity_done)s > %(quantity_reserved)s)",
|
755
755
|
product_name=line.product_id.name,
|
756
|
-
quantity_done=str(line.
|
756
|
+
quantity_done=str(line.qty_picked),
|
757
757
|
quantity_reserved=str(line.quantity),
|
758
758
|
),
|
759
759
|
}
|
760
760
|
|
761
|
-
def
|
761
|
+
def line_scanned_qty_picked_higher_than_allowed(self):
|
762
762
|
return {
|
763
763
|
"message_type": "warning",
|
764
764
|
"body": _(
|
@@ -117,13 +117,13 @@ class StockMoveLine(models.Model):
|
|
117
117
|
elif qty_lesser:
|
118
118
|
if not split_partial:
|
119
119
|
return (new_line, "lesser")
|
120
|
-
new_line = self.
|
120
|
+
new_line = self._split_partial_quantity_to_be_picked(
|
121
121
|
qty_done, split_default_vals
|
122
122
|
)
|
123
123
|
return (new_line, "lesser")
|
124
124
|
return (new_line, "full")
|
125
125
|
|
126
|
-
def
|
126
|
+
def _split_partial_quantity_to_be_picked(self, quantity_done, split_default_vals):
|
127
127
|
"""Create a new move line with the remaining quantity to process."""
|
128
128
|
# split the move line which will be processed later (maybe the user
|
129
129
|
# has to pick some goods from another place because the location
|
@@ -122,11 +122,8 @@ class StockPicking(models.Model):
|
|
122
122
|
return new_picking.id
|
123
123
|
|
124
124
|
def _put_in_pack(self, move_line_ids):
|
125
|
-
|
126
|
-
|
127
|
-
when the package is created in the backend.
|
128
|
-
|
129
|
-
"""
|
125
|
+
# Marks the corresponding move lines as 'shopfloor_checkout_done'
|
126
|
+
# when the package is created in the backend.
|
130
127
|
new_package = super()._put_in_pack(move_line_ids)
|
131
128
|
lines = move_line_ids.filtered(lambda p: p.result_package_id == new_package)
|
132
129
|
lines.write({"shopfloor_checkout_done": True})
|
@@ -426,9 +426,9 @@ class Checkout(Component):
|
|
426
426
|
continue
|
427
427
|
if self.work.menu.no_prefill_qty and i == 0:
|
428
428
|
# For prefill quantity we only want to increment one line
|
429
|
-
line.
|
429
|
+
line.qty_picked += prefill_qty
|
430
430
|
elif not self.work.menu.no_prefill_qty:
|
431
|
-
line.
|
431
|
+
line.picked = True
|
432
432
|
line.shopfloor_user_id = self.env.user
|
433
433
|
|
434
434
|
picking = lines.mapped("picking_id")
|
@@ -440,7 +440,7 @@ class Checkout(Component):
|
|
440
440
|
|
441
441
|
def _deselect_lines(self, lines):
|
442
442
|
lines.filtered(lambda x: not x.shopfloor_checkout_done).write(
|
443
|
-
{"
|
443
|
+
{"qty_picked": 0, "shopfloor_user_id": False}
|
444
444
|
)
|
445
445
|
|
446
446
|
def scan_line(self, picking_id, barcode, confirm_pack_all=False, confirm_lot=None):
|
@@ -454,7 +454,7 @@ class Checkout(Component):
|
|
454
454
|
several packs contain it, the endpoint will ask to scan a pack; if the
|
455
455
|
product is tracked by lot, to scan a lot.
|
456
456
|
|
457
|
-
Once move lines are found, their ``
|
457
|
+
Once move lines are found, their ``qty_picked`` is set to their reserved
|
458
458
|
quantity.
|
459
459
|
|
460
460
|
Transitions:
|
@@ -828,28 +828,28 @@ class Checkout(Component):
|
|
828
828
|
if not move_lines:
|
829
829
|
message = self.msg_store.record_not_found()
|
830
830
|
for move_line in move_lines:
|
831
|
-
|
832
|
-
if
|
831
|
+
qty_picked = quantity_func(move_line)
|
832
|
+
if qty_picked < 0:
|
833
833
|
message = {
|
834
834
|
"body": _("Negative quantity not allowed."),
|
835
835
|
"message_type": "error",
|
836
836
|
}
|
837
837
|
else:
|
838
838
|
new_line = self.env["stock.move.line"]
|
839
|
-
if
|
839
|
+
if qty_picked > 0:
|
840
840
|
new_line, qty_check = move_line._split_qty_to_be_done(
|
841
|
-
|
841
|
+
qty_picked,
|
842
842
|
split_partial=False,
|
843
843
|
result_package_id=False,
|
844
844
|
)
|
845
|
-
move_line.
|
845
|
+
move_line.qty_picked = qty_picked
|
846
846
|
if new_line:
|
847
847
|
selected_line_ids.append(new_line.id)
|
848
|
-
if
|
848
|
+
if qty_picked > move_line.quantity:
|
849
849
|
return self._response_for_select_package(
|
850
850
|
picking,
|
851
851
|
self.env["stock.move.line"].browse(selected_line_ids).exists(),
|
852
|
-
message=self.msg_store.
|
852
|
+
message=self.msg_store.line_scanned_qty_picked_higher_than_allowed(),
|
853
853
|
)
|
854
854
|
return self._response_for_select_package(
|
855
855
|
picking,
|
@@ -858,7 +858,7 @@ class Checkout(Component):
|
|
858
858
|
)
|
859
859
|
|
860
860
|
def reset_line_qty(self, picking_id, selected_line_ids, move_line_id):
|
861
|
-
"""Reset
|
861
|
+
"""Reset picked quantity of a move line to zero
|
862
862
|
|
863
863
|
Used to deselect a line in the "select_package" screen.
|
864
864
|
The selected_line_ids parameter is used to keep the selection of lines
|
@@ -873,7 +873,7 @@ class Checkout(Component):
|
|
873
873
|
)
|
874
874
|
|
875
875
|
def set_line_qty(self, picking_id, selected_line_ids, move_line_id):
|
876
|
-
"""Set
|
876
|
+
"""Set picked quantity of a move line to its reserved quantity
|
877
877
|
|
878
878
|
Used to select a line in the "select_package" screen.
|
879
879
|
The selected_line_ids parameter is used to keep the selection of lines
|
@@ -888,7 +888,7 @@ class Checkout(Component):
|
|
888
888
|
)
|
889
889
|
|
890
890
|
def set_custom_qty(self, picking_id, selected_line_ids, move_line_id, qty_done):
|
891
|
-
"""Change
|
891
|
+
"""Change picked quantity of a move line with a custom value
|
892
892
|
|
893
893
|
The selected_line_ids parameter is used to keep the selection of lines
|
894
894
|
stateless.
|
@@ -901,14 +901,14 @@ class Checkout(Component):
|
|
901
901
|
picking_id, selected_line_ids, [move_line_id], lambda __: qty_done
|
902
902
|
)
|
903
903
|
|
904
|
-
def
|
905
|
-
"""Switch
|
904
|
+
def _switch_line_qty_picked(self, picking, selected_lines, switch_lines):
|
905
|
+
"""Switch picked qty on lines and return to the 'select_package' state
|
906
906
|
|
907
|
-
If at least one of the lines to switch has a
|
908
|
-
to zero. If all the lines to switch have a zero
|
907
|
+
If at least one of the lines to switch has a picked qty, set them all
|
908
|
+
to zero. If all the lines to switch have a zero picked qty, switch them
|
909
909
|
to their quantity to deliver.
|
910
910
|
"""
|
911
|
-
if any(line.
|
911
|
+
if any(line.qty_picked for line in switch_lines):
|
912
912
|
return self._change_line_qty(
|
913
913
|
picking.id, selected_lines.ids, switch_lines.ids, lambda __: 0
|
914
914
|
)
|
@@ -923,7 +923,7 @@ class Checkout(Component):
|
|
923
923
|
def _increment_custom_qty(
|
924
924
|
self, picking, selected_lines, increment_lines, qty_increment
|
925
925
|
):
|
926
|
-
"""Increment the
|
926
|
+
"""Increment the picked quantity of a move line with a custom value
|
927
927
|
|
928
928
|
The selected_line parameter is used to keep the selection of lines
|
929
929
|
stateless.
|
@@ -936,22 +936,31 @@ class Checkout(Component):
|
|
936
936
|
picking.id,
|
937
937
|
selected_lines.ids,
|
938
938
|
increment_lines.ids,
|
939
|
-
lambda line: line.
|
939
|
+
lambda line: line.qty_picked + qty_increment,
|
940
940
|
)
|
941
941
|
|
942
942
|
@staticmethod
|
943
943
|
def _filter_lines_unpacked(move_line):
|
944
944
|
return (
|
945
|
-
move_line.
|
945
|
+
not move_line.picked or move_line.shopfloor_user_id
|
946
946
|
) and not move_line.shopfloor_checkout_done
|
947
947
|
|
948
948
|
@staticmethod
|
949
949
|
def _filter_lines_to_pack(move_line):
|
950
|
-
return move_line.
|
950
|
+
return move_line.picked and not move_line.shopfloor_checkout_done
|
951
951
|
|
952
952
|
@staticmethod
|
953
953
|
def _filter_lines_checkout_done(move_line):
|
954
|
-
|
954
|
+
# Starting from Odoo 18+, a move line part of a package level is not
|
955
|
+
# flagged as picked anymore (it'll be automatically at validation however).
|
956
|
+
# See '<stock.picking>._put_in_pack()' changes from
|
957
|
+
# https://github.com/odoo/odoo/commit/7dda6bb92715e
|
958
|
+
#
|
959
|
+
# Based on this new Odoo std behavior, we now consider a move line within
|
960
|
+
# a package level as picked (checkout is done).
|
961
|
+
return (
|
962
|
+
move_line.picked or move_line.package_level_id.is_done
|
963
|
+
) and move_line.shopfloor_checkout_done
|
955
964
|
|
956
965
|
def _is_package_allowed(self, picking, package):
|
957
966
|
"""Check if a package is allowed as a destination/delivery package.
|
@@ -966,7 +975,7 @@ class Checkout(Component):
|
|
966
975
|
return package in existing_packages
|
967
976
|
|
968
977
|
def _put_lines_in_package(self, picking, selected_lines, package):
|
969
|
-
"""Put the current selected lines with a
|
978
|
+
"""Put the current selected lines with a picked quantity in a package
|
970
979
|
|
971
980
|
Note: only packages which are already a delivery package for another
|
972
981
|
line of the stock picking can be selected. Packages which are the
|
@@ -983,8 +992,8 @@ class Checkout(Component):
|
|
983
992
|
|
984
993
|
def _put_lines_in_allowed_package(self, picking, lines_to_pack, package):
|
985
994
|
for line in lines_to_pack:
|
986
|
-
if line.
|
987
|
-
line.
|
995
|
+
if line.qty_picked < line.quantity:
|
996
|
+
line._split_partial_quantity_to_be_picked(line.qty_picked, {})
|
988
997
|
lines_to_pack.write(
|
989
998
|
{"result_package_id": package.id, "shopfloor_checkout_done": True}
|
990
999
|
)
|
@@ -1032,8 +1041,8 @@ class Checkout(Component):
|
|
1032
1041
|
of a selected line, the package is set to be the destination package of
|
1033
1042
|
all the lines to pack.
|
1034
1043
|
|
1035
|
-
When a product is scanned, it selects (set
|
1036
|
-
deselects (set
|
1044
|
+
When a product is scanned, it selects (set qty_picked = reserved qty) or
|
1045
|
+
deselects (set qty_picked = 0) the move lines for this product. Only
|
1037
1046
|
products not tracked by lot can use this.
|
1038
1047
|
|
1039
1048
|
When a lot is scanned, it does the same as for the products but based
|
@@ -1043,7 +1052,7 @@ class Checkout(Component):
|
|
1043
1052
|
package is created and set as destination of the lines to pack.
|
1044
1053
|
|
1045
1054
|
Lines to pack are move lines in the list of ``selected_line_ids``
|
1046
|
-
where ``
|
1055
|
+
where ``picked`` is set and have not been packed yet
|
1047
1056
|
(``shopfloor_checkout_done is False``).
|
1048
1057
|
|
1049
1058
|
Transitions:
|
@@ -1104,7 +1113,7 @@ class Checkout(Component):
|
|
1104
1113
|
If none are found, return the first line for that product.
|
1105
1114
|
"""
|
1106
1115
|
return next(
|
1107
|
-
(line for line in product_lines if line.
|
1116
|
+
(line for line in product_lines if line.qty_picked < line.quantity),
|
1108
1117
|
fields.first(product_lines),
|
1109
1118
|
)
|
1110
1119
|
|
@@ -1126,7 +1135,7 @@ class Checkout(Component):
|
|
1126
1135
|
self._find_line_to_increment(product_lines),
|
1127
1136
|
quantity_increment,
|
1128
1137
|
)
|
1129
|
-
return self.
|
1138
|
+
return self._switch_line_qty_picked(picking, selected_lines, product_lines)
|
1130
1139
|
|
1131
1140
|
def _scan_package_action_from_packaging(
|
1132
1141
|
self, picking, selected_lines, packaging, **kw
|
@@ -1141,7 +1150,7 @@ class Checkout(Component):
|
|
1141
1150
|
return self._increment_custom_qty(
|
1142
1151
|
picking, selected_lines, self._find_line_to_increment(lot_lines), 1
|
1143
1152
|
)
|
1144
|
-
return self.
|
1153
|
+
return self._switch_line_qty_picked(picking, selected_lines, lot_lines)
|
1145
1154
|
|
1146
1155
|
def _scan_package_action_from_serial(self, picking, selection_lines, lot, **kw):
|
1147
1156
|
# Search serial number is actually the same as searching for lot (as of v14...)
|
@@ -1221,7 +1230,7 @@ class Checkout(Component):
|
|
1221
1230
|
selected_lines,
|
1222
1231
|
message=self.msg_store.no_delivery_packaging_available(),
|
1223
1232
|
)
|
1224
|
-
response = self.
|
1233
|
+
response = self._check_allowed_qty_picked(picking, selected_lines)
|
1225
1234
|
if response:
|
1226
1235
|
return response
|
1227
1236
|
return self._response_for_select_delivery_packaging(picking, delivery_packaging)
|
@@ -1233,8 +1242,8 @@ class Checkout(Component):
|
|
1233
1242
|
the selected lines.
|
1234
1243
|
|
1235
1244
|
Selected lines are move lines in the list of ``move_line_ids`` where
|
1236
|
-
``
|
1237
|
-
(shopfloor_checkout_done is
|
1245
|
+
``picked`` is set and have no destination package
|
1246
|
+
(``shopfloor_checkout_done`` is not set).
|
1238
1247
|
|
1239
1248
|
Transitions:
|
1240
1249
|
* select_line: goes back to selection of lines to work on next lines
|
@@ -1253,8 +1262,8 @@ class Checkout(Component):
|
|
1253
1262
|
"""Process all selected lines without any package.
|
1254
1263
|
|
1255
1264
|
Selected lines are move lines in the list of ``move_line_ids`` where
|
1256
|
-
``
|
1257
|
-
(shopfloor_checkout_done is False).
|
1265
|
+
``picked`` is set and have no destination package
|
1266
|
+
(``shopfloor_checkout_done`` is False).
|
1258
1267
|
|
1259
1268
|
Transitions:
|
1260
1269
|
* select_line: goes back to selection of lines to work on next lines
|
@@ -1266,13 +1275,11 @@ class Checkout(Component):
|
|
1266
1275
|
if message:
|
1267
1276
|
return self._response_for_select_document(message=message)
|
1268
1277
|
selected_lines = self.env["stock.move.line"].browse(selected_line_ids).exists()
|
1269
|
-
|
1270
|
-
|
1271
|
-
)
|
1272
|
-
selected_lines_with_qty_done.write(
|
1278
|
+
picked_selected_lines = selected_lines.filtered(lambda line: line.picked)
|
1279
|
+
picked_selected_lines.write(
|
1273
1280
|
{"shopfloor_checkout_done": True, "result_package_id": False}
|
1274
1281
|
)
|
1275
|
-
response = self.
|
1282
|
+
response = self._check_allowed_qty_picked(picking, selected_lines)
|
1276
1283
|
if response:
|
1277
1284
|
return response
|
1278
1285
|
return self._response_for_select_line(
|
@@ -1298,21 +1305,21 @@ class Checkout(Component):
|
|
1298
1305
|
if message:
|
1299
1306
|
return self._response_for_select_document(message=message)
|
1300
1307
|
lines = self.env["stock.move.line"].browse(selected_line_ids).exists()
|
1301
|
-
response = self.
|
1308
|
+
response = self._check_allowed_qty_picked(picking, lines)
|
1302
1309
|
if response:
|
1303
1310
|
return response
|
1304
1311
|
return self._response_for_select_dest_package(picking, lines)
|
1305
1312
|
|
1306
|
-
def
|
1313
|
+
def _check_allowed_qty_picked(self, picking, lines):
|
1307
1314
|
for line in lines:
|
1308
|
-
# Do not allow to proceed if the
|
1315
|
+
# Do not allow to proceed if the qty_picked of
|
1309
1316
|
# any of the selected lines
|
1310
1317
|
# is higher than the quantity to do.
|
1311
|
-
if line.
|
1318
|
+
if line.qty_picked > line.quantity:
|
1312
1319
|
return self._response_for_select_package(
|
1313
1320
|
picking,
|
1314
1321
|
lines,
|
1315
|
-
message=self.msg_store.
|
1322
|
+
message=self.msg_store.selected_lines_qty_picked_higher_than_allowed(
|
1316
1323
|
line
|
1317
1324
|
),
|
1318
1325
|
)
|
@@ -1329,7 +1336,7 @@ class Checkout(Component):
|
|
1329
1336
|
def scan_dest_package(self, picking_id, selected_line_ids, barcode):
|
1330
1337
|
"""Scan destination package for lines
|
1331
1338
|
|
1332
|
-
Set the destination package on the selected lines
|
1339
|
+
Set the destination package on the `picked` selected lines if
|
1333
1340
|
the package is valid. It is valid when one of:
|
1334
1341
|
|
1335
1342
|
* it is already the destination package of another line of the stock.picking
|
@@ -1459,7 +1466,7 @@ class Checkout(Component):
|
|
1459
1466
|
|
1460
1467
|
All the move lines with the package as ``result_package_id`` have their
|
1461
1468
|
``result_package_id`` reset to the source package (default odoo behavior)
|
1462
|
-
and their ``
|
1469
|
+
and their ``qty_picked`` set to 0.
|
1463
1470
|
|
1464
1471
|
It flags ``shopfloor_checkout_done`` to False
|
1465
1472
|
so they have to be processed again.
|
@@ -1488,14 +1495,17 @@ class Checkout(Component):
|
|
1488
1495
|
for move_line in move_lines:
|
1489
1496
|
move_line.write(
|
1490
1497
|
{
|
1491
|
-
"
|
1498
|
+
"qty_picked": 0,
|
1499
|
+
"picked": False,
|
1492
1500
|
"result_package_id": move_line.package_id,
|
1493
1501
|
"shopfloor_checkout_done": False,
|
1494
1502
|
}
|
1495
1503
|
)
|
1496
1504
|
msg = _("Package cancelled")
|
1497
1505
|
if line:
|
1498
|
-
line.write(
|
1506
|
+
line.write(
|
1507
|
+
{"qty_picked": 0, "picked": False, "shopfloor_checkout_done": False}
|
1508
|
+
)
|
1499
1509
|
msg = _("Line cancelled")
|
1500
1510
|
return self._response_for_select_line(
|
1501
1511
|
picking, message={"message_type": "success", "body": msg}
|
@@ -1504,7 +1514,7 @@ class Checkout(Component):
|
|
1504
1514
|
def done(self, picking_id, confirmation=False):
|
1505
1515
|
"""Set the moves as done
|
1506
1516
|
|
1507
|
-
If some lines
|
1517
|
+
If some lines are not fully ``picked`` or no destination package set,
|
1508
1518
|
a confirmation is asked to the user.
|
1509
1519
|
|
1510
1520
|
Transitions:
|
@@ -1519,7 +1529,7 @@ class Checkout(Component):
|
|
1519
1529
|
return self._response_for_select_document(message=message)
|
1520
1530
|
lines = picking.move_line_ids
|
1521
1531
|
if not confirmation:
|
1522
|
-
if not all(line.
|
1532
|
+
if not all(line.qty_picked == line.quantity for line in lines):
|
1523
1533
|
return self._response_for_summary(
|
1524
1534
|
picking,
|
1525
1535
|
need_confirm=True,
|
@@ -4,8 +4,9 @@
|
|
4
4
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
5
5
|
from odoo import _, fields
|
6
6
|
from odoo.osv import expression
|
7
|
+
from odoo.tools import str2bool
|
7
8
|
|
8
|
-
from odoo.addons.base_rest.components.service import
|
9
|
+
from odoo.addons.base_rest.components.service import to_int
|
9
10
|
from odoo.addons.component.core import Component
|
10
11
|
|
11
12
|
from ..utils import to_float
|
@@ -1385,7 +1386,7 @@ class ShopfloorClusterPickingValidator(Component):
|
|
1385
1386
|
return {
|
1386
1387
|
"picking_batch_id": {"coerce": to_int, "required": True, "type": "integer"},
|
1387
1388
|
"move_line_id": {"coerce": to_int, "required": True, "type": "integer"},
|
1388
|
-
"zero": {"coerce":
|
1389
|
+
"zero": {"coerce": str2bool, "required": True, "type": "boolean"},
|
1389
1390
|
}
|
1390
1391
|
|
1391
1392
|
def skip_line(self):
|
@@ -2,9 +2,10 @@
|
|
2
2
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
3
3
|
from odoo import _, fields
|
4
4
|
from odoo.osv import expression
|
5
|
+
from odoo.tools import str2bool
|
5
6
|
from odoo.tools.float_utils import float_is_zero
|
6
7
|
|
7
|
-
from odoo.addons.base_rest.components.service import
|
8
|
+
from odoo.addons.base_rest.components.service import to_int
|
8
9
|
from odoo.addons.component.core import Component
|
9
10
|
|
10
11
|
|
@@ -211,25 +212,23 @@ class Delivery(Component):
|
|
211
212
|
if product_qty: # defined with lot/product/packaging scan
|
212
213
|
# With a product_qty we process only one move line,
|
213
214
|
# so one move to deal with regarding the qty
|
214
|
-
|
215
|
+
qty_picked = lines.move_id.product_id.uom_id._compute_quantity(
|
215
216
|
product_qty, lines.move_id.product_uom
|
216
217
|
)
|
217
|
-
|
218
|
+
for line in lines:
|
219
|
+
line.qty_picked += qty_picked
|
218
220
|
return self._action_picking_done(
|
219
221
|
lines.picking_id, force=allow_prepackaged_product
|
220
222
|
)
|
221
223
|
for line in lines:
|
222
224
|
# note: the package level is automatically set to "is_done" when
|
223
|
-
# the
|
224
|
-
line.
|
225
|
+
# the line is fully picked
|
226
|
+
line.picked = True
|
225
227
|
picking = fields.first(lines.mapped("picking_id"))
|
226
228
|
return self._action_picking_done(picking, force=allow_prepackaged_product)
|
227
229
|
|
228
230
|
def _reset_lines(self, lines):
|
229
|
-
|
230
|
-
# note: the package level "is_done" field is automatically unset
|
231
|
-
# when the qty_done is not full
|
232
|
-
line.qty_done = 0
|
231
|
+
lines.picked = False
|
233
232
|
|
234
233
|
def _deliver_package(self, picking, package, location):
|
235
234
|
lines = package.move_line_ids.filtered(
|
@@ -256,7 +255,7 @@ class Delivery(Component):
|
|
256
255
|
message = self._check_picking_type(lines.mapped("picking_id"))
|
257
256
|
if message:
|
258
257
|
return self._response_for_deliver(location=location, message=message)
|
259
|
-
# TODO add a message if any of the lines already
|
258
|
+
# TODO add a message if any of the lines are already picked
|
260
259
|
new_picking = fields.first(lines.mapped("picking_id"))
|
261
260
|
if self._set_lines_done(lines):
|
262
261
|
return self._response_for_deliver(
|
@@ -269,7 +268,7 @@ class Delivery(Component):
|
|
269
268
|
# in the picking type, and then use IN (ids)
|
270
269
|
domain = []
|
271
270
|
if no_qty_done:
|
272
|
-
domain.append(("
|
271
|
+
domain.append(("picked", "=", False))
|
273
272
|
return domain
|
274
273
|
|
275
274
|
def _lines_from_lot_domain(
|
@@ -419,8 +418,8 @@ class Delivery(Component):
|
|
419
418
|
location=location,
|
420
419
|
message=self.msg_store.product_not_unitary_in_package_scan_package(),
|
421
420
|
)
|
422
|
-
# We focus only on lines on which we can increase the '
|
423
|
-
lines = lines.filtered(lambda x: (x.
|
421
|
+
# We focus only on lines on which we can increase the 'qty_picked'
|
422
|
+
lines = lines.filtered(lambda x: (x.qty_picked + product_qty) <= x.quantity)
|
424
423
|
# Filter lines to keep only ones from one delivery operation
|
425
424
|
# (we do not want to process lines of another delivery operation)
|
426
425
|
lines = lines._filter_on_picking(picking)
|
@@ -716,7 +715,7 @@ class Delivery(Component):
|
|
716
715
|
"Product Unit of Measure"
|
717
716
|
)
|
718
717
|
no_quantities_done = all(
|
719
|
-
float_is_zero(move_line.
|
718
|
+
float_is_zero(move_line.qty_picked, precision_digits=precision_digits)
|
720
719
|
for move_line in picking.move_line_ids.filtered(
|
721
720
|
lambda m: m.state not in ("done", "cancel")
|
722
721
|
)
|
@@ -799,7 +798,7 @@ class ShopfloorDeliveryValidator(Component):
|
|
799
798
|
def done(self):
|
800
799
|
return {
|
801
800
|
"picking_id": {"coerce": to_int, "required": True, "type": "integer"},
|
802
|
-
"confirm": {"coerce":
|
801
|
+
"confirm": {"coerce": str2bool, "required": False, "type": "boolean"},
|
803
802
|
}
|
804
803
|
|
805
804
|
|
@@ -6,9 +6,10 @@ import functools
|
|
6
6
|
from collections import defaultdict
|
7
7
|
|
8
8
|
from odoo.fields import first
|
9
|
+
from odoo.tools import str2bool
|
9
10
|
from odoo.tools.float_utils import float_compare, float_is_zero
|
10
11
|
|
11
|
-
from odoo.addons.base_rest.components.service import
|
12
|
+
from odoo.addons.base_rest.components.service import to_int
|
12
13
|
from odoo.addons.component.core import Component
|
13
14
|
|
14
15
|
from ..exceptions import ConcurentWorkOnTransfer
|
@@ -1802,7 +1803,7 @@ class ShopfloorZonePickingValidator(Component):
|
|
1802
1803
|
def is_zero(self):
|
1803
1804
|
return {
|
1804
1805
|
"move_line_id": {"coerce": to_int, "required": True, "type": "integer"},
|
1805
|
-
"zero": {"coerce":
|
1806
|
+
"zero": {"coerce": str2bool, "required": True, "type": "boolean"},
|
1806
1807
|
}
|
1807
1808
|
|
1808
1809
|
def stock_issue(self):
|
@@ -372,7 +372,7 @@ ul.auto-toc {
|
|
372
372
|
!! This file is generated by oca-gen-addon-readme !!
|
373
373
|
!! changes will be overwritten. !!
|
374
374
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
375
|
-
!! source digest: sha256:
|
375
|
+
!! source digest: sha256:534d443b8feb0fd2548ede9663e260ceb8dcfb20686a39d06022ee92bcc6d209
|
376
376
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
377
377
|
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/license-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/stock-logistics-shopfloor/tree/18.0/shopfloor"><img alt="OCA/stock-logistics-shopfloor" src="https://img.shields.io/badge/github-OCA%2Fstock--logistics--shopfloor-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/stock-logistics-shopfloor-18-0/stock-logistics-shopfloor-18-0-shopfloor"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/stock-logistics-shopfloor&target_branch=18.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
|
378
378
|
<p>Shopfloor is a barcode scanner application for internal warehouse
|
@@ -23,37 +23,38 @@ from . import test_actions_stock
|
|
23
23
|
# from . import test_cluster_picking_stock_issue
|
24
24
|
# from . import test_cluster_picking_change_pack_lot
|
25
25
|
# from . import test_cluster_picking_unload
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
26
|
+
from . import test_checkout_base
|
27
|
+
from . import test_checkout_scan
|
28
|
+
from . import test_checkout_select
|
29
|
+
from . import test_checkout_scan_line
|
30
|
+
from . import test_checkout_scan_line_no_prefill_qty
|
31
|
+
from . import test_checkout_scan_line_base
|
32
|
+
from . import test_checkout_scan_dest_location
|
33
|
+
from . import test_checkout_select_line
|
34
|
+
from . import test_checkout_select_package_base
|
35
|
+
from . import test_checkout_set_qty
|
36
|
+
from . import test_checkout_scan_package_action
|
37
|
+
from . import test_checkout_scan_package_action_no_prefill_qty
|
38
|
+
from . import test_checkout_new_package
|
39
|
+
from . import test_checkout_no_package
|
40
|
+
from . import test_checkout_auto_post
|
41
|
+
from . import test_checkout_list_delivery_packaging
|
42
|
+
from . import test_checkout_list_package
|
43
|
+
from . import test_checkout_summary
|
44
|
+
from . import test_checkout_change_packaging
|
45
|
+
from . import test_checkout_cancel_line
|
46
|
+
from . import test_checkout_done
|
47
|
+
from . import test_delivery_base
|
48
|
+
from . import test_delivery_done
|
49
|
+
from . import test_delivery_scan_deliver
|
50
|
+
from . import test_delivery_reset_qty_done_line
|
51
|
+
from . import test_delivery_reset_qty_done_pack
|
52
|
+
from . import test_delivery_set_qty_done_pack
|
53
|
+
from . import test_delivery_set_qty_done_line
|
54
|
+
from . import test_delivery_sublocation
|
55
|
+
from . import test_delivery_list_stock_picking
|
56
|
+
from . import test_delivery_select
|
57
|
+
|
57
58
|
# from . import test_location_content_transfer_base
|
58
59
|
# from . import test_location_content_transfer_start
|
59
60
|
# from . import test_location_content_transfer_get_work
|
@@ -182,8 +182,10 @@ class CommonCase(BaseCommonCase):
|
|
182
182
|
)
|
183
183
|
# this method adds the quantity to the current quantity, so remove it
|
184
184
|
quantity -= sum(quants.mapped("quantity"))
|
185
|
+
if not quantity:
|
186
|
+
return
|
185
187
|
cls.env["stock.quant"]._update_available_quantity(
|
186
|
-
product, location, quantity, package_id=package, lot_id=lot
|
188
|
+
product, location, quantity=quantity, package_id=package, lot_id=lot
|
187
189
|
)
|
188
190
|
|
189
191
|
@classmethod
|