mirror of
https://github.com/OCA/stock-logistics-warehouse.git
synced 2025-01-21 14:27:28 +02:00
[MIG] stock_pull_list: Migration to 14.0
This commit is contained in:
@@ -5,14 +5,17 @@
|
|||||||
"name": "Stock Pull List",
|
"name": "Stock Pull List",
|
||||||
"summary": "The pull list checks the stock situation and calculates "
|
"summary": "The pull list checks the stock situation and calculates "
|
||||||
"needed quantities.",
|
"needed quantities.",
|
||||||
"version": "13.0.1.0.0",
|
"version": "14.0.1.0.0",
|
||||||
"license": "LGPL-3",
|
"license": "LGPL-3",
|
||||||
"website": "https://github.com/OCA/stock-logistics-warehouse",
|
"website": "https://github.com/OCA/stock-logistics-warehouse",
|
||||||
"author": "ForgeFlow, " "Odoo Community Association (OCA)",
|
"author": "ForgeFlow, " "Odoo Community Association (OCA)",
|
||||||
"maintainers": ["LoisRForgeFlow"],
|
"maintainers": ["LoisRForgeFlow"],
|
||||||
"development_status": "Alpha",
|
"development_status": "Alpha",
|
||||||
"category": "Warehouse Management",
|
"category": "Warehouse Management",
|
||||||
"depends": ["stock", "stock_available_unreserved"],
|
"depends": ["stock", "stock_free_quantity"],
|
||||||
"data": ["wizards/stock_pull_list_wizard.xml"],
|
"data": [
|
||||||
|
"wizards/stock_pull_list_wizard.xml",
|
||||||
|
"security/ir.model.access.csv",
|
||||||
|
],
|
||||||
"installable": True,
|
"installable": True,
|
||||||
}
|
}
|
||||||
|
|||||||
5
stock_pull_list/security/ir.model.access.csv
Normal file
5
stock_pull_list/security/ir.model.access.csv
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||||
|
access_wiz_stock_pull_list_user,access_wiz_stock_pull_list_user,model_stock_pull_list_wizard,stock.group_stock_user,1,1,1,1
|
||||||
|
access_wiz_stock_pull_list_manager,access_wiz_stock_pull_list_manager,model_stock_pull_list_wizard,stock.group_stock_manager,1,1,1,1
|
||||||
|
access_wiz_stock_pull_list_line_user,access_wiz_stock_pull_list_line_user,model_stock_pull_list_wizard_line,stock.group_stock_user,1,1,1,1
|
||||||
|
access_wiz_stock_pull_list_line_manager,access_wiz_stock_pull_list_line_manager,model_stock_pull_list_wizard_line,stock.group_stock_manager,1,1,1,1
|
||||||
|
@@ -67,7 +67,6 @@ class TestPullListCommon(TransactionCase):
|
|||||||
{
|
{
|
||||||
"name": "Test move",
|
"name": "Test move",
|
||||||
"product_id": self.product_a.id,
|
"product_id": self.product_a.id,
|
||||||
"date_expected": date_move,
|
|
||||||
"date": date_move,
|
"date": date_move,
|
||||||
"product_uom": self.product_a.uom_id.id,
|
"product_uom": self.product_a.uom_id.id,
|
||||||
"product_uom_qty": qty,
|
"product_uom_qty": qty,
|
||||||
|
|||||||
@@ -11,12 +11,12 @@ class TestStockPullList(TestPullListCommon):
|
|||||||
wiz.action_prepare()
|
wiz.action_prepare()
|
||||||
lines = wiz.line_ids.filtered(lambda l: l.product_id == self.product_a)
|
lines = wiz.line_ids.filtered(lambda l: l.product_id == self.product_a)
|
||||||
self.assertEqual(len(lines), 2)
|
self.assertEqual(len(lines), 2)
|
||||||
line_1 = lines.filtered(lambda l: l.date_expected == self.yesterday.date())
|
line_1 = lines.filtered(lambda l: l.date == self.yesterday.date())
|
||||||
self.assertEqual(line_1.raw_demand_qty, 50)
|
self.assertEqual(line_1.raw_demand_qty, 50)
|
||||||
self.assertEqual(line_1.needed_qty, 50)
|
self.assertEqual(line_1.needed_qty, 50)
|
||||||
self.assertEqual(line_1.stock_rule_id, self.transfer_rule)
|
self.assertEqual(line_1.stock_rule_id, self.transfer_rule)
|
||||||
|
|
||||||
line_2 = lines.filtered(lambda l: l.date_expected == self.date_3.date())
|
line_2 = lines.filtered(lambda l: l.date == self.date_3.date())
|
||||||
self.assertEqual(line_2.raw_demand_qty, 70)
|
self.assertEqual(line_2.raw_demand_qty, 70)
|
||||||
self.assertEqual(line_2.needed_qty, 70)
|
self.assertEqual(line_2.needed_qty, 70)
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ class TestStockPullList(TestPullListCommon):
|
|||||||
wiz.action_prepare()
|
wiz.action_prepare()
|
||||||
line = wiz.line_ids.filtered(lambda l: l.product_id == self.product_a)
|
line = wiz.line_ids.filtered(lambda l: l.product_id == self.product_a)
|
||||||
self.assertEqual(len(line), 1)
|
self.assertEqual(len(line), 1)
|
||||||
self.assertEqual(line.date_expected, self.today.date())
|
self.assertEqual(line.date, self.today.date())
|
||||||
expected = 50 + 70
|
expected = 50 + 70
|
||||||
self.assertEqual(line.raw_demand_qty, expected)
|
self.assertEqual(line.raw_demand_qty, expected)
|
||||||
self.assertEqual(line.needed_qty, expected)
|
self.assertEqual(line.needed_qty, expected)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import itertools
|
|||||||
|
|
||||||
from odoo import _, api, fields, models
|
from odoo import _, api, fields, models
|
||||||
from odoo.exceptions import UserError
|
from odoo.exceptions import UserError
|
||||||
|
from odoo.tools import float_compare
|
||||||
|
|
||||||
|
|
||||||
class PullListWizard(models.TransientModel):
|
class PullListWizard(models.TransientModel):
|
||||||
@@ -69,7 +70,7 @@ class PullListWizard(models.TransientModel):
|
|||||||
if self.exclude_reserved:
|
if self.exclude_reserved:
|
||||||
domain.append(("state", "not in", ("assigned",)))
|
domain.append(("state", "not in", ("assigned",)))
|
||||||
if self.date_to:
|
if self.date_to:
|
||||||
domain.append(("date_expected", "<=", self.date_to))
|
domain.append(("date", "<=", self.date_to))
|
||||||
if self.procurement_group_ids:
|
if self.procurement_group_ids:
|
||||||
domain.append(("group_id", "in", self.procurement_group_ids.ids))
|
domain.append(("group_id", "in", self.procurement_group_ids.ids))
|
||||||
return domain
|
return domain
|
||||||
@@ -81,12 +82,12 @@ class PullListWizard(models.TransientModel):
|
|||||||
("state", "not in", ("draft", "done", "cancel")),
|
("state", "not in", ("draft", "done", "cancel")),
|
||||||
]
|
]
|
||||||
if self.date_to:
|
if self.date_to:
|
||||||
domain.append(("date_expected", "<=", self.date_to))
|
domain.append(("date", "<=", self.date_to))
|
||||||
return domain
|
return domain
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def _prepare_line_values(self, key, demand_qty, supply_qty):
|
def _prepare_line_values(self, key, demand_qty, supply_qty):
|
||||||
product, location, date_expected = key
|
product, location, date = key
|
||||||
rule = self._get_stock_rule_id(product, location)
|
rule = self._get_stock_rule_id(product, location)
|
||||||
global qty_assigned
|
global qty_assigned
|
||||||
prev = qty_assigned.setdefault(product, 0.0)
|
prev = qty_assigned.setdefault(product, 0.0)
|
||||||
@@ -98,7 +99,7 @@ class PullListWizard(models.TransientModel):
|
|||||||
return {
|
return {
|
||||||
"product_id": product.id if product else False,
|
"product_id": product.id if product else False,
|
||||||
"location_id": location.id if location else False,
|
"location_id": location.id if location else False,
|
||||||
"date_expected": date_expected,
|
"date": date,
|
||||||
"stock_rule_id": rule.id if rule else False,
|
"stock_rule_id": rule.id if rule else False,
|
||||||
"raw_demand_qty": demand_qty,
|
"raw_demand_qty": demand_qty,
|
||||||
"available_qty": qty_available,
|
"available_qty": qty_available,
|
||||||
@@ -112,7 +113,7 @@ class PullListWizard(models.TransientModel):
|
|||||||
product.id
|
product.id
|
||||||
)
|
)
|
||||||
if self.exclude_reserved:
|
if self.exclude_reserved:
|
||||||
return product_l.qty_available_not_res
|
return product_l.free_qty
|
||||||
return product_l.qty_available
|
return product_l.qty_available
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
@@ -130,35 +131,28 @@ class PullListWizard(models.TransientModel):
|
|||||||
domain = self._get_moves_demand_domain()
|
domain = self._get_moves_demand_domain()
|
||||||
# `read_group` is not possible here because of the date format the
|
# `read_group` is not possible here because of the date format the
|
||||||
# method returns.
|
# method returns.
|
||||||
demand_moves = self.env["stock.move"].search(domain, order="date_expected asc")
|
demand_moves = self.env["stock.move"].search(domain, order="date asc")
|
||||||
demand_dict = {}
|
demand_dict = {}
|
||||||
force_date = fields.Date.today() if self.consolidate_by_product else False
|
force_date = fields.Date.today() if self.consolidate_by_product else False
|
||||||
for demand in demand_moves:
|
for demand in demand_moves:
|
||||||
key = (
|
key = (
|
||||||
demand.product_id,
|
demand.product_id,
|
||||||
demand.location_id,
|
demand.location_id,
|
||||||
fields.Date.to_date(demand.date_expected)
|
fields.Date.to_date(demand.date) if not force_date else force_date,
|
||||||
if not force_date
|
|
||||||
else force_date,
|
|
||||||
)
|
)
|
||||||
prev = demand_dict.setdefault(key, 0.0)
|
prev = demand_dict.setdefault(key, 0.0)
|
||||||
# TODO: when exclude_reserved is selected, handle partially avail.
|
# TODO: when exclude_reserved is selected, handle partially avail.
|
||||||
demand_dict[key] = prev + demand.product_uom_qty
|
demand_dict[key] = prev + demand.product_uom_qty
|
||||||
|
|
||||||
domain = self._get_moves_incoming_domain()
|
domain = self._get_moves_incoming_domain()
|
||||||
incoming_moves = self.env["stock.move"].search(
|
incoming_moves = self.env["stock.move"].search(domain, order="date asc")
|
||||||
domain, order="date_expected asc"
|
|
||||||
)
|
|
||||||
incoming_dict = {}
|
incoming_dict = {}
|
||||||
for supply in incoming_moves:
|
for supply in incoming_moves:
|
||||||
move_for_date = demand_moves.filtered(
|
move_for_date = demand_moves.filtered(
|
||||||
lambda m: m.product_id == supply.product_id
|
lambda m: m.product_id == supply.product_id and m.date >= supply.date
|
||||||
and m.date_expected >= supply.date_expected
|
|
||||||
)
|
)
|
||||||
if move_for_date:
|
if move_for_date:
|
||||||
date_selected = (
|
date_selected = move_for_date[0].date if not force_date else force_date
|
||||||
move_for_date[0].date_expected if not force_date else force_date
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
# Supply is later than last demand -> ignore it.
|
# Supply is later than last demand -> ignore it.
|
||||||
continue
|
continue
|
||||||
@@ -273,7 +267,7 @@ class PullListWizard(models.TransientModel):
|
|||||||
group = pg_obj.create(self._prepare_proc_group_values())
|
group = pg_obj.create(self._prepare_proc_group_values())
|
||||||
proc_groups.append(group.id)
|
proc_groups.append(group.id)
|
||||||
|
|
||||||
values = self._prepare_procurement_values(line.date_expected, group)
|
values = self._prepare_procurement_values(line.date, group)
|
||||||
procurements.append(
|
procurements.append(
|
||||||
pg_obj.Procurement(
|
pg_obj.Procurement(
|
||||||
line.product_id,
|
line.product_id,
|
||||||
@@ -318,11 +312,11 @@ class PullListWizardLine(models.TransientModel):
|
|||||||
location_id = fields.Many2one(
|
location_id = fields.Many2one(
|
||||||
comodel_name="stock.location",
|
comodel_name="stock.location",
|
||||||
)
|
)
|
||||||
date_expected = fields.Date()
|
date = fields.Date()
|
||||||
available_qty = fields.Float()
|
available_qty = fields.Float(digits="Product Unit of Measure")
|
||||||
incoming_qty = fields.Float()
|
incoming_qty = fields.Float(digits="Product Unit of Measure")
|
||||||
raw_demand_qty = fields.Float()
|
raw_demand_qty = fields.Float(digits="Product Unit of Measure")
|
||||||
needed_qty = fields.Float()
|
needed_qty = fields.Float(digits="Product Unit of Measure")
|
||||||
stock_rule_id = fields.Many2one(
|
stock_rule_id = fields.Many2one(
|
||||||
comodel_name="stock.rule",
|
comodel_name="stock.rule",
|
||||||
)
|
)
|
||||||
@@ -334,4 +328,4 @@ class PullListWizardLine(models.TransientModel):
|
|||||||
qty_avail = self.wizard_id._get_available_qty(
|
qty_avail = self.wizard_id._get_available_qty(
|
||||||
self.product_id, self.stock_rule_id.location_src_id
|
self.product_id, self.stock_rule_id.location_src_id
|
||||||
)
|
)
|
||||||
return qty_avail > self.needed_qty
|
return float_compare(qty_avail, self.needed_qty, precision_digits=2) > 0
|
||||||
|
|||||||
@@ -55,7 +55,7 @@
|
|||||||
<field name="wizard_id" invisible="1" />
|
<field name="wizard_id" invisible="1" />
|
||||||
<field name="product_id" />
|
<field name="product_id" />
|
||||||
<field name="location_id" />
|
<field name="location_id" />
|
||||||
<field name="date_expected" />
|
<field name="date" />
|
||||||
<field name="available_qty" />
|
<field name="available_qty" />
|
||||||
<field name="incoming_qty" />
|
<field name="incoming_qty" />
|
||||||
<field name="raw_demand_qty" />
|
<field name="raw_demand_qty" />
|
||||||
@@ -112,14 +112,14 @@
|
|||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
<act_window
|
<record id="action_stock_pull_list_wizard" model="ir.actions.act_window">
|
||||||
name="Generate Pull List"
|
<field name="name">Generate Pull List</field>
|
||||||
res_model="stock.pull.list.wizard"
|
<field name="res_model">stock.pull.list.wizard</field>
|
||||||
binding_model="stock.pull.list.wizard"
|
<field name="binding_model_id" ref="model_stock_pull_list_wizard" />
|
||||||
view_mode="form"
|
<field name="view_mode">form</field>
|
||||||
target="new"
|
<field name="target">new</field>
|
||||||
id="action_stock_pull_list_wizard"
|
</record>
|
||||||
/>
|
|
||||||
<menuitem
|
<menuitem
|
||||||
name="Generate Pull List"
|
name="Generate Pull List"
|
||||||
id="menu_stock_pull_list_wizard"
|
id="menu_stock_pull_list_wizard"
|
||||||
|
|||||||
Reference in New Issue
Block a user