addons-cm/stock_picking_batch_collect/tests/test_picking_collected.py
GitHub Copilot 18cfd38347
Some checks failed
CI / lint (pull_request) Successful in 32s
CI / test (pull_request) Failing after 3m15s
CI / review (pull_request) Has been skipped
[IMP] stock_picking_batch_collect: demanded quantity on the move line lists
The move lists already show the demand, the move line ones do not: the
detailed operations of the batch and of the transfer, and the operator
(Basket Assembly) view. Adds a read-only column with the demand of the
line's move, in the unit of the line, next to the ordered quantity.

Closes #21

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 18:34:56 +02:00

181 lines
6.5 KiB
Python

# Copyright 2026 Criptomart
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import Command
from odoo.exceptions import UserError
from odoo.tests import TransactionCase
from odoo.tests import tagged
@tagged("-at_install", "post_install")
class TestPickingCollected(TransactionCase):
"""Collected checks and ordered quantities on transfers outside a batch."""
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.stock_location = cls.env.ref("stock.stock_location_stock")
cls.picking_type_out = cls.env.ref("stock.picking_type_out")
cls.picking_type_out.collected_check_required = True
cls.env.company.write(
{
"batch_detailed_restriction_enabled": True,
"batch_detailed_restriction_scope": "processed",
"batch_summary_restriction_enabled": False,
}
)
kg = cls.env.ref("uom.product_uom_kgm")
cls.product = cls.env["product.product"].create(
{
"name": "Collected Pears",
"is_storable": True,
"uom_id": kg.id,
"uom_po_id": kg.id,
}
)
cls.env["stock.quant"]._update_available_quantity(
cls.product, cls.stock_location, 50.0
)
cls.partner = cls.env["res.partner"].create({"name": "Pear Lover"})
def _create_sale_picking(self, qty=2.0):
order = self.env["sale.order"].create(
{
"partner_id": self.partner.id,
"order_line": [
Command.create(
{"product_id": self.product.id, "product_uom_qty": qty}
)
],
}
)
order.action_confirm()
picking = order.picking_ids
picking.action_assign()
return picking
def test_loose_picking_blocks_until_collected(self):
picking = self._create_sale_picking()
with self.assertRaisesRegex(UserError, self.product.display_name):
picking.button_validate()
picking.move_ids.is_collected = True
picking.button_validate()
self.assertEqual(picking.state, "done")
def test_picking_type_without_check_is_not_blocked(self):
self.picking_type_out.collected_check_required = False
picking = self._create_sale_picking()
picking.button_validate()
self.assertEqual(picking.state, "done")
def test_batch_picking_follows_the_batch_restriction(self):
"""The batch summary flag is not required by the loose transfer check."""
self.env.company.batch_summary_restriction_enabled = True
picking = self._create_sale_picking()
batch = self.env["stock.picking.batch"].create(
{"picking_ids": [Command.set(picking.ids)]}
)
batch.action_confirm()
picking.move_ids.is_collected = True
with self.assertRaisesRegex(UserError, "product summary"):
batch.action_done()
def test_collecting_the_move_collects_its_lines(self):
picking = self._create_sale_picking()
move = picking.move_ids
self.assertFalse(move.is_collected)
move.is_collected = True
self.assertTrue(all(move.move_line_ids.mapped("is_collected")))
self.assertTrue(move.picked)
move.move_line_ids.is_collected = False
self.assertFalse(move.is_collected)
def test_ordered_quantity_survives_weighing(self):
picking = self._create_sale_picking(2.0)
move = picking.move_ids
move.move_line_ids.write({"quantity": 1.5, "picked": True})
self.assertEqual(move.product_uom_qty, 1.5)
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(
{"picking_ids": [Command.set(pickings.ids)]}
)
pickings[0].move_ids.move_line_ids.write({"quantity": 1.5, "picked": True})
batch._compute_summary_line_ids()
line = batch.summary_line_ids
self.assertEqual(line.qty_ordered, 5.0)
self.assertEqual(line.qty_demanded, 4.5)
def test_report_prints_every_delivery_slip(self):
pickings = self._create_sale_picking(2.0) | self._create_sale_picking(3.0)
batch = self.env["stock.picking.batch"].create(
{"picking_ids": [Command.set(pickings.ids)]}
)
html, _report_format = self.env["ir.actions.report"]._render_qweb_html(
"stock_picking_batch_collect.report_batch_deliveryslip", batch.ids
)
for picking in pickings:
self.assertIn(picking.name, html.decode())