[9.0][IMP] stock_cycle_count: add the possibility to define rules for specific zones.

This commit is contained in:
lreficent
2017-05-04 19:21:17 +02:00
committed by Mateu Griful
parent d0295f1266
commit 0ca46546d7
8 changed files with 98 additions and 56 deletions

View File

@@ -18,6 +18,7 @@ can propose Zero-Confirmations which are simple and opportunistic counts to
check whether a locations has actually became empty or not.
With this strategy it is possible to:
* Remove the need to perform full physical inventories and to stop the
production in the warehouse.
* Measure the accuracy of the inventory records and improve it.
@@ -36,14 +37,12 @@ Configuration
You can configure the rules to compute the cycle count, acting as follow:
#. Go to "Inventory > Configuration > Cycle Count Rules"
#. Go to *Inventory > Configuration > Cycle Count Rules*.
#. Create as much cycle count rules as you want.
#. Assign the rules to the Warehouse where you want to apply the rules in.
#. Set a "Cycle Count Planning Horizon" for each warehouse.
.. figure:: path/to/local/image.png
:alt: alternative description
:width: 600 px
#. Assign the rules to the Warehouse or zones where you want to apply the rules
in.
#. Go to *Inventory > Configuration > Warehouse Management > Warehouses* and
set a *Cycle Count Planning Horizon* for each warehouse.
Usage
=====
@@ -53,11 +52,12 @@ is described below.
#. Go to "Inventory > Configuration > Warehouse Management > Warehouses".
#. Select all the warehouses you want to compute the rules in.
#. Click on "Action" and then in "Compute Cycle Count Rules".
#. Click on "Action" and then in "Compute Cycle Count Rules". (**note**: A
cron job will do this for every warehouse daily.)
#. Go to "Inventory Control > Cycle Counts".
#. Select a Cycle Count planned an confirm it, this will create a draft
#. Select a planned Cycle Count and confirm it, this will create a draft
Inventory Adjustment.
#. In the right top corner of the form view you can access the generated
#. In the right top corner of the form view you can access to the generated
Inventory Adjustment.
#. Proceed with the Inventory Adjustment as usual.
@@ -65,9 +65,6 @@ is described below.
:alt: Try me on Runbot
:target: https://runbot.odoo-community.org/runbot/153/9.0
.. repo_id is available in https://github.com/OCA/stock-logistics-warehouse
.. branch is "9.0" for example
Bug Tracker
===========

View File

@@ -6,7 +6,7 @@
"name": "Stock Cycle Count",
"summary": "Adds the capability to schedule cycle counts in a "
"warehouse through different rules defined by the user",
"version": "9.0.1.0.0",
"version": "9.0.1.1.0",
"author": "Eficent, "
"Odoo Community Association (OCA)",
"website": "https://github.com/OCA/stock-logistics-warehouse",

View File

@@ -8,6 +8,7 @@ from openerp import api, fields, models
class StockCycleCount(models.Model):
_name = 'stock.cycle.count'
_description = "Stock Cycle Counts"
_inherit = 'mail.thread'
@api.one

View File

@@ -11,6 +11,7 @@ from datetime import timedelta, datetime
class StockCycleCountRule(models.Model):
_name = 'stock.cycle.count.rule'
_description = "Stock Cycle Counts Rules"
@api.one
def _compute_currency(self):
@@ -77,6 +78,15 @@ class StockCycleCountRule(models.Model):
_('You cannot define a negative period.')
)
@api.onchange('location_ids')
def _get_warehouses(self):
"""Get the warehouses for the selected locations."""
wh_ids = []
for loc in self.location_ids:
wh_ids.append(loc.get_warehouse(loc))
wh_ids = list(set(wh_ids))
self.warehouse_ids = self.env['stock.warehouse'].browse(wh_ids)
name = fields.Char('Name', required=True)
rule_type = fields.Selection(selection="_selection_rule_types",
string='Type of rule',
@@ -94,11 +104,19 @@ class StockCycleCountRule(models.Model):
compute=_compute_currency)
accuracy_threshold = fields.Float(string='Minimum Accuracy Threshold',
digits=(3, 2))
warehouse_ids = fields.Many2many(comodel_name='stock.warehouse',
relation='warehouse_cycle_count_rule_rel',
column1='rule_id',
column2='warehouse_id',
string='Applied in')
apply_in = fields.Selection(
string='Apply this rule in:',
selection=[('warehouse', 'Selected warehouses'),
('location', 'Selected Location Zones.')],
default='warehouse')
warehouse_ids = fields.Many2many(
comodel_name='stock.warehouse',
relation='warehouse_cycle_count_rule_rel', column1='rule_id',
column2='warehouse_id', string='Warehouses where applied')
location_ids = fields.Many2many(
comodel_name='stock.location',
relation='location_cycle_count_rule_rel', column1='rule_id',
column2='location_id', string='Zones where applied')
def compute_rule(self, locs):
if self.rule_type == 'periodic':

View File

@@ -36,24 +36,30 @@ class StockWarehouse(models.Model):
return date_horizon
@api.model
def _get_cycle_count_locations_search_domain(self):
wh_parent_left = self.view_location_id.parent_left
wh_parent_right = self.view_location_id.parent_right
domain = [('parent_left', '>', wh_parent_left),
('parent_right', '<', wh_parent_right),
def _get_cycle_count_locations_search_domain(
self, parent):
domain = [('parent_left', '>=', parent.parent_left),
('parent_right', '<=', parent.parent_right),
('cycle_count_disabled', '=', False)]
return domain
@api.model
def _search_cycle_count_locations(self):
locations = self.env['stock.location'].search(
self._get_cycle_count_locations_search_domain())
def _search_cycle_count_locations(self, rule):
locations = self.env['stock.location']
if rule.apply_in == 'warehouse':
locations = self.env['stock.location'].search(
self._get_cycle_count_locations_search_domain(
self.view_location_id))
elif rule.apply_in == 'location':
for loc in rule.location_ids:
locations += self.env['stock.location'].search(
self._get_cycle_count_locations_search_domain(loc))
return locations
@api.model
def _cycle_count_rules_to_compute(self):
rules = self.cycle_count_rule_ids.search([
('rule_type', '!=', 'zero')])
('rule_type', '!=', 'zero'), ('warehouse_ids', '=', self.id)])
return rules
@api.one
@@ -62,10 +68,10 @@ class StockWarehouse(models.Model):
returns a list with required dates for the cycle count of each
location '''
proposed_cycle_counts = []
locations = self._search_cycle_count_locations()
rules = self._cycle_count_rules_to_compute()
if locations:
for rule in rules:
for rule in rules:
locations = self._search_cycle_count_locations(rule)
if locations:
proposed_cycle_counts.extend(rule.compute_rule(locations))
if proposed_cycle_counts:
locations = list(set([d['location'] for d in

View File

@@ -35,6 +35,14 @@ class TestStockCycleCount(common.TransactionCase):
self.user = self._create_user(
'user_2', [self.g_stock_user], self.company).id
# Create warehouses:
self.big_wh = self.stock_warehouse_model.create({
'name': 'BIG',
'code': 'B',
'cycle_count_planning_horizon': 30})
self.small_wh = self.stock_warehouse_model.create({
'name': 'SMALL', 'code': 'S'})
# Create rules:
self.rule_periodic = \
self._create_stock_cycle_count_rule_periodic(
@@ -44,30 +52,26 @@ class TestStockCycleCount(common.TransactionCase):
self.manager, 'rule_2', [100])
self.rule_accuracy = \
self._create_stock_cycle_count_rule_accuracy(
self.manager, 'rule_3', [5])
self.manager, 'rule_3', [5], self.big_wh.view_location_id.ids)
self.zero_rule = self._create_stock_cycle_count_rule_zero(
self.manager, 'rule_4')
# Create and configure warehouses:
# Configure warehouses:
self.rule_ids = [
self.rule_periodic.id,
self.rule_turnover.id,
self.rule_accuracy.id,
self.zero_rule.id]
self.big_wh = self.stock_warehouse_model.create({
'name': 'BIG',
'code': 'B',
'cycle_count_planning_horizon': 30,
self.big_wh.write({
'cycle_count_rule_ids': [(6, 0, self.rule_ids)]
})
self.small_wh = self.stock_warehouse_model.create({
'name': 'SMALL', 'code': 'S'})
# Create a location:
self.count_loc = self.stock_location_model.create({
'name': 'Place',
'usage': 'production'
})
self.stock_location_model._parent_store_compute()
# Create a cycle count:
self.cycle_count_1 = self.cycle_count_model.sudo(self.manager).create({
@@ -113,11 +117,14 @@ class TestStockCycleCount(common.TransactionCase):
})
return rule
def _create_stock_cycle_count_rule_accuracy(self, uid, name, values):
def _create_stock_cycle_count_rule_accuracy(
self, uid, name, values, zone_ids):
rule = self.stock_cycle_count_rule_model.sudo(uid).create({
'name': name,
'rule_type': 'accuracy',
'accuracy_threshold': values[0],
'apply_in': 'location',
'location_ids': [(6, 0, zone_ids)],
})
return rule
@@ -132,8 +139,10 @@ class TestStockCycleCount(common.TransactionCase):
"""Tests creation of cycle counts."""
# Common rules:
wh = self.big_wh
self.stock_location_model._parent_store_compute()
locs = wh._search_cycle_count_locations()
locs = self.stock_location_model
for rule in self.big_wh.cycle_count_rule_ids:
locs += wh._search_cycle_count_locations(rule)
locs = locs.exists() # remove duplicated locations.
counts = self.cycle_count_model.search([
('location_id', 'in', locs.ids)])
self.assertFalse(
@@ -225,6 +234,10 @@ class TestStockCycleCount(common.TransactionCase):
for r in rules:
r._get_rule_description()
self.assertTrue(r.rule_description, 'No description provided')
self.rule_accuracy._get_warehouses()
self.assertEqual(self.rule_accuracy.warehouse_ids.ids, self.big_wh.ids,
'Rules defined for zones are not getting the right '
'warehouse.')
def test_user_security(self):
"""Tests user rights."""

View File

@@ -11,6 +11,7 @@
<tree string="Stock Cycle Count">
<field name="name"/>
<field name="warehouse_ids"/>
<field name="location_ids"/>
<field name="rule_type"/>
</tree>
</field>
@@ -47,12 +48,19 @@
</div>
</group>
</group>
<group name="applied_in" string="Applied in:">
<p colspan="4">You can apply the cycle count rules in complete
warehouses or specific zones. A zone it is
understood as a location and all its children.</p>
<p colspan="4">In either case you can exclude specific locations
going to the locations form and checking the box
"Exclude from Cycle Count".</p>
<field name="apply_in"/>
<field name="warehouse_ids" widget="many2many_tags"/>
<field name="location_ids"
attrs="{'invisible': [('apply_in', '!=', 'location')]}"/>
</group>
<notebook>
<page string="Applied in">
<field name="warehouse_ids"/>
</page>
</notebook>
</sheet>
</form>

View File

@@ -10,15 +10,14 @@
<field name="inherit_id" ref="stock.view_warehouse"/>
<field name="arch" type="xml">
<notebook position="before">
<group string="Cycle Counting">
<group >
<field name="cycle_count_planning_horizon"/>
<field name="counts_for_accuracy_qty"/>
</group>
<group>
<field name="cycle_count_rule_ids" nolabel="1">Cycle
count rules</field>
</group>
<group string="Cycle Counting" colspan="4">
<field name="cycle_count_planning_horizon"/>
<field name="counts_for_accuracy_qty"/>
<br></br>
<center colspan="4"><h3 colspan="4">Cycle Count Rules
applied in this Warehouse:</h3></center>
<field name="cycle_count_rule_ids" nolabel="1" colspan="4">
Cycle count rules</field>
</group>
</notebook>
</field>