Skip to content

Commit f703e5c

Browse files
committed
wip
1 parent fe585c6 commit f703e5c

File tree

11 files changed

+128
-261
lines changed

11 files changed

+128
-261
lines changed

stock_resupply_order/README.rst

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ Stock resupply order
2929
|badge1| |badge2| |badge3| |badge4| |badge5|
3030

3131

32-
This module enhances the views associated to account moves and account move
33-
lines to display the product that is associated to the move line.
32+
This module adds a model used to create procurements that take into account
33+
stock available in a targeted location.
3434

35-
This will be relevant in perpetual inventory, for inventory-related account
36-
moves.
35+
The user create "resupply orders" with lines of products and their final desired quantity
36+
for a desired location. Those orders can be then executed to create procurements.
3737

3838
**Table of contents**
3939

@@ -62,9 +62,7 @@ Contributors
6262
~~~~~~~~~~~~
6363

6464

65-
* Jordi Ballester Alomar <[email protected]>
66-
* Pimolnat Suntian <[email protected]>
67-
* Mantas Šniukas <[email protected]>
65+
* Tabis Lucas <[email protected]>
6866

6967
Maintainers
7068
~~~~~~~~~~~

stock_resupply_order/__manifest__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
# Odoo
1616
"base",
1717
"product",
18+
"stock",
1819
],
1920
"data": [
2021
"security/ir.model.access.csv",

stock_resupply_order/demo/stock_route_stock_resupply_order.xml

Lines changed: 17 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,58 +6,50 @@
66
<odoo>
77
<data>
88
<record model="stock.location" id="location_stock_demo">
9-
<field name="name">Stock Saint-Ouen</field>
9+
<field name="name">Stock</field>
1010
<field name="usage">internal</field>
11-
<field name="warehouse_id" ref="stock.warehouse0" />
1211
</record>
13-
<record model="stock.location" id="location_ondemand_demo">
14-
<field name="name">Preparation Ondemand</field>
12+
13+
<record model="stock.location" id="location_dest_demo">
14+
<field name="name">Destination location</field>
1515
<field name="usage">internal</field>
16-
<field name="warehouse_id" ref="stock.warehouse0" />
1716
</record>
1817

19-
<record model="stock.picking.type" id="picking_type_od_so_demo">
20-
<field name="name">Stock to OnDemand SO</field>
21-
<field name="sequence_code">ONDEMAND-STOCK-SO</field>
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>
2221
<field name="code">outgoing</field>
2322
<field name="show_operations">True</field>
2423
<field name="use_create_lots">False</field>
2524
<field name="use_existing_lots">True</field>
2625
<field name="warehouse_id" ref="stock.warehouse0" />
2726
<field
2827
name="default_location_src_id"
29-
ref="foodles_stock_resupply_order.location_stock_demo"
28+
ref="stock_resupply_order.location_stock_demo"
3029
/>
3130
<field
3231
name="default_location_dest_id"
33-
ref="foodles_stock_resupply_order.location_ondemand_demo"
32+
ref="stock_resupply_order.location_dest_demo"
3433
/>
3534
</record>
3635

37-
<record model="stock.location.route" id="route_ondemand_so_ajd_request_demo">
38-
<field name="name">OnDemand SO stock resupply order</field>
36+
<record model="stock.location.route" id="route_demo">
37+
<field name="name">stock resupply order</field>
3938
<field name="product_categ_selectable">True</field>
40-
<field name="service_level_selectable">True</field>
41-
<field
42-
name="service_level_ids"
43-
eval="[(4, ref('foodles_stock_service_level.ondemand'))]"
44-
/>
4539
</record>
46-
<record model="stock.rule" id="rule_ondemand_so_demo">
40+
41+
<record model="stock.rule" id="rule_demo">
4742
<field name="name">Pull</field>
4843
<field name="action">pull</field>
49-
<field name="picking_type_id" ref="picking_type_od_so_demo" />
44+
<field name="picking_type_id" ref="picking_type_demo" />
5045
<field
5146
name="location_src_id"
52-
ref="foodles_stock_resupply_order.location_stock_demo"
53-
/>
54-
<field
55-
name="location_id"
56-
ref="foodles_stock_resupply_order.location_ondemand_demo"
47+
ref="stock_resupply_order.location_stock_demo"
5748
/>
49+
<field name="location_id" ref="stock_resupply_order.location_dest_demo" />
5850
<field name="procure_method">make_to_stock</field>
5951
<field name="warehouse_id" ref="stock.warehouse0" />
60-
<field name="route_id" ref="route_ondemand_so_ajd_request_demo" />
52+
<field name="route_id" ref="route_demo" />
6153
</record>
6254
</data>
6355
</odoo>

stock_resupply_order/models/stock_resupply_order.py

Lines changed: 36 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import logging
2-
from datetime import datetime
32

43
from odoo import api, fields, models
54

@@ -80,34 +79,33 @@ def action_run(self):
8079

8180
self.procurement_group_id = self.env["procurement.group"].create(
8281
{
83-
"name": (
84-
f"Adjustment Request {self.location_id.name} / {self.planned_consumed_date}"
85-
),
82+
"name": (f"Resupply Order {self.location_id.name}"),
8683
"move_type": "one",
8784
}
8885
)
8986

90-
lines_with_stock_quants = self._get_existing_quants()
87+
quant_groups = self._get_existing_quants()
9188

9289
procurements = []
9390

94-
for (
95-
line,
96-
stock_quant,
97-
) in lines_with_stock_quants: # self.stock_picking_adjustment_request_lines:
91+
for line in self.stock_resupply_order_lines:
9892
# service products have no tracking/lot and cannot be run in procurement
9993
if line.product_id.product_tmpl_id.type == "service":
10094
continue
10195

102-
if stock_quant.quantity < line.quantity:
96+
available_quantity = self._get_available_quantity_for_product(
97+
quant_groups, line
98+
)
99+
100+
if available_quantity < line.quantity:
103101
procurements.append(
104102
self.env["procurement.group"].Procurement(
105103
product_id=line.product_id,
106-
product_qty=line.quantity - stock_quant.quantity,
104+
product_qty=line.quantity - available_quantity,
107105
product_uom=line.product_id.product_tmpl_id.uom_id,
108106
location_id=self.location_id,
109-
name=f"Adjustment request {self.planned_consumed_date}",
110-
origin=f"Adjustment request {self.planned_consumed_date}",
107+
name=f"Resupply Order to {self.location_id.name}",
108+
origin=f"Resupply Order to {self.location_id.name}",
111109
company_id=self.company_id,
112110
values=self._get_procurement_values(),
113111
)
@@ -120,23 +118,37 @@ def action_run(self):
120118

121119
return self.procurement_group_id
122120

121+
def _get_available_quantity_for_product(
122+
self, quant_groups, stock_resupply_order_line
123+
):
124+
try:
125+
# I could not find a way to merge stock_resupply_order_lines
126+
# with the quant_groups query, so it is retrieved with a product
127+
# id search here. Not ideal, but it works.
128+
group = next(
129+
group
130+
for group in quant_groups
131+
if group["product_id"][0] == stock_resupply_order_line.product_id.id
132+
)
133+
134+
return group["quantity"] - group["reserved_quantity"]
135+
except StopIteration:
136+
return 0
137+
123138
def _get_procurement_values(self):
124139
"""
125140
Values to pass to the procurement once the order is run.
126141
"""
127-
return (
128-
{
129-
"group_id": self.procurement_group_id,
130-
"service_level_id": self.service_level.id,
131-
"planned_consumed_date": self.planned_consumed_date,
132-
},
133-
)
142+
return {
143+
"group_id": self.procurement_group_id,
144+
}
134145

135146
def _get_existing_quants(self):
136147
"""
137148
Get stock quants at the targeted location. Override if you need to
138149
apply specific constraints.
139150
"""
151+
140152
return (
141153
self.env["stock.quant"]
142154
.sudo()
@@ -146,37 +158,17 @@ def _get_existing_quants(self):
146158
(
147159
"product_id",
148160
"in",
149-
list(self.stock_picking_adjustment_request_lines.product_id.id),
161+
self.stock_resupply_order_lines.product_id.ids,
150162
),
151-
# ("expiration_date", ">", self.planned_consumed_date),
152-
],
153-
fields=[
154-
"product_id",
155-
"quantity:sum(quantity)",
156-
"reserved_quantity:sum(reserved_quantity)",
157163
],
164+
# Cant aggregate available_quantity here.
165+
fields=["product_id", "quantity:sum", "reserved_quantity:sum"],
158166
groupby=["product_id"],
159-
orderby="location_id, product_id, lot_id",
167+
orderby="product_id",
160168
lazy=False,
161169
)
162170
)
163171

164-
# stock_quant = self.env["stock.quant"].search(
165-
# [
166-
# ("location_id", "=", self.location_id.id),
167-
# ("product_id", "=", line.product_id.id),
168-
# ("expiration_date", ">", line.planned_consumed_date),
169-
# ]
170-
# )
171-
172-
@api.model
173-
def action_run_at(self, date):
174-
return self.search([("date", "=", date)]).action_run()
175-
176-
@api.model
177-
def action_run_today(self):
178-
return self.action_run_at(datetime.now())
179-
180172
def action_view_transfers(self):
181173
pickings = self.procurement_group_id.stock_move_ids.picking_id
182174

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,2 @@
11

2-
* Jordi Ballester Alomar <[email protected]>
3-
* Pimolnat Suntian <[email protected]>
4-
* Mantas Šniukas <[email protected]>
2+
* Tabis Lucas <[email protected]>
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

2-
This module enhances the views associated to account moves and account move
3-
lines to display the product that is associated to the move line.
2+
This module adds a model used to create procurements that take into account
3+
stock available in a targeted location.
44

5-
This will be relevant in perpetual inventory, for inventory-related account
6-
moves.
5+
The user create "resupply orders" with lines of products and their final desired quantity
6+
for a desired location. Those orders can be then executed to create procurements.

stock_resupply_order/static/description/index.html

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -370,10 +370,10 @@ <h1 class="title">Stock resupply order</h1>
370370
!! source digest: sha256:54063437212cf93a49834105eb403d625eb1a3e3cb8acd475f4337d53dd8d232
371371
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
372372
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/stock-logistics-warehouse/tree/14.0/stock_resupply_order"><img alt="OCA/stock-logistics-warehouse" src="https://img.shields.io/badge/github-OCA%2Fstock--logistics--warehouse-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/stock-logistics-warehouse-14-0/stock-logistics-warehouse-14-0-stock_resupply_order"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/stock-logistics-warehouse&amp;target_branch=14.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
373-
<p>This module enhances the views associated to account moves and account move
374-
lines to display the product that is associated to the move line.</p>
375-
<p>This will be relevant in perpetual inventory, for inventory-related account
376-
moves.</p>
373+
<p>This module adds a model used to create procurements that take into account
374+
stock available in a targeted location.</p>
375+
<p>The user create “resupply orders” with lines of products and their final desired quantity
376+
for a desired location. Those orders can be then executed to create procurements.</p>
377377
<p><strong>Table of contents</strong></p>
378378
<div class="contents local topic" id="contents">
379379
<ul class="simple">
@@ -405,9 +405,7 @@ <h2><a class="toc-backref" href="#toc-entry-3">Authors</a></h2>
405405
<div class="section" id="contributors">
406406
<h2><a class="toc-backref" href="#toc-entry-4">Contributors</a></h2>
407407
<ul class="simple">
408-
<li>Jordi Ballester Alomar &lt;<a class="reference external" href="mailto:jordi.ballester&#64;forgeflow.com">jordi.ballester&#64;forgeflow.com</a>&gt;</li>
409-
<li>Pimolnat Suntian &lt;<a class="reference external" href="mailto:pimolnat&#64;ecosoft.co.th">pimolnat&#64;ecosoft.co.th</a>&gt;</li>
410-
<li>Mantas Šniukas &lt;<a class="reference external" href="mailto:mantas&#64;vialaurea.lt">mantas&#64;vialaurea.lt</a>&gt;</li>
408+
<li>Tabis Lucas &lt;<a class="reference external" href="mailto:ltabis.pro&#64;gmail.com">ltabis.pro&#64;gmail.com</a>&gt;</li>
411409
</ul>
412410
</div>
413411
<div class="section" id="maintainers">
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
from . import common, test_stock_resupply_order
1+
from . import test_stock_resupply_order

stock_resupply_order/tests/common.py

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,17 @@ def setUpClass(cls):
1111
super().setUpClass()
1212

1313
cls.warehouse = cls.env.ref("stock.warehouse0")
14-
cls.location = cls.env.ref("stock_resupply_order.location_ondemand_demo")
15-
cls.service_level = cls.env.ref("foodles_stock_service_level.ondemand")
14+
cls.location = cls.env.ref("stock_resupply_order.location_dest_demo")
1615
cls.product_attribute = (
17-
cls.env["product.attribute"]
18-
.sudo()
19-
.create({"name": "Packaging", "code": "packaging"})
16+
cls.env["product.attribute"].sudo().create({"name": "Packaging"})
2017
)
2118
cls.product_attribute_value = (
2219
cls.env["product.attribute.value"]
2320
.sudo()
2421
.create({"attribute_id": cls.product_attribute.id, "name": "Disposable"})
2522
)
2623
product_attribute_packaging = (
27-
cls.env["product.attribute"]
28-
.sudo()
29-
.create({"name": "Packaging", "code": "packaging"})
24+
cls.env["product.attribute"].sudo().create({"name": "Packaging"})
3025
)
3126
product_attribute_value_disposable = (
3227
cls.env["product.attribute.value"]
@@ -35,7 +30,6 @@ def setUpClass(cls):
3530
{
3631
"attribute_id": product_attribute_packaging.id,
3732
"name": "Disposable",
38-
"default_code_suffix": "D",
3933
},
4034
)
4135
)
@@ -45,9 +39,8 @@ def setUpClass(cls):
4539
.sudo()
4640
.create(
4741
{
48-
"name": "A OD Dish",
42+
"name": "A product",
4943
"tracking": "lot",
50-
"use_expiration_date": True,
5144
"type": "product",
5245
"default_code": "CODE123",
5346
"attribute_line_ids": [
@@ -72,9 +65,7 @@ def setUpClass(cls):
7265
cls.product_template.categ_id.route_ids = [
7366
(
7467
4,
75-
cls.env.ref(
76-
"stock_resupply_order.route_ondemand_so_ajd_request_demo"
77-
).id,
68+
cls.env.ref("stock_resupply_order.route_demo").id,
7869
),
7970
]
8071
cls.product_disposable = cls.product_template.product_variant_ids[0]

0 commit comments

Comments
 (0)