Merge pull request '[IMP] stock_picking_batch_collect: cantidad demandada en las líneas de movimiento' (#22) from 18.0-imp-stock_picking_batch_collect-demand into 18.0
Some checks failed
CI / lint (push) Successful in 32s
CI / test (push) Failing after 11m2s
CI / review (push) Has been skipped

Reviewed-on: #22
This commit is contained in:
snt 2026-10-10 16:55:16 +00:00
commit 8a029464eb
11 changed files with 93 additions and 1 deletions

View file

@ -761,6 +761,8 @@ last_purchase_price_compute_type != "manual_update" # Para auto-cálculo
`product_pricelist_total_margin`, `product_origin_char`, `l10n_es_edi_tbai_reagyp_recibidas`.
`product_origin` (OCA) sustituido por `product_origin_char` (custom).
- **2026-06-04**: `product_sale_price_from_pricelist` aplica descuentos de proveedor desde `supplierinfo`.
- **2026-10-10**: `stock_picking_batch_collect` (v18.0.2.2.0) — columna de cantidad demandada en
las listas de líneas de movimiento (operaciones detalladas de lote y albarán, vista operario).
- **2026-10-04**: `stock_picking_batch_collect` (v18.0.2.1.0) — checks de recogido en albaranes
sueltos (activables por tipo de operación), columna de cantidad pedida en la venta (depende de
`sale_stock`) e informe *Albaranes* del lote.

View file

@ -29,6 +29,11 @@ producto y una vista a pantalla completa para el almacén.
comparar lo pedido con lo preparado en la misma pantalla. Está en las
operaciones detalladas, la vista de operario, la pestaña *Operations* y el
resumen por producto del lote, y en el albarán.
- Columna **Cantidad demandada** (``move_demand_qty``), de sólo lectura, en las
listas de líneas de movimiento, que no la traen de serie: las operaciones
detalladas del lote y del albarán y la vista de operario. Es la demanda del
movimiento completo, así que se repite en cada línea de un movimiento
repartido en varias (lotes, ubicaciones).
- Informe **Albaranes** en el lote: todos sus albaranes de entrega en un PDF.
Las columnas se añaden con ``optional="show"`` en la vista de líneas del lote
@ -136,6 +141,8 @@ Uso
9. La columna **Cantidad pedida** muestra lo que pidió el cliente, frente a la
demanda (ya ajustada al peso) y la cantidad preparada. En el resumen por
producto del lote es la suma de los pedidos.
La columna **Cantidad demandada** está junto a ella en todas las vistas,
también en la vista de operario.
10. **Imprimir > Albaranes** en el lote genera un único PDF con el albarán de
entrega de cada uno de sus traslados (salvo los cancelados), ordenados por

View file

@ -2,7 +2,7 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{ # noqa: B018
"name": "Stock Picking Batch Collect",
"version": "18.0.2.1.0",
"version": "18.0.2.2.0",
"category": "Warehouse",
"summary": "Collect batch operations: operator view, extra columns and product summary",
"author": "Odoo Community Association (OCA), Criptomart",

View file

@ -105,6 +105,7 @@ msgid "Created on"
msgstr "Creado el"
#. module: stock_picking_batch_collect
#: model:ir.model.fields,field_description:stock_picking_batch_collect.field_stock_move_line__move_demand_qty
#: model:ir.model.fields,field_description:stock_picking_batch_collect.field_stock_picking_batch_summary_line__qty_demanded
msgid "Demanded Quantity"
msgstr "Cantidad demandada"
@ -282,3 +283,8 @@ msgid ""
msgstr ""
"Hay que marcar como recogidas las operaciones de %(picking)s antes de validarlo.\n"
"Productos pendientes: %(products)s"
#. module: stock_picking_batch_collect
#: model_terms:ir.ui.view,arch_db:stock_picking_batch_collect.view_move_line_batch_operator
msgid "Demand"
msgstr "Demanda"

View file

@ -104,6 +104,7 @@ msgid "Created on"
msgstr "Noiz sortua"
#. module: stock_picking_batch_collect
#: model:ir.model.fields,field_description:stock_picking_batch_collect.field_stock_move_line__move_demand_qty
#: model:ir.model.fields,field_description:stock_picking_batch_collect.field_stock_picking_batch_summary_line__qty_demanded
msgid "Demanded Quantity"
msgstr "Eskatutako kantitatea"
@ -282,3 +283,8 @@ msgid ""
msgstr ""
"%(picking)s balidatu aurretik, bere eragiketak jasota gisa markatu behar dira.\n"
"Zain dauden produktuak: %(products)s"
#. module: stock_picking_batch_collect
#: model_terms:ir.ui.view,arch_db:stock_picking_batch_collect.view_move_line_batch_operator
msgid "Demand"
msgstr "Eskaria"

View file

@ -41,6 +41,11 @@ class StockMoveLine(models.Model):
digits="Product Unit of Measure",
compute="_compute_sale_ordered_qty",
)
move_demand_qty = fields.Float(
string="Demanded Quantity",
digits="Product Unit of Measure",
compute="_compute_move_demand_qty",
)
@api.depends("move_id.sale_ordered_qty", "move_id.product_uom", "product_uom_id")
def _compute_sale_ordered_qty(self):
@ -53,6 +58,18 @@ class StockMoveLine(models.Model):
else:
line.sale_ordered_qty = 0.0
@api.depends("move_id.product_uom_qty", "move_id.product_uom", "product_uom_id")
def _compute_move_demand_qty(self):
"""The demand of the whole move: every line of a split move shows it."""
for line in self:
move = line.move_id
if move.product_uom and line.product_uom_id:
line.move_demand_qty = move.product_uom._compute_quantity(
move.product_uom_qty, line.product_uom_id, round=False
)
else:
line.move_demand_qty = 0.0
def write(self, vals):
res = super().write(vals)
if vals.get("is_collected"):

View file

@ -23,6 +23,11 @@ producto y una vista a pantalla completa para el almacén.
comparar lo pedido con lo preparado en la misma pantalla. Está en las
operaciones detalladas, la vista de operario, la pestaña *Operations* y el
resumen por producto del lote, y en el albarán.
- Columna **Cantidad demandada** (``move_demand_qty``), de sólo lectura, en las
listas de líneas de movimiento, que no la traen de serie: las operaciones
detalladas del lote y del albarán y la vista de operario. Es la demanda del
movimiento completo, así que se repite en cada línea de un movimiento
repartido en varias (lotes, ubicaciones).
- Informe **Albaranes** en el lote: todos sus albaranes de entrega en un PDF.
Las columnas se añaden con ``optional="show"`` en la vista de líneas del lote

View file

@ -36,6 +36,8 @@ Uso
9. La columna **Cantidad pedida** muestra lo que pidió el cliente, frente a la
demanda (ya ajustada al peso) y la cantidad preparada. En el resumen por
producto del lote es la suma de los pedidos.
La columna **Cantidad demandada** está junto a ella en todas las vistas,
también en la vista de operario.
10. **Imprimir > Albaranes** en el lote genera un único PDF con el albarán de
entrega de cada uno de sus traslados (salvo los cancelados), ordenados por

View file

@ -110,6 +110,50 @@ class TestPickingCollected(TransactionCase):
self.assertEqual(move.sale_ordered_qty, 2.0)
self.assertEqual(move.move_line_ids.sale_ordered_qty, 2.0)
def test_move_line_demand_follows_the_move(self):
picking = self._create_sale_picking(2.0)
move = picking.move_ids
line = move.move_line_ids
self.assertEqual(line.move_demand_qty, 2.0)
gram = self.env.ref("uom.product_uom_gram")
line.product_uom_id = gram
self.assertEqual(line.move_demand_qty, 2000.0)
move.product_uom_qty = 3.0
self.assertEqual(line.move_demand_qty, 3000.0)
def test_move_line_demand_without_sale(self):
"""Unlike the ordered quantity, the demand needs no sale order."""
picking = self.env["stock.picking"].create(
{
"picking_type_id": self.picking_type_out.id,
"location_id": self.stock_location.id,
"location_dest_id": self.env.ref("stock.stock_location_customers").id,
"move_ids": [
Command.create(
{
"name": self.product.name,
"product_id": self.product.id,
"product_uom_qty": 4.0,
"product_uom": self.product.uom_id.id,
"location_id": self.stock_location.id,
"location_dest_id": self.env.ref(
"stock.stock_location_customers"
).id,
}
)
],
}
)
picking.action_confirm()
picking.action_assign()
line = picking.move_ids.move_line_ids
self.assertEqual(line.move_demand_qty, 4.0)
self.assertEqual(line.sale_ordered_qty, 0.0)
def test_batch_summary_ordered_quantity(self):
pickings = self._create_sale_picking(2.0) | self._create_sale_picking(3.0)
batch = self.env["stock.picking.batch"].create(

View file

@ -32,6 +32,7 @@
<field name="reference" readonly="1" optional="hide"/>
<field name="picking_partner_id" readonly="1" optional="show"/>
<field name="sale_ordered_qty" string="Ordered" readonly="1" optional="show"/>
<field name="move_demand_qty" string="Demand" readonly="1" optional="show"/>
<field name="quantity" string="Cant."/>
<!-- Loaded so `_onchange_quantity_manual` reaches the server. -->
<field name="picked" column_invisible="True"/>
@ -82,6 +83,7 @@
</xpath>
<xpath expr="//field[@name='quantity']" position="before">
<field name="sale_ordered_qty" readonly="1" optional="show"/>
<field name="move_demand_qty" readonly="1" optional="show"/>
</xpath>
<xpath expr="//field[@name='quantity']" position="after">
<!-- Loaded so `_onchange_quantity_manual` reaches the server. -->

View file

@ -25,6 +25,7 @@
<xpath expr="//field[@name='quantity']" position="before">
<field name="sale_ordered_qty" readonly="1" optional="show"
column_invisible="context.get('picking_code') == 'incoming'"/>
<field name="move_demand_qty" readonly="1" optional="show"/>
</xpath>
<xpath expr="//field[@name='quantity']" position="after">
<field name="is_collected" widget="boolean_toggle" optional="show"