[MOV] stock: barcode, procurement, product, res_*

Move models not located in stock.py file and their views:

 - barcode
 - procurement
 - product
 - product.putaway, product.removal and stock.fixed.putaway.strat are
   extracted from product.py to their own product_strategy file
   to separate product and product.template code from stock specific
   code related to products
 - res_*
 - settings
 - web_planner

This commit only moves files. No change is done.
This commit is contained in:
Thibault Delavallée
2016-04-29 12:18:36 +02:00
parent 3116e8946b
commit e28b83603b
19 changed files with 278 additions and 250 deletions
+4 -10
View File
@@ -1,14 +1,8 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from stock import *
import partner
import product
import procurement
import report
import wizard
import res_config
import res_company
import web_planner
import controllers
import models
import report
import stock
import wizard
+5 -3
View File
@@ -69,10 +69,12 @@ Dashboard / Reports for Inventory Management will include:
'wizard/stock_immediate_transfer.xml',
'wizard/stock_backorder_confirmation.xml',
'views/res_partner_views.xml',
'views/product_strategy_views.xml',
'stock_view.xml',
'product_view.xml',
'partner_view.xml',
'res_config_view.xml',
'views/procurement_views.xml',
'views/product_views.xml',
'views/stock_config_settings_views.xml',
'stock_dashboard.xml',
'data/default_barcode_patterns.xml',
+11
View File
@@ -0,0 +1,11 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import barcode
import product
import procurement
import product_strategy
import res_company
import res_partner
import stock_config_settings
import web_planner
+19
View File
@@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import models
from odoo.tools.translate import _
class barcode_rule(models.Model):
_inherit = 'barcode.rule'
def _get_type_selection(self):
types = set(super(barcode_rule, self)._get_type_selection())
types.update([
('weight', _('Weighted Product')),
('location', _('Location')),
('lot', _('Lot')),
('package', _('Package'))
])
return list(types)
@@ -8,6 +8,7 @@ import openerp.addons.decimal_precision as dp
from openerp.tools.float_utils import float_round
from openerp.exceptions import UserError
class product_product(osv.osv):
_inherit = "product.product"
@@ -513,55 +514,6 @@ class product_template(osv.osv):
return super(product_template, self).write(cr, uid, ids, vals, context=context)
class product_removal_strategy(osv.osv):
_name = 'product.removal'
_description = 'Removal Strategy'
_columns = {
'name': fields.char('Name', required=True),
'method': fields.char("Method", required=True, help="FIFO, LIFO..."),
}
class product_putaway_strategy(osv.osv):
_name = 'product.putaway'
_description = 'Put Away Strategy'
def _get_putaway_options(self, cr, uid, context=None):
return [('fixed', 'Fixed Location')]
_columns = {
'name': fields.char('Name', required=True),
'method': fields.selection(_get_putaway_options, "Method", required=True),
'fixed_location_ids': fields.one2many('stock.fixed.putaway.strat', 'putaway_id', 'Fixed Locations Per Product Category', help="When the method is fixed, this location will be used to store the products", copy=True),
}
_defaults = {
'method': 'fixed',
}
def putaway_apply(self, cr, uid, ids, product, context=None):
putaway_strat = self.browse(cr, uid, ids[0], context=context)
if putaway_strat.method == 'fixed':
for strat in putaway_strat.fixed_location_ids:
categ = product.categ_id
while categ:
if strat.category_id.id == categ.id:
return strat.fixed_location_id.id
categ = categ.parent_id
class fixed_putaway_strat(osv.osv):
_name = 'stock.fixed.putaway.strat'
_order = 'sequence'
_columns = {
'putaway_id': fields.many2one('product.putaway', 'Put Away Method', required=True),
'category_id': fields.many2one('product.category', 'Product Category', required=True),
'fixed_location_id': fields.many2one('stock.location', 'Location', required=True),
'sequence': fields.integer('Priority', help="Give to the more specialized category, a higher priority to have them in top of the list."),
}
class product_category(osv.osv):
_inherit = 'product.category'
+53
View File
@@ -0,0 +1,53 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from openerp.osv import fields, osv
class product_removal_strategy(osv.osv):
_name = 'product.removal'
_description = 'Removal Strategy'
_columns = {
'name': fields.char('Name', required=True),
'method': fields.char("Method", required=True, help="FIFO, LIFO..."),
}
class product_putaway_strategy(osv.osv):
_name = 'product.putaway'
_description = 'Put Away Strategy'
def _get_putaway_options(self, cr, uid, context=None):
return [('fixed', 'Fixed Location')]
_columns = {
'name': fields.char('Name', required=True),
'method': fields.selection(_get_putaway_options, "Method", required=True),
'fixed_location_ids': fields.one2many('stock.fixed.putaway.strat', 'putaway_id', 'Fixed Locations Per Product Category', help="When the method is fixed, this location will be used to store the products", copy=True),
}
_defaults = {
'method': 'fixed',
}
def putaway_apply(self, cr, uid, ids, product, context=None):
putaway_strat = self.browse(cr, uid, ids[0], context=context)
if putaway_strat.method == 'fixed':
for strat in putaway_strat.fixed_location_ids:
categ = product.categ_id
while categ:
if strat.category_id.id == categ.id:
return strat.fixed_location_id.id
categ = categ.parent_id
class fixed_putaway_strat(osv.osv):
_name = 'stock.fixed.putaway.strat'
_order = 'sequence'
_columns = {
'putaway_id': fields.many2one('product.putaway', 'Put Away Method', required=True),
'category_id': fields.many2one('product.category', 'Product Category', required=True),
'fixed_location_id': fields.many2one('stock.location', 'Location', required=True),
'sequence': fields.integer('Priority', help="Give to the more specialized category, a higher priority to have them in top of the list."),
}
-14
View File
@@ -5,7 +5,6 @@ from datetime import datetime
from dateutil import relativedelta
import json
import time
import sets
from openerp.osv import fields, osv
from openerp.tools.float_utils import float_compare, float_round
@@ -4936,19 +4935,6 @@ class stock_picking_type(osv.osv):
'use_create_lots': True,
}
class barcode_rule(models.Model):
_inherit = 'barcode.rule'
def _get_type_selection(self):
types = sets.Set(super(barcode_rule,self)._get_type_selection())
types.update([
('weight', _('Weighted Product')),
('location', _('Location')),
('lot', _('Lot')),
('package', _('Package'))
])
return list(types)
class StockPackOperation(models.Model):
_inherit = 'stock.pack.operation'
-157
View File
@@ -386,42 +386,6 @@
</field>
</record>
<record id="view_putaway" model="ir.ui.view">
<field name="name">product.putaway.form</field>
<field name="model">product.putaway</field>
<field name="arch" type="xml">
<form string="Putaway">
<group colspan="4">
<field name="name"/>
<field name="method"/>
</group>
<div attrs="{'invisible': [('method', '!=', 'fixed')]}">
<separator string="Fixed Locations Per Categories"/>
<field name="fixed_location_ids" colspan="4" nolabel="1">
<tree editable="top">
<field name="sequence" widget='handle'/>
<field name="category_id"/>
<field name="fixed_location_id"/>
</tree>
</field>
</div>
</form>
</field>
</record>
<record id="view_removal" model="ir.ui.view">
<field name="name">product.removal.form</field>
<field name="model">product.removal</field>
<field name="arch" type="xml">
<form string="Removal">
<group col="4">
<field name="name"/>
<field name="method"/>
</group>
</form>
</field>
</record>
<record id="stock_location_path_filter" model="ir.ui.view">
<field name="name">stock.location.path.select</field>
<field name="model">stock.location.path</field>
@@ -485,24 +449,6 @@
</field>
</record>
<record id="product_category_form_view_inherit" model="ir.ui.view">
<field name="name">product.category.form</field>
<field name="model">product.category</field>
<field name="inherit_id" ref="product.product_category_form_view" />
<field name="arch" type="xml">
<group name="first" position="after">
<group string="Logistics">
<field name="route_ids" widget="many2many_tags"/>
<div colspan="2" attrs="{'invisible': [('parent_id', '=', False)]}">
The following routes will apply to the products in this category taking into account parent categories:
<field name="total_route_ids" nolabel="1" widget="many2many_tags"/>
</div>
<field name="removal_strategy_id" options="{'no_create': True}"/>
</group>
</group>
</field>
</record>
<record id="action_location_form" model="ir.actions.act_window">
<field name="name">Locations</field>
<field name="res_model">stock.location</field>
@@ -1918,86 +1864,6 @@
src_model="stock.warehouse"
groups="stock.group_stock_user"/>
<!-- Procurements -->
<record id="view_procurement_form_stock_inherit" model="ir.ui.view">
<field name="name">procurement.order.form.stock.inherit</field>
<field name="model">procurement.order</field>
<field name="inherit_id" ref="procurement.procurement_form_view"/>
<field name="arch" type="xml">
<xpath expr="//group[@name='scheduling']" position="before">
<group>
<field name="warehouse_id" on_change="change_warehouse_id(warehouse_id, context)"/>
<field name="location_id" domain="[('usage', '=', 'internal')]"/>
<field name="route_ids" widget="many2many_tags" groups="stock.group_adv_location"/>
</group>
</xpath>
<div name="button_box" position="inside">
<button name="do_view_pickings" class="oe_stat_button" icon="fa-bars" string="Group's Pickings" type="object"/>
</div>
<xpath expr="//field[@name='rule_id']" position="replace">
<field name="rule_id" domain="['|', ('location_id', '=', False), ('location_id', '=', location_id)]"/>
<field name="partner_dest_id"/>
</xpath>
</field>
</record>
<record id="view_procurement_tree_stock_inherit" model="ir.ui.view">
<field name="name">procurement.order.tree.stock.inherit</field>
<field name="model">procurement.order</field>
<field name="inherit_id" ref="procurement.procurement_tree_view"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='origin']" position="before">
<field name="location_id"/>
</xpath>
</field>
</record>
<record id="view_procurement_rule_tree_stock_inherit" model="ir.ui.view">
<field name="name">procurement.rule.tree.stock.inherit</field>
<field name="model">procurement.rule</field>
<field name="inherit_id" ref="procurement.view_procurement_rule_tree"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='action']" position="after">
<field name="picking_type_id"/>
</xpath>
</field>
</record>
<record id="view_procurement_rule_form_stock_inherit" model="ir.ui.view">
<field name="name">procurement.rule.form.stock.inherit</field>
<field name="model">procurement.rule</field>
<field name="inherit_id" ref="procurement.view_procurement_rule_form"/>
<field name="arch" type="xml">
<xpath expr="//group[@name='general']" position="after">
<group>
<group string="Applied On">
<field name="location_id"/>
<field name="warehouse_id" groups="base.group_no_one"/>
</group>
<group string="Creates">
<field name="location_src_id" attrs="{'required': [('action', '=', 'move')], 'invisible':[('action', '!=', 'move')]}" domain="[('usage','!=','view')]"/>
<field name="procure_method" groups="stock.group_adv_location" attrs="{'invisible': [('action', '!=', 'move')]}"/>
<field name="picking_type_id" attrs="{'required': [('action', '!=', 'manufacture')]}"/>
<field name="partner_address_id" groups="stock.group_adv_location" context="{'show_address': 1}" options="{'always_reload': 1}" attrs="{'invisible': [('action', '!=', 'move')]}"/>
<label for="delay" string="Delay" groups="stock.group_adv_location" attrs="{'invisible': [('action', '!=', 'move')]}"/>
<div groups="stock.group_adv_location" attrs="{'invisible': [('action', '!=', 'move')]}">
<field name="delay" class="oe_inline"/>days
</div>
</group>
</group>
</xpath>
<xpath expr="//field[@name='group_id']" position="after">
<field name="propagate"/>
<field name="propagate_warehouse_id"/>
</xpath>
</field>
</record>
<record model="ir.actions.act_window" id="procrules">
<field name="context">{'search_default_route_false':1}</field>
<field name="name">Procurement Rules</field>
<field name="res_model">procurement.rule</field>
</record>
<record model="ir.actions.act_window" id="stolocpath">
<field name="context">{'search_default_route_false':1}</field>
<field name="name">Push Rules</field>
@@ -2131,23 +1997,10 @@
</field>
</record>
<!-- Procurements are located in Warehouse menu hierarchy, MRP users should come to Stock application to use it. -->
<menuitem id="menu_stock_sched" name="Schedulers" parent="stock.menu_stock_root" groups="group_stock_manager" sequence="50"/>
<menuitem action="action_procurement_compute" id="menu_procurement_compute" parent="menu_stock_sched" sequence="2"/>
<menuitem action="procurement.action_compute_schedulers" id="menu_stock_proc_schedulers" parent="menu_stock_sched" sequence="1" groups="stock.group_stock_manager"/>
<menuitem id="menu_stock_procurement" name="Automatic Procurements" parent="stock.menu_stock_config_settings" sequence="5"/>
<menuitem action="procurement.procurement_order_action_exceptions" id="menu_stock_procurement_action" parent="stock.menu_warehouse_report" sequence="150" groups="stock.group_stock_manager"/>
<menuitem action="action_move_form2" id="menu_action_move_form2" parent="stock.menu_warehouse_report" sequence="130"/>
<menuitem id="menu_quants" name="Inventory Valuation" parent="stock.menu_warehouse_report" sequence="120" action="quantsact"/>
<menuitem id="menu_procurement_rules" name="Global Procurement Rules" parent="stock.menu_routes_config" action="procrules" groups="base.group_no_one" sequence="3"/>
<menuitem id="menu_stock_location_path" name="Global Push Rules" parent="stock.menu_routes_config" action="stolocpath" groups="base.group_no_one" sequence="4"/>
<menuitem id="menu_pickingtype" name="Operations Types" parent="stock.menu_warehouse_config" action="action_picking_type_list" sequence="4" groups="stock.group_stock_multi_locations"/>
<record model="ir.actions.act_window" id="product_open_orderpoint">
<field name="context">{'default_product_id': active_id, 'search_default_product_id': active_id}</field>
<field name="name">Reordering Rules</field>
<field name="res_model">stock.warehouse.orderpoint</field>
</record>
<record model="ir.actions.act_window" id="product_template_open_quants">
<field name="name">Stock On Hand</field>
@@ -2369,15 +2222,5 @@
<field name="view_mode">tree,form</field>
<field name="domain">[('group_id','=',active_id)]</field>
</record>
<record id="procurement_group_form_view_herited" model="ir.ui.view">
<field name="name">procurement.group.form.herited</field>
<field name="model">procurement.group</field>
<field name="inherit_id" ref="procurement.procurement_group_form_view"/>
<field name="arch" type="xml">
<div name="button_box" position="inside">
<button name="%(do_view_pickings)d" string="Pickings" type="action"/>
</div>
</field>
</record>
</data>
</openerp>
+101
View File
@@ -0,0 +1,101 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="procurement_group_form_view_herited" model="ir.ui.view">
<field name="name">procurement.group.view.form.inherit.picking</field>
<field name="model">procurement.group</field>
<field name="inherit_id" ref="procurement.procurement_group_form_view"/>
<field name="arch" type="xml">
<div name="button_box" position="inside">
<button name="%(do_view_pickings)d" string="Pickings" type="action"/>
</div>
</field>
</record>
<!-- Procurements -->
<record id="view_procurement_form_stock_inherit" model="ir.ui.view">
<field name="name">procurement.order.form.stock.inherit</field>
<field name="model">procurement.order</field>
<field name="inherit_id" ref="procurement.procurement_form_view"/>
<field name="arch" type="xml">
<xpath expr="//group[@name='scheduling']" position="before">
<group>
<field name="warehouse_id" on_change="change_warehouse_id(warehouse_id, context)"/>
<field name="location_id" domain="[('usage', '=', 'internal')]"/>
<field name="route_ids" widget="many2many_tags" groups="stock.group_adv_location"/>
</group>
</xpath>
<div name="button_box" position="inside">
<button name="do_view_pickings" class="oe_stat_button" icon="fa-bars" string="Group's Pickings" type="object"/>
</div>
<xpath expr="//field[@name='rule_id']" position="replace">
<field name="rule_id" domain="['|', ('location_id', '=', False), ('location_id', '=', location_id)]"/>
<field name="partner_dest_id"/>
</xpath>
</field>
</record>
<record id="view_procurement_tree_stock_inherit" model="ir.ui.view">
<field name="name">procurement.order.tree.stock.inherit</field>
<field name="model">procurement.order</field>
<field name="inherit_id" ref="procurement.procurement_tree_view"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='origin']" position="before">
<field name="location_id"/>
</xpath>
</field>
</record>
<record id="view_procurement_rule_tree_stock_inherit" model="ir.ui.view">
<field name="name">procurement.rule.tree.stock.inherit</field>
<field name="model">procurement.rule</field>
<field name="inherit_id" ref="procurement.view_procurement_rule_tree"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='action']" position="after">
<field name="picking_type_id"/>
</xpath>
</field>
</record>
<record id="view_procurement_rule_form_stock_inherit" model="ir.ui.view">
<field name="name">procurement.rule.form.stock.inherit</field>
<field name="model">procurement.rule</field>
<field name="inherit_id" ref="procurement.view_procurement_rule_form"/>
<field name="arch" type="xml">
<xpath expr="//group[@name='general']" position="after">
<group>
<group string="Applied On">
<field name="location_id"/>
<field name="warehouse_id" groups="base.group_no_one"/>
</group>
<group string="Creates">
<field name="location_src_id" attrs="{'required': [('action', '=', 'move')], 'invisible':[('action', '!=', 'move')]}" domain="[('usage','!=','view')]"/>
<field name="procure_method" groups="stock.group_adv_location" attrs="{'invisible': [('action', '!=', 'move')]}"/>
<field name="picking_type_id" attrs="{'required': [('action', '!=', 'manufacture')]}"/>
<field name="partner_address_id" groups="stock.group_adv_location" context="{'show_address': 1}" options="{'always_reload': 1}" attrs="{'invisible': [('action', '!=', 'move')]}"/>
<label for="delay" string="Delay" groups="stock.group_adv_location" attrs="{'invisible': [('action', '!=', 'move')]}"/>
<div groups="stock.group_adv_location" attrs="{'invisible': [('action', '!=', 'move')]}">
<field name="delay" class="oe_inline"/>days
</div>
</group>
</group>
</xpath>
<xpath expr="//field[@name='group_id']" position="after">
<field name="propagate"/>
<field name="propagate_warehouse_id"/>
</xpath>
</field>
</record>
<record model="ir.actions.act_window" id="procrules">
<field name="context">{'search_default_route_false':1}</field>
<field name="name">Procurement Rules</field>
<field name="res_model">procurement.rule</field>
</record>
<!-- Procurements are located in Warehouse menu hierarchy, MRP users should come to Stock application to use it. -->
<menuitem id="menu_stock_sched" name="Schedulers" parent="stock.menu_stock_root" groups="group_stock_manager" sequence="50"/>
<menuitem action="action_procurement_compute" id="menu_procurement_compute" parent="menu_stock_sched" sequence="2"/>
<menuitem action="procurement.action_compute_schedulers" id="menu_stock_proc_schedulers" parent="menu_stock_sched" sequence="1" groups="stock.group_stock_manager"/>
<menuitem id="menu_stock_procurement" name="Automatic Procurements" parent="stock.menu_stock_config_settings" sequence="5"/>
<menuitem action="procurement.procurement_order_action_exceptions" id="menu_stock_procurement_action" parent="stock.menu_warehouse_report" sequence="150" groups="stock.group_stock_manager"/>
<menuitem id="menu_procurement_rules" name="Global Procurement Rules" parent="stock.menu_routes_config" action="procrules" groups="base.group_no_one" sequence="3"/>
</odoo>
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_putaway" model="ir.ui.view">
<field name="name">product.putaway.form</field>
<field name="model">product.putaway</field>
<field name="arch" type="xml">
<form string="Putaway">
<group colspan="4">
<field name="name"/>
<field name="method"/>
</group>
<div attrs="{'invisible': [('method', '!=', 'fixed')]}">
<separator string="Fixed Locations Per Categories"/>
<field name="fixed_location_ids" colspan="4" nolabel="1">
<tree editable="top">
<field name="sequence" widget='handle'/>
<field name="category_id"/>
<field name="fixed_location_id"/>
</tree>
</field>
</div>
</form>
</field>
</record>
<record id="view_removal" model="ir.ui.view">
<field name="name">product.removal.form</field>
<field name="model">product.removal</field>
<field name="arch" type="xml">
<form string="Removal">
<group col="4">
<field name="name"/>
<field name="method"/>
</group>
</form>
</field>
</record>
</odoo>
@@ -2,6 +2,30 @@
<openerp>
<data>
<record id="product_category_form_view_inherit" model="ir.ui.view">
<field name="name">product.category.form</field>
<field name="model">product.category</field>
<field name="inherit_id" ref="product.product_category_form_view" />
<field name="arch" type="xml">
<group name="first" position="after">
<group string="Logistics">
<field name="route_ids" widget="many2many_tags"/>
<div colspan="2" attrs="{'invisible': [('parent_id', '=', False)]}">
The following routes will apply to the products in this category taking into account parent categories:
<field name="total_route_ids" nolabel="1" widget="many2many_tags"/>
</div>
<field name="removal_strategy_id" options="{'no_create': True}"/>
</group>
</group>
</field>
</record>
<record model="ir.actions.act_window" id="product_open_orderpoint">
<field name="context">{'default_product_id': active_id, 'search_default_product_id': active_id}</field>
<field name="name">Reordering Rules</field>
<field name="res_model">stock.warehouse.orderpoint</field>
</record>
<record id="view_stock_product_tree" model="ir.ui.view">
<field name="name">product.stock.tree.inherit</field>
<field name="model">product.product</field>
@@ -328,5 +352,24 @@
</data>
</field>
</record>
<record id="product_template_action_product" model="ir.actions.act_window">
<field name="name">Products</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">product.template</field>
<field name="view_mode">kanban,tree,form</field>
<field name="view_type">form</field>
<field name="context">{"search_default_products": 1, 'default_type': 'product'}</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to define a new product.
</p>
</field>
</record>
<menuitem id="menu_product_variant_config_stock" name="Products" action="product_template_action_product"
parent="stock.menu_stock_inventory_control" sequence="1"/>
<menuitem id="product_product_menu" name="Product Variants" action="product.product_normal_action"
parent="menu_stock_inventory_control" sequence="2" groups="product.group_product_variant"/>
</data>
</openerp>
+3 -17
View File
@@ -11,9 +11,11 @@
<menuitem id="menu_warehouse_config" name="Warehouse Management" parent="menu_stock_config_settings" groups="stock.group_stock_manager" sequence="1"/>
<menuitem id="menu_routes_config" name="Routes" parent="menu_stock_config_settings" sequence="2" groups="stock.group_adv_location"/>
<menuitem id="menu_packages_config" name="Packages" parent="menu_stock_config_settings" sequence="3" groups="product.group_stock_packaging"/>
<menuitem id="menu_wms_barcode_nomenclature_all" parent="menu_stock_config_settings" action="barcodes.action_barcode_nomenclature_form"
sequence="50" groups="base.group_no_one"/>
<menuitem id="menu_product_in_config_stock" name="Products" parent="stock.menu_stock_config_settings" sequence="4"/>
<menuitem
action="product.product_category_action_form" id="menu_product_category_config_stock"
parent="stock.menu_product_in_config_stock" sequence="2"/>
@@ -23,27 +25,11 @@
<menuitem
id="menu_stock_unit_measure_stock" name="Units of Measure"
parent="stock.menu_product_in_config_stock" sequence="35" groups="product.group_uom"/>
<menuitem id="menu_stock_uom_form_action" action="product.product_uom_form_action"
parent="menu_stock_config_settings" sequence="35" groups="product.group_uom"/>
<menuitem id="menu_stock_inventory_control" name="Inventory Control" parent="menu_stock_root" sequence="4"/>
<record id="product_template_action_product" model="ir.actions.act_window">
<field name="name">Products</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">product.template</field>
<field name="view_mode">kanban,tree,form</field>
<field name="view_type">form</field>
<field name="context">{"search_default_products": 1, 'default_type': 'product'}</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to define a new product.
</p>
</field>
</record>
<menuitem id="menu_product_variant_config_stock" name="Products" action="product_template_action_product"
parent="stock.menu_stock_inventory_control" sequence="1"/>
<menuitem id="product_product_menu" name="Product Variants" action="product.product_normal_action"
parent="menu_stock_inventory_control" sequence="2" groups="product.group_product_variant"/>
<menuitem id="stock.menu_warehouse_report" name="Reports" sequence="99" parent="stock.menu_stock_root" groups="group_stock_manager"/>
</odoo>