[IMP] stock: improve order logic of stock.move.line

Currently, the order of transfer lines makes no sense for a picker
(it's in the order of the creation of the line). We want to have the
lines of the detailed operation in the same order as the picker will be
picking the products, so we order by source location, destination
location, sequence, and then by id (i.e. creation time) respectively
instead.

Also the printing report of the batch transfer is on too many pages,
it's one page by location, but we always group on 'from location'.
So it would be better not to split by location and keep the report
on the least number of pages possible.

task-2496324
odoo/enterprise#21921

closes odoo/odoo#79446

X-original-commit: 9b120caa2a5cd5e2487d663a180b486b5bdb201b
Related: odoo/enterprise#22144
Signed-off-by: Tiffany Chang <tic@odoo.com>
This commit is contained in:
brsy-odoo
2021-11-08 07:07:59 +00:00
committed by Bruno-brsy
parent 477a535e03
commit eaae9ea8ec
4 changed files with 75 additions and 77 deletions
+1 -1
View File
@@ -14,7 +14,7 @@ class StockMoveLine(models.Model):
_name = "stock.move.line"
_description = "Product Moves (Stock Move Line)"
_rec_name = "product_id"
_order = "result_package_id desc, id"
_order = "result_package_id desc, location_id asc, location_dest_id asc, picking_id asc, id"
picking_id = fields.Many2one(
'stock.picking', 'Transfer', auto_join=True,
@@ -84,48 +84,44 @@
</tr>
</thead>
<tbody>
<t t-foreach="o.move_ids_without_package" t-as="move">
<!-- In case you come across duplicated lines, ask NIM or LAP -->
<t t-foreach="move.move_line_ids.sorted(key=lambda ml: ml.location_id.id)" t-as="ml">
<tr>
<td>
<span t-field="ml.product_id.display_name"/><br/>
<span t-field="ml.product_id.description_picking"/>
</td>
<td>
<span t-if="o.state != 'done'" t-field="ml.product_uom_qty"/>
<span t-if="o.state == 'done'" t-field="ml.qty_done"/>
<span t-field="ml.product_uom_id" groups="uom.group_uom"/>
</td>
<td t-if="o.picking_type_id.code != 'incoming'" groups="stock.group_stock_multi_locations">
<span t-esc="ml.location_id.display_name"/>
<t t-if="ml.package_id">
<span t-field="ml.package_id"/>
</t>
</td>
<td t-if="o.picking_type_id.code != 'outgoing'" groups="stock.group_stock_multi_locations">
<div>
<span t-field="ml.location_dest_id"/>
<t t-if="ml.result_package_id">
<span t-field="ml.result_package_id"/>
</t>
</div>
</td>
<td class=" text-center h6" t-if="has_serial_number">
<div t-if="has_serial_number and (ml.lot_id or ml.lot_name)" t-esc="ml.lot_id.name or ml.lot_name" t-options="{'widget': 'barcode', 'humanreadable': 1, 'width': 400, 'height': 100, 'img_style': 'width:100%;height:35px;'}"/>
</td>
<td class="text-center" t-if="has_barcode">
<t t-if="product_barcode != move.product_id.barcode">
<span t-if="move.product_id and move.product_id.barcode">
<div t-field="move.product_id.barcode" t-options="{'widget': 'barcode', 'symbology': 'auto', 'width': 400, 'height': 100, 'quiet': 0, 'img_style': 'height:35px;'}"/>
</span>
<t t-set="product_barcode" t-value="move.product_id.barcode"/>
<!-- In case you come across duplicated lines, ask NIM or LAP -->
<t t-foreach="o.move_line_ids_without_package" t-as="ml">
<tr>
<td>
<span t-field="ml.product_id.display_name"/><br/>
<span t-field="ml.product_id.description_picking"/>
</td>
<td>
<span t-if="o.state != 'done'" t-field="ml.product_uom_qty"/>
<span t-if="o.state == 'done'" t-field="ml.qty_done"/>
<span t-field="ml.product_uom_id" groups="uom.group_uom"/>
</td>
<td t-if="o.picking_type_id.code != 'incoming'" groups="stock.group_stock_multi_locations">
<span t-esc="ml.location_id.display_name"/>
<t t-if="ml.package_id">
<span t-field="ml.package_id"/>
</t>
</td>
</tr>
</t>
</td>
<td t-if="o.picking_type_id.code != 'outgoing'" groups="stock.group_stock_multi_locations">
<div>
<span t-field="ml.location_dest_id"/>
<t t-if="ml.result_package_id">
<span t-field="ml.result_package_id"/>
</t>
</div>
</td>
<td class=" text-center h6" t-if="has_serial_number">
<div t-if="has_serial_number and (ml.lot_id or ml.lot_name)" t-field="ml.lot_id.name or ml.lot_name" t-options="{'widget': 'barcode', 'humanreadable': 1, 'width': 400, 'height': 100, 'img_style': 'width:100%;height:35px;'}"/>
</td>
<td class="text-center" t-if="has_barcode">
<t t-if="product_barcode != ml.product_id.barcode">
<span t-if="ml.product_id and ml.product_id.barcode">
<div t-field="ml.product_id.barcode" t-options="{'widget': 'barcode', 'symbology': 'auto', 'width': 400, 'height': 100, 'quiet': 0, 'img_style': 'height:35px;'}"/>
</span>
<t t-set="product_barcode" t-value="ml.product_id.barcode"/>
</t>
</td>
</tr>
</t>
</tbody>
</table>
+1 -1
View File
@@ -1968,7 +1968,7 @@ class TestStockFlow(TestStockCommon):
# Validates the two receipts and checks the move lines' lot.
(receipt_1 | receipt_2).button_validate()
lots = self.env['stock.production.lot'].search([('product_id', '=', product_lot.id)])
lots = self.env['stock.production.lot'].search([('product_id', '=', product_lot.id)], order='name asc')
self.assertEqual(len(lots), 5)
lot1, lot2, lot3, lot4, lot5 = lots
self.assertEqual(lot1.name, 'lot-001')
@@ -48,34 +48,40 @@
</tbody>
</table>
<p style="page-break-after: always;"/>
<t t-foreach="locations" t-as="location">
<t t-set="loc_move_line" t-value="move_line_ids.filtered(lambda x: x.location_id==location)"/>
<t t-set="products" t-value="loc_move_line.mapped('product_id')"/>
<h3><span t-field="o.name"/></h3>
<div t-if="o.user_id">
<strong>Responsible:</strong>
<span t-field="o.user_id"/>
</div><br/>
<h4><strong>To take from: <span t-field="location.display_name"/></strong></h4>
<table class="table table-condensed">
<thead>
<tr>
<th>Product</th>
<th>Quantity</th>
<th width="27%">To</th>
<th width="23%">Transfer</th>
<th t-if="has_serial_number" width="15%">
<strong>Lot/Serial Number</strong>
</th>
<th t-if="has_barcode" width="15%" class="text-center">
<strong>Product Barcode</strong>
</th>
<th t-if="has_package" width="15%">
<strong>Package</strong>
</th>
</tr>
</thead>
<h3><span t-field="o.name"/></h3>
<div t-if="o.user_id">
<strong>Responsible:</strong>
<span t-field="o.user_id"/>
</div><br/>
<table class="table table-condensed">
<thead>
<tr>
<th>Product</th>
<th>Quantity</th>
<th width="20%">Transfer</th>
<th t-if="has_serial_number" width="15%">
<strong>Lot/Serial Number</strong>
</th>
<th t-if="has_barcode" width="15%" class="text-center">
<strong>Product Barcode</strong>
</th>
<th t-if="has_package" width="15%">
<strong>Package</strong>
</th>
</tr>
</thead>
<t t-foreach="locations" t-as="location">
<t t-set="loc_move_line" t-value="move_line_ids.filtered(lambda x: x.location_id==location)"/>
<t t-set="products" t-value="loc_move_line.mapped('product_id')"/>
<tbody>
<tr>
<td style="background-color:lightgrey" colspan="6" >
<p style="margin:0px"><strong>FROM</strong>
<span t-esc="loc_move_line.mapped('location_id').display_name"/></p>
<p style="margin:0px"><strong>TO</strong>
<span t-esc="loc_move_line.mapped('location_dest_id').display_name"/></p>
</td>
</tr>
<tr t-foreach="loc_move_line" t-as="move_operation">
<td>
<span t-field="move_operation.display_name"/>
@@ -94,9 +100,6 @@
</t>
<span t-field="move_operation.uom_id" groups="move_operation.group_uom"/>
</td>
<td>
<span t-esc="move_operation.mapped('location_dest_id').display_name"/>
</td>
<td>
<span t-esc="move_operation.mapped('picking_id').display_name"/>
</td>
@@ -111,14 +114,13 @@
<td t-if="has_package" width="15%">
<span t-field="move_operation.package_id"/>
<t t-if="move_operation.result_package_id">
→ <span t-field="move_operation.result_package_id"/>
<strong>→</strong> <span t-field="move_operation.result_package_id"/>
</t>
</td>
</tr>
</tbody>
</table>
<p style="page-break-after: always;"/>
</t>
</t>
</table>
</div>
</t>
</t>