Files
Odoo-18.0-20251222/sale_manual_delivery/tests/test_manual_delivery.py
tocmo0nlord adbe430761
Some checks failed
pre-commit / pre-commit (push) Has been cancelled
tests / Detect unreleased dependencies (push) Has been cancelled
tests / test with OCB (push) Has been cancelled
tests / test with Odoo (push) Has been cancelled
Initial commit: Odoo 18.0-20251222 extra-addons
2026-03-13 20:43:25 +00:00

532 lines
20 KiB
Python
Executable File

# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from datetime import datetime
from dateutil.relativedelta import relativedelta
from odoo.exceptions import UserError
from odoo.addons.sale.tests.common import TestSaleCommonBase
class TestSaleStock(TestSaleCommonBase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.partner = cls.env.ref("base.res_partner_1")
cls.product = cls.env.ref("product.product_delivery_01")
cls.product2 = cls.env.ref("product.product_delivery_02")
cls.product3 = cls.env.ref("product.product_order_01")
cls.carrier1 = cls.env.ref("delivery.delivery_carrier")
cls.carrier2 = cls.env.ref("delivery.delivery_local_delivery")
cls.stock_location = cls.env.ref("stock.stock_location_stock")
cls.env["stock.quant"]._update_available_quantity(
cls.product, cls.stock_location, 100
)
cls.env.user_demo = cls.env.ref("base.user_demo")
def _manual_delivery_wizard(self, records, vals=None):
if not vals:
vals = {}
return (
self.env["manual.delivery"]
.with_context(
active_model=records._name,
active_ids=records.ids,
)
.create(vals)
)
def test_00_sale_manual_delivery(self):
"""
Test SO's manual delivery; we do it with a user without admin rights
"""
model_user_order = self.env["sale.order"].with_user(self.env.user_demo)
order = model_user_order.create(
{
"partner_id": self.partner.id,
"partner_invoice_id": self.partner.id,
"partner_shipping_id": self.partner.id,
"order_line": [
(
0,
0,
{
"name": self.product.name,
"product_id": self.product.id,
"product_uom_qty": 5.0,
"product_uom": self.product.uom_id.id,
"price_unit": self.product.list_price,
},
)
],
"manual_delivery": True,
}
)
# confirm our standard so, check the picking
order.action_confirm()
self.assertFalse(
order.picking_ids,
'No picking should be created for "manual delivery" orders',
)
# Raise error when user try to modify sale order in confirmd stage.
with self.assertRaises(UserError):
order.write({"manual_delivery": False})
# open the manual delivery wizard
action = order.action_manual_delivery_wizard()
self.assertEqual(action["res_model"], "manual.delivery")
# create a manual delivery for all ordered quantity
self._manual_delivery_wizard(order).confirm()
# check picking is created
self.assertTrue(
order.picking_ids,
'Picking should be created after "manual delivery" wizard call',
)
# create a manual delivery, nothing left to ship
wizard = self._manual_delivery_wizard(order)
self.assertFalse(
wizard.line_ids,
"After picking creation for all products, "
"no lines should be left in the wizard",
)
wizard.confirm()
self.assertEqual(
len(order.picking_ids), 1.0, "Picking number should remain 1.0"
)
def test_01_sale_standard_delivery(self):
"""
Test SO's standard delivery
"""
order = self.env["sale.order"].create(
{
"partner_id": self.partner.id,
"partner_invoice_id": self.partner.id,
"partner_shipping_id": self.partner.id,
"order_line": [
(
0,
0,
{
"name": self.product.name,
"product_id": self.product.id,
"product_uom_qty": 5.0,
"product_uom": self.product.uom_id.id,
"price_unit": self.product.list_price,
},
)
],
"manual_delivery": False,
}
)
# confirm our standard so, check the picking
order.action_confirm()
self.assertTrue(
order.picking_ids,
'Picking should be created for "standard delivery" orders',
)
# deliver completely
pick = order.picking_ids
pick.action_assign()
pick.move_line_ids.write({"quantity": 5})
pick.button_validate()
# Check quantity delivered
del_qty = sum(sol.qty_delivered for sol in order.order_line)
self.assertEqual(del_qty, 5.0, "Delivery quantity doesn't match")
def test_02_sale_various_manual_delivery(self):
"""
Test SO's various manual delivery
"""
order = self.env["sale.order"].create(
{
"partner_id": self.partner.id,
"partner_invoice_id": self.partner.id,
"partner_shipping_id": self.partner.id,
"order_line": [
(
0,
0,
{
"name": self.product.name,
"product_id": self.product.id,
"product_uom_qty": 5.0,
"product_uom": self.product.uom_id.id,
"price_unit": self.product.list_price,
},
)
],
"manual_delivery": True,
}
)
# confirm our standard so, check the picking
order.action_confirm()
self.assertFalse(
order.picking_ids,
'No picking should be created for "manual delivery" orders',
)
# create a manual delivery for part of ordered quantity
wizard = self._manual_delivery_wizard(order)
wizard.line_ids.write({"quantity": 2.0})
wizard.confirm()
# checking has_pending_delivery for Create Delivery button to appear
self.assertTrue(order.has_pending_delivery)
# check picking is created
self.assertEqual(
len(order.picking_ids),
1,
'Picking should be created after "manual delivery" wizard call',
)
# deliver completely
pick = order.picking_ids
pick.action_assign()
pick.move_line_ids.write({"quantity": 2})
pick.button_validate()
# Check quantity delivered
del_qty = sum(sol.qty_delivered for sol in order.order_line)
self.assertEqual(del_qty, 2.0, "Delivery quantity doesn't match")
# a manual delivery with qty 0 shouldn't do anything
wizard = self._manual_delivery_wizard(order)
wizard.line_ids.write({"quantity": 0.0})
wizard.confirm()
self.assertEqual(
len(order.picking_ids),
1.0,
"No picking should've been created",
)
# try to create a manual delivery with more quantity than the ordered
wizard = self._manual_delivery_wizard(order)
with self.assertRaises(UserError):
wizard.line_ids.write({"quantity": 10.0})
wizard.confirm()
# create a manual delivery, 3.0 left to ship
wizard = self._manual_delivery_wizard(order)
wizard.line_ids.write({"quantity": 3.0})
wizard.confirm()
# checking has_pending_delivery for Create Delivery button to hide
self.assertFalse(order.has_pending_delivery)
self.assertEqual(
len(order.picking_ids),
2.0,
"Picking number doesn't match",
)
def test_03_sale_selected_lines(self):
"""
Test SO's various manual delivery
"""
order1 = self.env["sale.order"].create(
{
"partner_id": self.partner.id,
"partner_invoice_id": self.partner.id,
"partner_shipping_id": self.partner.id,
"order_line": [
(
0,
0,
{
"name": self.product.name,
"product_id": self.product.id,
"product_uom_qty": 1.0,
"product_uom": self.product.uom_id.id,
"price_unit": self.product.list_price,
},
)
],
"manual_delivery": True,
}
)
order2 = self.env["sale.order"].create(
{
"partner_id": self.partner.id,
"partner_invoice_id": self.partner.id,
"partner_shipping_id": self.partner.id,
"order_line": [
(
0,
0,
{
"name": self.product2.name,
"product_id": self.product2.id,
"product_uom_qty": 2.0,
"product_uom": self.product2.uom_id.id,
"price_unit": self.product2.list_price,
},
)
],
"manual_delivery": True,
}
)
order3 = self.env["sale.order"].create(
{
"partner_id": self.partner.id,
"partner_invoice_id": self.partner.id,
"partner_shipping_id": self.partner.id,
"order_line": [
(
0,
0,
{
"name": self.product3.name,
"product_id": self.product.id,
"product_uom_qty": 3.0,
"product_uom": self.product3.uom_id.id,
"price_unit": self.product3.list_price,
},
)
],
"manual_delivery": True,
}
)
# confirm our standard so, check the picking
order1.action_confirm()
order2.action_confirm()
order3.action_confirm()
some_lines = order1.order_line | order3.order_line
all_lines = order1.order_line | order2.order_line | order3.order_line
# create a manual delivery for part of ordered quantity
wizard = self._manual_delivery_wizard(some_lines)
self.assertEqual(sum(wizard.line_ids.mapped("quantity")), 4.0)
wizard.confirm()
# check picking is created
self.assertTrue(
order3.picking_ids,
'Picking should be created after "manual delivery" wizard call',
)
self.assertEqual(
len(order3.picking_ids.move_ids),
1,
"Different sales orders should still create different pickings",
)
self.assertFalse(
order2.picking_ids,
'Picking should not be created after "manual delivery" wizard call',
)
# test action undelivered
undelivered = self.env["sale.order.line"].search(
[
("qty_to_procure", ">", 0),
("state", "=", "sale"),
("id", "in", all_lines.ids),
]
)
self.assertEqual(
undelivered,
order2.order_line,
"Bad pending qty to deliver filter",
)
def test_03_sale_multi_delivery(self):
self.env["stock.quant"]._update_available_quantity(
self.product2, self.stock_location, 100
)
order = self.env["sale.order"].create(
{
"partner_id": self.partner.id,
"partner_invoice_id": self.partner.id,
"partner_shipping_id": self.partner.id,
"order_line": [
(
0,
0,
{
"name": self.product.name,
"product_id": self.product.id,
"product_uom_qty": 10.0,
"product_uom": self.product.uom_id.id,
"price_unit": self.product.list_price,
},
),
(
0,
0,
{
"name": self.product2.name,
"product_id": self.product2.id,
"product_uom_qty": 10.0,
"product_uom": self.product2.uom_id.id,
"price_unit": self.product2.list_price,
},
),
],
"manual_delivery": True,
}
)
# confirm our standard so, check the picking
order.action_confirm()
self.assertFalse(
order.picking_ids,
'No picking should be created for "manual delivery" orders',
)
# create a manual delivery for part of ordered quantity
date_now = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
wizard = self._manual_delivery_wizard(
order.order_line[0],
{"carrier_id": order.carrier_id.id, "date_planned": date_now},
)
wizard.line_ids.write({"quantity": 2.0})
wizard.confirm()
# check picking is created
self.assertEqual(
len(order.picking_ids),
1,
'Picking should be created after "manual delivery" wizard call',
)
first_picking = order.picking_ids
self.assertEqual(
first_picking.scheduled_date.replace(
hour=0, minute=0, second=0, microsecond=0
),
date_now,
)
# create a second manual delivery for next week
date_next_week = date_now + relativedelta(weeks=1)
wizard = self._manual_delivery_wizard(
order.order_line[1],
{"carrier_id": order.carrier_id.id, "date_planned": date_next_week},
)
wizard.line_ids.write({"quantity": 3.0})
wizard.confirm()
self.assertEqual(
len(order.picking_ids),
2,
"Sale Manual Delivery: second picking should be created after"
' "manual delivery" wizard call with different date',
)
second_picking = order.picking_ids - first_picking
self.assertEqual(
second_picking.scheduled_date.replace(
hour=0, minute=0, second=0, microsecond=0
),
date_next_week,
)
# create a third manual delivery for today (should be mixed with first)
new_date_now = datetime.now()
wizard = self._manual_delivery_wizard(
order.order_line[0],
{"carrier_id": order.carrier_id.id, "date_planned": new_date_now},
)
wizard.line_ids.write({"quantity": 5.0})
wizard.confirm()
self.assertEqual(
len(order.picking_ids),
2,
"Sale Manual Delivery: new moves should be merged in first picking"
' after "manual delivery" wizard call with same date',
)
self.assertEqual(
sum(first_picking.mapped("move_ids.product_uom_qty")),
7,
)
def test_04_sale_single_picking(self):
"""
Test SO's various manual delivery
"""
order = self.env["sale.order"].create(
{
"partner_id": self.partner.id,
"partner_invoice_id": self.partner.id,
"partner_shipping_id": self.partner.id,
"order_line": [
(
0,
0,
{
"name": self.product.name,
"product_id": self.product.id,
"product_uom_qty": 1.0,
"product_uom": self.product.uom_id.id,
"price_unit": self.product.list_price,
},
),
(
0,
0,
{
"name": self.product2.name,
"product_id": self.product2.id,
"product_uom_qty": 2.0,
"product_uom": self.product2.uom_id.id,
"price_unit": self.product2.list_price,
},
),
],
"manual_delivery": True,
}
)
# confirm our standard so, check the picking
order.action_confirm()
# create a manual delivery for part of ordered quantity
wizard = self._manual_delivery_wizard(order.order_line)
wizard.confirm()
self.assertEqual(
len(order.picking_ids), 1.0, "Delivery: picking number should be 1.0"
)
def test_05_sale_multi_carrier(self):
order = self.env["sale.order"].create(
{
"partner_id": self.partner.id,
"partner_invoice_id": self.partner.id,
"partner_shipping_id": self.partner.id,
"order_line": [
(
0,
0,
{
"name": self.product.name,
"product_id": self.product.id,
"product_uom_qty": 10.0,
"product_uom": self.product.uom_id.id,
"price_unit": self.product.list_price,
},
),
],
"manual_delivery": True,
"carrier_id": self.carrier1.id,
}
)
# confirm our standard so, check the picking
order.action_confirm()
# create a manual delivery for part of ordered quantity
wizard = self._manual_delivery_wizard(order, {"carrier_id": self.carrier1.id})
wizard.line_ids.write({"quantity": 2.0})
wizard.confirm()
# check picking is created
self.assertEqual(
len(order.picking_ids),
1,
'Picking should be created after "manual delivery" wizard call',
)
first_picking = order.picking_ids
self.assertEqual(
first_picking.carrier_id,
order.carrier_id,
"Picking carrier should be the one in the order",
)
# create a second manual delivery with a different carrier
wizard = self._manual_delivery_wizard(order, {"carrier_id": self.carrier2.id})
wizard.line_ids.write({"quantity": 2.0})
wizard.confirm()
self.assertEqual(
len(order.picking_ids),
2,
"A different picking should've been created, as the carrier is different",
)
second_picking = order.picking_ids - first_picking
self.assertEqual(
second_picking.carrier_id,
self.carrier2,
"Picking carrier should be the one selected",
)
# create a third manual delivery for (should be mixed with first)
wizard = self._manual_delivery_wizard(order, {"carrier_id": self.carrier1.id})
wizard.line_ids.write({"quantity": 2.0})
wizard.confirm()
self.assertEqual(
len(order.picking_ids),
2,
"The first picking should be re-used",
)