+ Click to create a Procurement order in exception state, or remove the filter on the search bar to display all the procurements.
+
+
+ Procurement Orders represent the need for a certain quantity of products, at a given time, in a given location.
+
+
+ Sales Orders are one typical source of Procurement Orders (but these are distinct documents).
+ Depending on the procurement parameters and the product configuration, the procurement engine will attempt to satisfy the need by reserving products from stock, ordering products from a supplier, or passing a manufacturing order, etc...
+
+
+ A Procurement Exception occurs when the system cannot find a way to fulfill a procurement. Some exceptions will resolve themselves automatically, but others require manual intervention (those are identified by a specific error message in the chatter).
+
- Click to create a Procurement Exception, or remove the filter on the search bar to display all the procurements.
+ Click to create a procurement order.
- Procurement Orders represent the need for a certain quantity of products, at a given time, in a given location.
+ A procurement order is used to record a need for a specific
+ product at a specific location. Procurement orders are usually
+ created automatically from sales orders, pull logistic rules or
+ minimum stock rules.
- Sales Orders are one typical source of Procurement Orders (but these are distinct documents).
- Depending on the procurement parameters and the product configuration, the procurement engine will attempt to satisfy the need by reserving products from stock, ordering products from a supplier, or passing a manufacturing order, etc...
+ When the procurement order is confirmed, it automatically
+ creates the necessary operations to fullfil the need: purchase
+ order proposition, manufacturing order, etc.
+
- A Procurement Exception occurs when the system cannot find a way to fulfill a procurement. Some exceptions will resolve themselves automatically, but others require manual intervention (those are identified by a specific error message in the chatter).
+ A procurement order is used to record a need for a specific
+ product at a specific location. Procurement orders are usually
+ created automatically from sales orders, pull logistic rules or
+ minimum stock rules.
+
+
+ When the procurement order is confirmed, it automatically
+ creates the necessary operations to fullfil the need: purchase
+ order proposition, manufacturing order, etc.
diff --git a/addons/procurement/product_product_view.xml b/addons/procurement/product_product_view.xml
new file mode 100644
index 00000000000..0a40e60b871
--- /dev/null
+++ b/addons/procurement/product_product_view.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+ product.template.procurement.stat.button
+ product.template
+
+
+
+
+
+
+
+
+
+ product.product.procurement.stat.button
+ product.product
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/addons/stock/product.py b/addons/stock/product.py
index fe5b21de417..f864aa2b65b 100644
--- a/addons/stock/product.py
+++ b/addons/stock/product.py
@@ -201,6 +201,13 @@ class product_product(osv.osv):
res[product.id] = str(product.qty_available) + _(" On Hand")
return res
+ def _compute_nbr_reordering_rules(self, cr, uid, ids, field_names=None, arg=None, context=None):
+ res = {}
+ product_data = self.pool['stock.warehouse.orderpoint'].read_group(cr, uid, [('product_id', 'in', ids)], ['product_id'], ['product_id'], context=context)
+ for data in product_data:
+ res[data['product_id'][0]] = int(data['product_id_count'])
+ return res
+
_columns = {
'reception_count': fields.function(_stock_move_count, string="Receipt", type='integer', multi='pickings'),
'delivery_count': fields.function(_stock_move_count, string="Delivery", type='integer', multi='pickings'),
@@ -259,6 +266,7 @@ class product_product(osv.osv):
'location_id': fields.dummy(string='Location', relation='stock.location', type='many2one'),
'warehouse_id': fields.dummy(string='Warehouse', relation='stock.warehouse', type='many2one'),
'orderpoint_ids': fields.one2many('stock.warehouse.orderpoint', 'product_id', 'Minimum Stock Rules'),
+ 'nbr_reordering_rules': fields.function(_compute_nbr_reordering_rules, string='Reordering Rules', type='integer'),
}
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
@@ -365,7 +373,13 @@ class product_template(osv.osv):
res[product.id] = str(product.qty_available) + _(" On Hand")
return res
-
+ def _compute_nbr_reordering_rules(self, cr, uid, ids, field_names=None, arg=None, context=None):
+ res = dict.fromkeys(ids, 0)
+ product_data = self.pool['stock.warehouse.orderpoint'].read_group(cr, uid, [('product_id.product_tmpl_id', 'in', ids)], ['product_id'], ['product_id'], context=context)
+ for data in product_data:
+ product_tmpl_id = data['__domain'][1][2][0]
+ res[product_tmpl_id] += data['product_id_count']
+ return res
_columns = {
'type': fields.selection([('product', 'Stockable Product'), ('consu', 'Consumable'), ('service', 'Service')], 'Product Type', required=True, help="Consumable: Will not imply stock management for this product. \nStockable product: Will imply stock management for this product."),
@@ -409,6 +423,8 @@ class product_template(osv.osv):
'route_ids': fields.many2many('stock.location.route', 'stock_route_product', 'product_id', 'route_id', 'Routes', domain="[('product_selectable', '=', True)]",
help="Depending on the modules installed, this will allow you to define the route of the product: whether it will be bought, manufactured, MTO/MTS,..."),
+ 'nbr_reordering_rules': fields.function(_compute_nbr_reordering_rules, string='Reordering Rules', type='integer'),
+ 'route_from_categ_ids': fields.related('categ_id', 'total_route_ids', type="many2many", relation="stock.location.route", string="Category Routes"),
}
_defaults = {
@@ -467,7 +483,6 @@ class product_template(osv.osv):
result['context'] = "{}"
return result
-
def action_view_stock_moves(self, cr, uid, ids, context=None):
products = self._get_products(cr, uid, ids, context=context)
result = self._get_act_window_dict(cr, uid, 'stock.act_product_stock_move_open', context=context)
diff --git a/addons/stock/product_view.xml b/addons/stock/product_view.xml
index 3ad0e10837a..3eeee833fd0 100644
--- a/addons/stock/product_view.xml
+++ b/addons/stock/product_view.xml
@@ -148,13 +148,12 @@
{'default_groups_ref': ['base.group_user', 'base.group_sale_manager', 'stock.group_stock_manager']}
-
-
-
-
-
-
-
+
+
+
+
+
+
@@ -227,10 +226,12 @@
type="action" attrs="{'invisible':[('type', '=', 'service')]}" groups="stock.group_locations">
-
+
-
+ attrs="{'invisible':[('type', '=', 'service')]}" icon="fa-refresh">
+
+
+
@@ -247,10 +248,12 @@
type="object" attrs="{'invisible':[('type', '=', 'service')]}" groups="stock.group_locations">
-
+
-
+ attrs="{'invisible':[('type', 'in', ('service','consu'))]}" icon="fa-refresh">
+
+
+
diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml
index 0688ca7051b..e4730974ea0 100644
--- a/addons/stock/stock_view.xml
+++ b/addons/stock/stock_view.xml
@@ -486,7 +486,6 @@
-
Locations
@@ -1952,7 +1951,8 @@
-
+
+