Skip to content

Commit

Permalink
[FIX] stock_secondary_unit: partial delivery
Browse files Browse the repository at this point in the history
  • Loading branch information
jcadhoc committed Feb 5, 2025
1 parent 498e678 commit 26b78b5
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 18 deletions.
2 changes: 1 addition & 1 deletion stock_secondary_unit/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
{
"name": "Stock Secondary Unit",
"summary": "Get product quantities in a secondary unit",
"version": "16.0.1.1.2",
"version": "16.0.1.1.3",
"development_status": "Production/Stable",
"category": "stock",
"website": "https://github.com/OCA/stock-logistics-warehouse",
Expand Down
2 changes: 2 additions & 0 deletions stock_secondary_unit/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@
from . import product_product
from . import product_template
from . import stock_move
from . import stock_move_line
from . import stock_picking
87 changes: 87 additions & 0 deletions stock_secondary_unit/models/stock_move_line.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
from odoo.tools import float_is_zero
from odoo.addons.stock.models.stock_move_line import StockMoveLine

def _new_get_aggregated_product_quantities(self, **kwargs):
""" Returns a dictionary of products (key = id+name+description+uom) and corresponding values of interest.
Allows aggregation of data across separate move lines for the same product. This is expected to be useful
in things such as delivery reports. Dict key is made as a combination of values we expect to want to group
the products by (i.e. so data is not lost). This function purposely ignores lots/SNs because these are
expected to already be properly grouped by line.
returns: dictionary {product_id+name+description+uom: {product, name, description, qty_done, product_uom}, ...}
"""
aggregated_move_lines = {}

# Loops to get backorders, backorders' backorders, and so and so...
backorders = self.env['stock.picking']
pickings = self.picking_id
while pickings.backorder_ids:
backorders |= pickings.backorder_ids
pickings = pickings.backorder_ids

for move_line in self:

if kwargs.get('except_package') and move_line.result_package_id:
continue
aggregated_properties = self._get_aggregated_properties(move_line=move_line)
line_key = f"{aggregated_properties['line_key']}_{move_line.id}"
uom = aggregated_properties['product_uom']
qty_done = move_line.product_uom_id._compute_quantity(move_line.qty_done, uom)
if line_key not in aggregated_move_lines:
qty_ordered = None
if backorders and not kwargs.get('strict'):
qty_ordered = move_line.move_id.product_uom_qty
# Filters on the aggregation key (product, description and uom) to add the
# quantities delayed to backorders to retrieve the original ordered qty.
following_move_lines = backorders.move_line_ids.filtered(
lambda ml: self._get_aggregated_properties(move=ml.move_id)['line_key'] == line_key
)
qty_ordered += sum(following_move_lines.move_id.mapped('product_uom_qty'))
# Remove the done quantities of the other move lines of the stock move
previous_move_lines = move_line.move_id.move_line_ids.filtered(
lambda ml: self._get_aggregated_properties(move=ml.move_id)['line_key'] == line_key and ml.id != move_line.id
)
qty_ordered -= sum(map(lambda m: m.product_uom_id._compute_quantity(m.qty_done, aggregated_properties['product_uom']), previous_move_lines))
aggregated_move_lines[line_key] = {
**aggregated_properties,
'qty_done': qty_done,
'qty_ordered': qty_ordered or qty_done,
'product': move_line.product_id,
'secondary_uom_qty': move_line.secondary_uom_qty,
'secondary_uom_id': move_line.secondary_uom_id.name

}
else:
aggregated_move_lines[line_key]['qty_ordered'] += qty_done
aggregated_move_lines[line_key]['qty_done'] += qty_done

# Does the same for empty move line to retrieve the ordered qty. for partially done moves
# (as they are splitted when the transfer is done and empty moves don't have move lines).
if kwargs.get('strict'):
return aggregated_move_lines
pickings = (self.picking_id | backorders)
for empty_move in pickings.move_ids:
to_bypass = False
if not (empty_move.product_uom_qty and float_is_zero(empty_move.quantity_done, precision_rounding=empty_move.product_uom.rounding)):
continue
if empty_move.state != "cancel":
if empty_move.state != "confirmed" or empty_move.move_line_ids:
continue
else:
to_bypass = True
aggregated_properties = self._get_aggregated_properties(move=empty_move)
line_key = aggregated_properties['line_key']

if line_key not in aggregated_move_lines and not to_bypass:
qty_ordered = empty_move.product_uom_qty
aggregated_move_lines[line_key] = {
**aggregated_properties,
'qty_done': False,
'qty_ordered': qty_ordered,
'product': empty_move.product_id,
}
elif line_key in aggregated_move_lines:
aggregated_move_lines[line_key]['qty_ordered'] += empty_move.product_uom_qty
# import pdb;pdb.set_trace()
return aggregated_move_lines

StockMoveLine._get_aggregated_product_quantities = _new_get_aggregated_product_quantities
29 changes: 29 additions & 0 deletions stock_secondary_unit/models/stock_picking.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from odoo import models


class StockPicking(models.Model):
_inherit = "stock.picking"

def _create_backorder(self):
res = super(StockPicking, self)._create_backorder()
for original_move in self.move_ids:
corresponding_move = next(
(
move
for move in res.move_ids
if move.product_id == original_move.product_id
),
None,
)
if corresponding_move and corresponding_move.secondary_uom_qty:
# To avoid rounding errors, Saving the current value of product_uom_qty
# before recalculating the secondary unit. Afterward,
# I'll restore the original value
product_uom_qty = corresponding_move.product_uom_qty
corresponding_move.with_context(
bypass_compute_field_qty=True
)._compute_secondary_uom_qty()
corresponding_move.product_uom_qty = product_uom_qty
else:
continue
return res
34 changes: 17 additions & 17 deletions stock_secondary_unit/report/report_deliveryslip.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,8 @@
<!-- Copyright 2018 Tecnativa - Sergio Teruel
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<odoo>
<template
id="report_delivery_document"
inherit_id="stock.report_delivery_document"
priority="8"
>
<xpath
expr='//table[@t-if="o.state!=&apos;done&apos;"]/thead/tr/th'
position="after"
>
<template id="report_delivery_document" inherit_id="stock.report_delivery_document" priority="8">
<xpath expr='//table[@t-if="o.state!=&apos;done&apos;"]/thead/tr/th' position="after">
<th>
<strong>Secondary Qty</strong>
</th>
Expand All @@ -21,24 +14,31 @@
<span t-field="move.secondary_uom_id.name" />
</td>
</xpath>
<xpath
expr='//table[@t-if="o.move_line_ids and o.state==&apos;done&apos;"]/thead/tr/th'
position="after"
>
<xpath expr='//table[@t-if="o.move_line_ids and o.state==&apos;done&apos;"]/thead/tr/th' position="after">
<th>
<strong>Secondary Qty</strong>
</th>
</xpath>
</template>
<template
id="stock_report_delivery_has_serial_move_line"
inherit_id="stock.stock_report_delivery_has_serial_move_line"
>
<template id="stock_report_delivery_has_serial_move_line" inherit_id="stock.stock_report_delivery_has_serial_move_line">
<xpath expr="//span[@t-field='move_line.product_id']/.." position="after">
<td>
<span t-field="move_line.secondary_uom_qty" />
<span t-field="move_line.secondary_uom_id" />
</td>
</xpath>
</template>

<template id="stock_report_delivery_aggregated_move_lines_ux" inherit_id="stock.stock_report_delivery_aggregated_move_lines">
<xpath expr="//td[@name='move_line_aggregated_qty_done']" position="before">
<td class="text-center" name="move_line_aggregated_secondary_unit">
<t t-if="aggregated_lines[line]['qty_done']">
<span t-esc="aggregated_lines[line]['secondary_uom_qty']"/>
<span t-esc="aggregated_lines[line]['secondary_uom_id']"/>

</t>
</td>

</xpath>
</template>
</odoo>

0 comments on commit 26b78b5

Please sign in to comment.