Skip to content

Commit 9d6959e

Browse files
urvisha-serpentcsMurtaza-OSI
authored andcommitted
[MIG] stock_exception: Migration to 17.0
Adding some more info to the description for when exceptions are checked.
1 parent 3b74ae7 commit 9d6959e

File tree

8 files changed

+132
-3
lines changed

8 files changed

+132
-3
lines changed

stock_exception/README.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@ Contributors
6464

6565
- Tharathip Chaweewongphan <[email protected]>
6666

67+
- Open Source Integrators http://www.opensourceintegrators.com
68+
69+
- Urvisha Desai [email protected]
70+
- Nikul Chaudhary [email protected]
71+
6772
Maintainers
6873
-----------
6974

stock_exception/models/stock.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ def action_confirm(self):
4343
return rec._popup_exceptions()
4444
return super().action_confirm()
4545

46+
def button_validate(self):
47+
for rec in self:
48+
if rec.detect_exceptions() and not rec.ignore_exception:
49+
return rec._popup_exceptions()
50+
return super().button_validate()
51+
4652
@api.model
4753
def _get_popup_action(self):
4854
action = self.env.ref("stock_exception.action_stock_exception_confirm")
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,6 @@
11
- Tharathip Chaweewongphan \<<[email protected]>\>
2+
3+
* Open Source Integrators <http://www.opensourceintegrators.com>
4+
5+
* Urvisha Desai <[email protected]>
6+
* Nikul Chaudhary <[email protected]>

stock_exception/readme/DESCRIPTION.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
This module allows you attach several customizable exceptions to your
22
stock picking in a way that you can filter pickings by exceptions type
3-
and fix them.
3+
and fix them. Exceptions are checked via a scheduled action as well as
4+
during confirmation and validation.
45

56
This is especially useful in an scenario for mass stock picking import,
67
because it's likely some pickings have errors when you import them (like

stock_exception/static/description/index.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,11 @@ <h2><a class="toc-backref" href="#toc-entry-3">Authors</a></h2>
407407
<h2><a class="toc-backref" href="#toc-entry-4">Contributors</a></h2>
408408
<ul class="simple">
409409
<li>Tharathip Chaweewongphan &lt;<a class="reference external" href="mailto:tharathipc&#64;ecosoft.co.th">tharathipc&#64;ecosoft.co.th</a>&gt;</li>
410+
<li>Open Source Integrators <a class="reference external" href="http://www.opensourceintegrators.com">http://www.opensourceintegrators.com</a><ul>
411+
<li>Urvisha Desai <a class="reference external" href="mailto:udesai&#64;opensourceintegrators.com">udesai&#64;opensourceintegrators.com</a></li>
412+
<li>Nikul Chaudhary <a class="reference external" href="mailto:nchaudhary&#64;opensourceintegrators.com">nchaudhary&#64;opensourceintegrators.com</a></li>
413+
</ul>
414+
</li>
410415
</ul>
411416
</div>
412417
<div class="section" id="maintainers">

stock_exception/tests/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import test_stock_exception
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# Copyright 2024 Open Source Integrators
2+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
3+
from odoo.tests import Form
4+
from odoo.tests.common import TransactionCase
5+
6+
7+
class TestStockPicking(TransactionCase):
8+
def setUp(self):
9+
super().setUp()
10+
stock_location = self.env.ref("stock.stock_location_stock")
11+
customer_location = self.env.ref("stock.stock_location_customers")
12+
product = self.env.ref("product.product_product_4")
13+
picking_type = self.env.ref("stock.picking_type_out")
14+
# Create a picking in 'assigned' state with exceptions
15+
self.picking_with_exceptions = self.env["stock.picking"].create(
16+
{
17+
"name": "Test Picking With Exceptions 2",
18+
"state": "assigned",
19+
"location_id": stock_location.id,
20+
"location_dest_id": customer_location.id,
21+
"picking_type_id": picking_type.id,
22+
"move_ids": [
23+
(
24+
0,
25+
0,
26+
{
27+
"name": "Test Move With Exceptions",
28+
"product_id": product.id,
29+
"product_uom_qty": 1,
30+
"quantity": 1,
31+
"product_uom": self.env.ref("uom.product_uom_unit").id,
32+
"location_id": stock_location.id,
33+
"location_dest_id": customer_location.id,
34+
},
35+
)
36+
],
37+
"ignore_exception": False,
38+
}
39+
)
40+
41+
self.exception = self.env["exception.rule"].create(
42+
{
43+
"name": "Demand Quantity not positive",
44+
"description": "Demand Quantity not positive",
45+
"sequence": 50,
46+
"model": "stock.move",
47+
"code": "if self.product_uom_qty == 0: failed=True",
48+
"active": True,
49+
}
50+
)
51+
52+
def test_detect_exceptions(self):
53+
# Test that exceptions are detected for the picking with exceptions
54+
exceptions = self.picking_with_exceptions.detect_exceptions()
55+
self.assertFalse(exceptions, "Exceptions shouldn't be detected")
56+
move = self.picking_with_exceptions.move_ids[0]
57+
move._reverse_field()
58+
move.write({"product_uom_qty": 0})
59+
exceptions = self.picking_with_exceptions.detect_exceptions()
60+
self.assertTrue(exceptions, "Exceptions should be detected")
61+
62+
def test_button_validate_with_exceptions(self):
63+
move = self.picking_with_exceptions.move_ids[0]
64+
move.write({"product_uom_qty": 0})
65+
move.write({"quantity": 1})
66+
# Result returns a dict in case it detects an exception,
67+
# otherwise it returns 'True'
68+
result = self.picking_with_exceptions.button_validate()
69+
70+
# Verify the result of the button_validate action
71+
# If exceptions detected, the result should be different from 'True'
72+
self.assertNotEqual(
73+
result, True, f"Expected result not to be True, but got {type(result)}"
74+
)
75+
76+
def test_onchange_ignore_exception(self):
77+
# Change state and verify onchange behavior for picking
78+
self.picking_with_exceptions.onchange_ignore_exception()
79+
self.picking_with_exceptions._reverse_field()
80+
self.picking_with_exceptions.write(
81+
{"state": "waiting", "ignore_exception": True}
82+
)
83+
self.assertTrue(self.picking_with_exceptions.ignore_exception)
84+
85+
def test_confirm_picking(self):
86+
self.stock_exception = self.env["exception.rule"].create(
87+
{
88+
"name": "No Partner",
89+
"description": "No Partner",
90+
"sequence": 10,
91+
"model": "stock.picking",
92+
"exception_type": "by_py_code",
93+
"code": "if not self.partner_id: failed=True",
94+
}
95+
)
96+
exception_action = self.picking_with_exceptions.action_confirm()
97+
self.assertEqual(exception_action.get("res_model"), "stock.exception.confirm")
98+
exception_form = Form(
99+
self.env["stock.exception.confirm"].with_context(
100+
**exception_action.get("context")
101+
),
102+
)
103+
stock_exception = exception_form.save()
104+
stock_exception.ignore = True
105+
self.picking_with_exceptions.test_all_draft_pickings()
106+
stock_exception.action_confirm()

stock_exception/views/stock_view.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
class="alert alert-danger"
2727
role="alert"
2828
style="margin-bottom:0px;"
29-
attrs="{'invisible': [('exceptions_summary', '=', False)]}"
29+
invisible="not exceptions_summary"
3030
>
3131
<p>
3232
<strong
@@ -46,7 +46,7 @@
4646
<xpath expr="//field[@name='date_deadline']/.." position="inside">
4747
<field
4848
name="ignore_exception"
49-
states="waiting,confirmed,assigned"
49+
invisible="state not in ('waiting','confirmed','assigned')"
5050
groups='base_exception.group_exception_rule_manager'
5151
/>
5252
<field name="exception_ids" widget="many2many_tags" readonly="True" />

0 commit comments

Comments
 (0)