Skip to content

Commit 2221a40

Browse files
committed
feat: stock_resupply_order
1 parent d1ffd9c commit 2221a40

File tree

5 files changed

+133
-128
lines changed

5 files changed

+133
-128
lines changed

stock_resupply_order/__manifest__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
# Copyright 2024-2025 Foodles (https://www.foodles.co/).
1+
# Copyright 2025 Foodles (https://www.foodles.co/).
22
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
33
{
44
"name": "Stock resupply order",
55
"summary": """
66
A module that takes the existing stock in the destination
77
location into account when creating procurements.
88
""",
9-
"category": "",
10-
"version": "14.0.1.0.0",
9+
"category": "Stock Management",
10+
"version": "14.0.1.0.1",
1111
"author": "Foodles, Odoo Community Association (OCA)",
1212
"website": "https://github.com/OCA/stock-logistics-warehouse",
1313
"license": "AGPL-3",
Lines changed: 40 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,50 @@
11
<?xml version="1.0" encoding="utf-8" ?>
22
<!--
3-
Copyright 2024 Foodles (https://www.foodles.co/).
3+
Copyright 2025 Foodles (https://www.foodles.co/).
44
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
55
-->
66
<odoo>
7-
<data>
8-
<record model="stock.location" id="location_stock_demo">
9-
<field name="name">Stock</field>
10-
<field name="usage">internal</field>
11-
</record>
7+
<record model="stock.location" id="location_stock_demo">
8+
<field name="name">Stock</field>
9+
<field name="usage">internal</field>
10+
</record>
1211

13-
<record model="stock.location" id="location_dest_demo">
14-
<field name="name">Destination location</field>
15-
<field name="usage">internal</field>
16-
</record>
12+
<record model="stock.location" id="location_dest_demo">
13+
<field name="name">Destination location</field>
14+
<field name="usage">internal</field>
15+
</record>
1716

18-
<record model="stock.picking.type" id="picking_type_demo">
19-
<field name="name">Stock to Destination</field>
20-
<field name="sequence_code">DEST-STOCK</field>
21-
<field name="code">outgoing</field>
22-
<field name="show_operations">True</field>
23-
<field name="use_create_lots">False</field>
24-
<field name="use_existing_lots">True</field>
25-
<field name="warehouse_id" ref="stock.warehouse0" />
26-
<field
27-
name="default_location_src_id"
28-
ref="stock_resupply_order.location_stock_demo"
29-
/>
30-
<field
31-
name="default_location_dest_id"
32-
ref="stock_resupply_order.location_dest_demo"
33-
/>
34-
</record>
17+
<record model="stock.picking.type" id="picking_type_demo">
18+
<field name="name">Stock to Destination</field>
19+
<field name="sequence_code">DEST-STOCK</field>
20+
<field name="code">outgoing</field>
21+
<field name="show_operations">True</field>
22+
<field name="use_create_lots">False</field>
23+
<field name="use_existing_lots">True</field>
24+
<field name="warehouse_id" ref="stock.warehouse0" />
25+
<field
26+
name="default_location_src_id"
27+
ref="stock_resupply_order.location_stock_demo"
28+
/>
29+
<field
30+
name="default_location_dest_id"
31+
ref="stock_resupply_order.location_dest_demo"
32+
/>
33+
</record>
3534

36-
<record model="stock.location.route" id="route_demo">
37-
<field name="name">stock resupply order</field>
38-
<field name="product_categ_selectable">True</field>
39-
</record>
35+
<record model="stock.location.route" id="route_demo">
36+
<field name="name">stock resupply order</field>
37+
<field name="product_categ_selectable">True</field>
38+
</record>
4039

41-
<record model="stock.rule" id="rule_demo">
42-
<field name="name">Pull</field>
43-
<field name="action">pull</field>
44-
<field name="picking_type_id" ref="picking_type_demo" />
45-
<field
46-
name="location_src_id"
47-
ref="stock_resupply_order.location_stock_demo"
48-
/>
49-
<field name="location_id" ref="stock_resupply_order.location_dest_demo" />
50-
<field name="procure_method">make_to_stock</field>
51-
<field name="warehouse_id" ref="stock.warehouse0" />
52-
<field name="route_id" ref="route_demo" />
53-
</record>
54-
</data>
40+
<record model="stock.rule" id="rule_demo">
41+
<field name="name">Pull</field>
42+
<field name="action">pull</field>
43+
<field name="picking_type_id" ref="picking_type_demo" />
44+
<field name="location_src_id" ref="stock_resupply_order.location_stock_demo" />
45+
<field name="location_id" ref="stock_resupply_order.location_dest_demo" />
46+
<field name="procure_method">make_to_stock</field>
47+
<field name="warehouse_id" ref="stock.warehouse0" />
48+
<field name="route_id" ref="route_demo" />
49+
</record>
5550
</odoo>

stock_resupply_order/models/stock_resupply_order.py

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class StockResupplyOrder(models.Model):
2727
default=lambda self: self.env.company,
2828
)
2929

30-
stock_resupply_order_lines = fields.One2many(
30+
stock_resupply_order_line_ids = fields.One2many(
3131
"stock.resupply.order.line",
3232
inverse_name="stock_resupply_order_id",
3333
help="All product quantities desired at the given location",
@@ -78,17 +78,14 @@ def action_run(self):
7878
return self.procurement_group_id
7979

8080
self.procurement_group_id = self.env["procurement.group"].create(
81-
{
82-
"name": (f"Resupply Order {self.location_id.name}"),
83-
"move_type": "one",
84-
}
81+
self._get_procurement_group_parameters()
8582
)
8683

8784
quant_groups = self._get_existing_quants()
8885

8986
procurements = []
9087

91-
for line in self.stock_resupply_order_lines:
88+
for line in self.stock_resupply_order_line_ids:
9289
# service products have no tracking/lot and cannot be run in procurement
9390
if line.product_id.product_tmpl_id.type == "service":
9491
continue
@@ -118,11 +115,12 @@ def action_run(self):
118115

119116
return self.procurement_group_id
120117

118+
@api.model
121119
def _get_available_quantity_for_product(
122120
self, quant_groups, stock_resupply_order_line
123121
):
124122
try:
125-
# I could not find a way to merge stock_resupply_order_lines
123+
# I could not find a way to merge stock_resupply_order_line_ids
126124
# with the quant_groups query, so it is retrieved with a product
127125
# id search here. Not ideal, but it works.
128126
group = next(
@@ -135,10 +133,25 @@ def _get_available_quantity_for_product(
135133
except StopIteration:
136134
return 0
137135

136+
def _get_procurement_group_parameters(self):
137+
"""
138+
Values to pass to the procurement group constructor.
139+
"""
140+
141+
self.ensure_one()
142+
143+
return {
144+
"name": (f"Resupply Order {self.location_id.name}"),
145+
"move_type": "one",
146+
}
147+
138148
def _get_procurement_values(self):
139149
"""
140150
Values to pass to the procurement once the order is run.
141151
"""
152+
153+
self.ensure_one()
154+
142155
return {
143156
"group_id": self.procurement_group_id,
144157
}
@@ -149,6 +162,8 @@ def _get_existing_quants(self):
149162
apply specific constraints.
150163
"""
151164

165+
self.ensure_one()
166+
152167
return (
153168
self.env["stock.quant"]
154169
.sudo()
@@ -158,7 +173,7 @@ def _get_existing_quants(self):
158173
(
159174
"product_id",
160175
"in",
161-
self.stock_resupply_order_lines.product_id.ids,
176+
self.stock_resupply_order_line_ids.product_id.ids,
162177
),
163178
],
164179
# Cant aggregate available_quantity here.

stock_resupply_order/tests/test_stock_resupply_order.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
from odoo.tests import tagged
22

3-
from .common import StockResupplyOrderBaseCase
4-
5-
# TODO: add tests with reserved quantities
3+
from odoo.addons.stock_resupply_order.tests.common import StockResupplyOrderBaseCase
64

75

86
@tagged("post_install", "-at_install")

stock_resupply_order/views/stock_resupply_order.xml

Lines changed: 66 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -4,78 +4,75 @@
44
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
55
-->
66
<odoo>
7-
<data>
8-
<record id="stock_resupply_order_tree_view" model="ir.ui.view">
9-
<field name="name">stock.resupply.order.tree</field>
10-
<field name="model">stock.resupply.order</field>
11-
<field name="arch" type="xml">
12-
<tree string="Resupply Order">
13-
<field name="location_id" />
14-
<field name="state" />
15-
</tree>
16-
</field>
17-
</record>
7+
<record id="stock_resupply_order_tree_view" model="ir.ui.view">
8+
<field name="name">stock.resupply.order.tree</field>
9+
<field name="model">stock.resupply.order</field>
10+
<field name="arch" type="xml">
11+
<tree string="Resupply Order">
12+
<field name="location_id" />
13+
<field name="state" />
14+
</tree>
15+
</field>
16+
</record>
1817

19-
<record id="stock_resupply_order_view_form" model="ir.ui.view">
20-
<field name="name">stock.resupply.order.form</field>
21-
<field name="model">stock.resupply.order</field>
22-
<field name="arch" type="xml">
23-
<form>
24-
<header>
25-
<field name="state" widget="statusbar" readonly="1" />
18+
<record id="stock_resupply_order_view_form" model="ir.ui.view">
19+
<field name="name">stock.resupply.order.form</field>
20+
<field name="model">stock.resupply.order</field>
21+
<field name="arch" type="xml">
22+
<form>
23+
<header>
24+
<field name="state" widget="statusbar" readonly="1" />
25+
<button
26+
name="action_run"
27+
string="Run"
28+
type="object"
29+
attrs="{'invisible': [('state', '!=', 'draft')] }"
30+
/>
31+
</header>
32+
<sheet>
33+
<div class="oe_button_box" name="button_box">
2634
<button
27-
name="action_run"
28-
string="Run"
2935
type="object"
30-
attrs="{'invisible': [('state', '!=', 'draft')] }"
31-
/>
32-
</header>
33-
<sheet>
34-
<div class="oe_button_box" name="button_box">
35-
<button
36-
type="object"
37-
name="action_view_transfers"
38-
class="oe_stat_button"
39-
icon="fa-truck"
40-
attrs="{'invisible': [('state', '!=', 'done')] }"
41-
>
42-
<field
43-
name="picking_count"
44-
widget="statinfo"
45-
string="Pickings"
46-
/>
47-
</button>
48-
</div>
49-
<group name="stock_resupply_order_parameters_group">
50-
<field name="location_id" widget="many2one" />
51-
</group>
52-
53-
<field name="stock_resupply_order_lines" widget="one2many">
54-
<tree default_order="product_id asc" editable="bottom">
55-
<field name="product_id" widget="many2one" />
56-
<field name="quantity" />
57-
</tree>
58-
</field>
59-
</sheet>
60-
61-
<!-- Chatter -->
62-
<div class="oe_chatter">
63-
<field
64-
name="message_follower_ids"
65-
widget="mail_followers"
66-
groups="base.group_user"
67-
/>
68-
<field name="message_ids" widget="mail_thread" />
36+
name="action_view_transfers"
37+
class="oe_stat_button"
38+
icon="fa-truck"
39+
attrs="{'invisible': [('state', '!=', 'done')] }"
40+
>
41+
<field
42+
name="picking_count"
43+
widget="statinfo"
44+
string="Pickings"
45+
/>
46+
</button>
6947
</div>
70-
</form>
71-
</field>
72-
</record>
48+
<group name="stock_resupply_order_parameters_group">
49+
<field name="location_id" widget="many2one" />
50+
</group>
51+
<field name="stock_resupply_order_line_ids" widget="one2many">
52+
<tree default_order="product_id asc" editable="bottom">
53+
<field name="product_id" widget="many2one" />
54+
<field name="quantity" />
55+
</tree>
56+
</field>
57+
</sheet>
58+
59+
<!-- Chatter -->
60+
<div class="oe_chatter">
61+
<field
62+
name="message_follower_ids"
63+
widget="mail_followers"
64+
groups="base.group_user"
65+
/>
66+
<field name="message_ids" widget="mail_thread" />
67+
</div>
68+
</form>
69+
</field>
70+
</record>
7371

74-
<record model="ir.actions.act_window" id="stock_resupply_order_action_window">
75-
<field name="name">Resupply Order</field>
76-
<field name="res_model">stock.resupply.order</field>
77-
<field name="view_mode">tree,form</field>
78-
<field name="help">No request found</field>
79-
</record>
80-
</data>
72+
<record model="ir.actions.act_window" id="stock_resupply_order_action_window">
73+
<field name="name">Resupply Order</field>
74+
<field name="res_model">stock.resupply.order</field>
75+
<field name="view_mode">tree,form</field>
76+
<field name="help">No request found</field>
77+
</record>
8178
</odoo>

0 commit comments

Comments
 (0)