addons-cm/stock_picking_batch_collect/tests/test_picking_collected.py
GitHub Copilot 9c81cb986d
[IMP] stock_picking_batch_collect: collected checks on transfers, ordered quantity, delivery slips report
- The collected checks also apply to transfers outside a batch, opt-in per
  operation type ("Require Collected Lines"), with the batch restrictions of
  the settings. A per-product toggle in the transfer's Operations tab collects
  all its lines.
- Read-only ordered quantity from the sale line on every batch and transfer
  view, since the weighed demand overwrites it. Adds a dependency on
  sale_stock; a migration fills it in the summary of open batches.
- "Delivery Slips" report on the batch: all its delivery slips in one PDF.

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

137 lines
4.8 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_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())