Initial commit: Odoo 18.0-20251222 extra-addons
This commit is contained in:
531
sale_manual_delivery/tests/test_manual_delivery.py
Executable file
531
sale_manual_delivery/tests/test_manual_delivery.py
Executable file
@@ -0,0 +1,531 @@
|
||||
# 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",
|
||||
)
|
||||
Reference in New Issue
Block a user