changeset 7c417dc2d884 in modules/stock:default
details: https://hg.tryton.org/modules/stock?cmd=changeset;node=7c417dc2d884
description:
Define lost and found location for inventory on parent location
We remove the lost and found location on the inventory to only used one
define
on the warehouse or parent of the inventoried location.
issue9071
review276901002
diffstat:
CHANGELOG | 1 +
doc/index.rst | 20 ++++++++++----------
inventory.py | 22 +++++++++-------------
location.py | 17 +++++++++++++++++
location.xml | 9 +++++----
message.xml | 3 +++
tests/scenario_stock_inventory.rst | 5 +++--
tests/scenario_stock_inventory_empty_quantity.rst | 3 ++-
view/inventory_form.xml | 6 ++++--
view/location_form.xml | 5 +++++
10 files changed, 59 insertions(+), 32 deletions(-)
diffs (262 lines):
diff -r da645fd3072b -r 7c417dc2d884 CHANGELOG
--- a/CHANGELOG Tue Mar 17 20:08:12 2020 +0100
+++ b/CHANGELOG Tue Mar 17 23:35:47 2020 +0100
@@ -1,3 +1,4 @@
+* Define one lost and found location per warehouse
* Show warehouse in user status if not unique
* Add cost price revision
* Add wizard to modify product cost price
diff -r da645fd3072b -r 7c417dc2d884 doc/index.rst
--- a/doc/index.rst Tue Mar 17 20:08:12 2020 +0100
+++ b/doc/index.rst Tue Mar 17 23:35:47 2020 +0100
@@ -18,13 +18,14 @@
* Warehouse
- Warehouses are meta-locations which define input, storage, picking and output
- locations. These locations are all of type Storage. Input and Output are
- locations where incoming an outgoing product are temporally stored awaiting
- transportation. The storage location is often the biggest location where
- products are stored for middle or long periods of time. The picking location
- is optionally where the products are picked by the customer shipment
- otherwise the storage location is used.
+ Warehouses are meta-locations which define input, storage, picking, output
+ and lost and found locations. These locations are all of type Storage. Input
+ and Output are locations where incoming an outgoing product are temporally
+ stored awaiting transportation. The storage location is often the biggest
+ location where products are stored for middle or long periods of time. The
+ picking location is optionally where the products are picked by the customer
+ shipment otherwise the storage location is used. The lost and found location
+ is the location used by inventories when correcting stock levels.
* Customer
@@ -261,9 +262,8 @@
Inventory
*********
-Inventories allow to control and update stock levels. They are mainly
-composed of two locations (a Storage location and a Lost And Found
-location), and a list of inventory lines.
+Inventories allow to control and update stock levels. They are mainly composed
+of the inventoried storage location and a list of inventory lines.
Inventory lines consist of a product and it's default unit of measure, an
expected quantity and the real quantity (the real products on the shelves).
diff -r da645fd3072b -r 7c417dc2d884 inventory.py
--- a/inventory.py Tue Mar 17 20:08:12 2020 +0100
+++ b/inventory.py Tue Mar 17 23:35:47 2020 +0100
@@ -37,11 +37,6 @@
},
depends=['state'],
help="The date of the stock count.")
- lost_found = fields.Many2One(
- 'stock.location', 'Lost and Found', required=True,
- domain=[('type', '=', 'lost_found')], states=_states, depends=_depends,
- help="Used for the balancing entries needed when the stock is "
- "corrected.")
lines = fields.One2Many(
'stock.inventory.line', 'inventory', 'Lines',
states={
@@ -106,6 +101,9 @@
# Add index on create_date
table.index_action('create_date', action='add')
+ # Migration from 5.4: remove lost_found
+ table.not_null_action('lost_found', 'remove')
+
@staticmethod
def default_state():
return 'draft'
@@ -120,13 +118,6 @@
return Transaction().context.get('company')
@classmethod
- def default_lost_found(cls):
- Location = Pool().get('stock.location')
- locations = Location.search(cls.lost_found.domain)
- if len(locations) == 1:
- return locations[0].id
-
- @classmethod
def view_attributes(cls):
return [
('/tree', 'visual', If(Eval('state') == 'cancel', 'muted', '')),
@@ -446,7 +437,12 @@
if delta_qty == 0.0:
return
from_location = self.inventory.location
- to_location = self.inventory.lost_found
+ to_location = self.inventory.location.lost_found_used
+ if not to_location:
+ raise InventoryValidationError(
+ gettext('stock.msg_inventory_location_missing_lost_found',
+ inventory=self.inventory.rec_name,
+ location=self.inventory.location.rec_name))
if delta_qty < 0:
(from_location, to_location, delta_qty) = \
(to_location, from_location, -delta_qty)
diff -r da645fd3072b -r 7c417dc2d884 location.py
--- a/location.py Tue Mar 17 20:08:12 2020 +0100
+++ b/location.py Tue Mar 17 23:35:47 2020 +0100
@@ -112,6 +112,18 @@
depends=['type', 'storage_location'],
help="Where stock is picked from.\n"
"Leave empty to use the storage location.")
+ lost_found_location = fields.Many2One(
+ 'stock.location', "Lost and Found",
+ states={
+ 'invisible': Eval('type') != 'warehouse',
+ 'readonly': ~Eval('active'),
+ },
+ domain=[
+ ('type', '=', 'lost_found'),
+ ],
+ depends=['type', 'active'],
+ help="Used, by inventories, when correcting stock levels "
+ "in the warehouse.")
quantity = fields.Function(
fields.Float('Quantity',
help="The amount of stock in the location."),
@@ -304,6 +316,11 @@
cls._default_warehouse_cache.set(None, warehouse)
return warehouse
+ @property
+ def lost_found_used(self):
+ if self.warehouse:
+ return self.warehouse.lost_found_location
+
@classmethod
def search_rec_name(cls, name, clause):
if clause[1].startswith('!') or clause[1].startswith('not '):
diff -r da645fd3072b -r 7c417dc2d884 location.xml
--- a/location.xml Tue Mar 17 20:08:12 2020 +0100
+++ b/location.xml Tue Mar 17 23:35:47 2020 +0100
@@ -194,6 +194,10 @@
<field name="code">STO</field>
<field name="type">storage</field>
</record>
+ <record model="stock.location" id="location_lost_found">
+ <field name="name">Lost and Found</field>
+ <field name="type">lost_found</field>
+ </record>
<record model="stock.location" id="location_warehouse">
<field name="name">Warehouse</field>
<field name="code">WH</field>
@@ -201,6 +205,7 @@
<field name="input_location" ref="location_input"/>
<field name="output_location" ref="location_output"/>
<field name="storage_location" ref="location_storage"/>
+ <field name="lost_found_location" ref="location_lost_found"/>
</record>
<record model="stock.location" id="location_supplier">
<field name="name">Supplier</field>
@@ -212,10 +217,6 @@
<field name="code">CUS</field>
<field name="type">customer</field>
</record>
- <record model="stock.location" id="location_lost_found">
- <field name="name">Lost and Found</field>
- <field name="type">lost_found</field>
- </record>
<record model="stock.location" id="location_transit">
<field name="name">Transit</field>
<field name="type">storage</field>
diff -r da645fd3072b -r 7c417dc2d884 message.xml
--- a/message.xml Tue Mar 17 20:08:12 2020 +0100
+++ b/message.xml Tue Mar 17 23:35:47 2020 +0100
@@ -41,6 +41,9 @@
<record model="ir.message" id="msg_inventory_missing_empty_quantity">
<field name="text">To confirm the inventory "%(inventory)s" you
must select an option for empty quantity.</field>
</record>
+ <record model="ir.message"
id="msg_inventory_location_missing_lost_found">
+ <field name="text">To confirm the inventory "%(inventory)s" you
must set a lost and found on a parent of location "%(location)s".</field>
+ </record>
<record model="ir.message" id="msg_inventory_line_unique">
<field name="text">Inventory line "%(line)s" is not unique on
inventory "%(inventory)s".</field>
</record>
diff -r da645fd3072b -r 7c417dc2d884 tests/scenario_stock_inventory.rst
--- a/tests/scenario_stock_inventory.rst Tue Mar 17 20:08:12 2020 +0100
+++ b/tests/scenario_stock_inventory.rst Tue Mar 17 23:35:47 2020 +0100
@@ -28,6 +28,7 @@
>>> supplier_loc, = Location.find([('code', '=', 'SUP')])
>>> storage_loc, = Location.find([('code', '=', 'STO')])
>>> customer_loc, = Location.find([('code', '=', 'CUS')])
+ >>> lost_found_loc, = Location.find([('type', '=', 'lost_found')])
Create products::
@@ -170,7 +171,7 @@
>>> move, = line_p1.moves
>>> move.quantity
1.0
- >>> move.from_location == inventory.lost_found
+ >>> move.from_location == lost_found_loc
True
>>> move.to_location == inventory.location
True
@@ -230,7 +231,7 @@
>>> move, = line.moves
>>> move.quantity
5.0
- >>> move.from_location == inventory.lost_found
+ >>> move.from_location == lost_found_loc
True
>>> move.to_location == inventory.location
True
diff -r da645fd3072b -r 7c417dc2d884
tests/scenario_stock_inventory_empty_quantity.rst
--- a/tests/scenario_stock_inventory_empty_quantity.rst Tue Mar 17 20:08:12
2020 +0100
+++ b/tests/scenario_stock_inventory_empty_quantity.rst Tue Mar 17 23:35:47
2020 +0100
@@ -28,6 +28,7 @@
>>> supplier_loc, = Location.find([('code', '=', 'SUP')])
>>> storage_loc, = Location.find([('code', '=', 'STO')])
>>> customer_loc, = Location.find([('code', '=', 'CUS')])
+ >>> lost_found_loc, = Location.find([('type', '=', 'lost_found')])
Create product::
@@ -83,5 +84,5 @@
1.0
>>> move.from_location == inventory.location
True
- >>> move.to_location == inventory.lost_found
+ >>> move.to_location == lost_found_loc
True
diff -r da645fd3072b -r 7c417dc2d884 view/inventory_form.xml
--- a/view/inventory_form.xml Tue Mar 17 20:08:12 2020 +0100
+++ b/view/inventory_form.xml Tue Mar 17 23:35:47 2020 +0100
@@ -6,15 +6,17 @@
<field name="location"/>
<label name="number"/>
<field name="number"/>
+
<label name="date"/>
<field name="date"/>
- <label name="lost_found"/>
- <field name="lost_found"/>
<label name="company"/>
<field name="company"/>
+
<label name="empty_quantity"/>
<field name="empty_quantity"/>
+
<field name="lines" colspan="4"/>
+
<label name="state"/>
<field name="state"/>
<group colspan="2" col="-1" id="buttons">
diff -r da645fd3072b -r 7c417dc2d884 view/location_form.xml
--- a/view/location_form.xml Tue Mar 17 20:08:12 2020 +0100
+++ b/view/location_form.xml Tue Mar 17 23:35:47 2020 +0100
@@ -28,5 +28,10 @@
<field name="storage_location"/>
<label name="picking_location"/>
<field name="picking_location"/>
+
+ <label name="lost_found_location"/>
+ <field name="lost_found_location"/>
+ <newline/>
+
<field name="childs" colspan="4"/>
</form>