[IMP] product: clean forms and improve archiving

Several last cleaning in the product and product variant form :
- various labelling and design improvements
- sales, purchased and manufactured stat button (number of sales was
incorrect and click will now open normal sales analysis)
- now archiving related product.template if there is only one active product.product

Task-1880039  closes #28633
This commit is contained in:
Andrea Ulliana
2018-12-06 14:27:14 +00:00
committed by Christophe Simonis
parent 03bcd2235b
commit 4a350ff8cc
17 changed files with 102 additions and 117 deletions
+2 -2
View File
@@ -44,9 +44,9 @@ class ProductTemplate(models.Model):
action = self.env.ref('mrp.mrp_production_report').read()[0]
action['domain'] = [('state', '=', 'done'), '&', ('product_tmpl_id', 'in', self.ids)]
action['context'] = {
'search_default_last_year_mo_order': 1,
'search_default_status': 1, 'search_default_scheduled_month': 1,
'graph_measure': 'product_uom_qty',
'search_default_confirmed': 0,
'time_ranges': {'field': 'date_finished', 'range': 'last_365_days'}
}
return action
+1 -2
View File
@@ -271,8 +271,6 @@
<separator/>
<filter string="Late" domain="['&amp;', ('date_planned_start', '&lt;', current_date), ('state', '=', 'confirmed')]"
name="late" help="Production started late"/>
<filter string="Done Last 365 Days" name="last_year_mo_order"
domain="[('date_planned_start', '&gt;', (context_today() - relativedelta(days=365)).strftime('%Y-%m-%d'))]"/>
<filter string="My Activities" name="activities_my"
domain="[('activity_ids.user_id', '=', uid)]"/>
<separator/>
@@ -340,6 +338,7 @@
<field name="res_model">mrp.production</field>
<field name="view_type">form</field>
<field name="view_mode">graph,pivot,form</field>
<field name="target">current</field>
</record>
<menuitem id="menu_mrp_workorder_todo"
+2 -2
View File
@@ -87,7 +87,7 @@
<field string="Used In" name="used_in_bom_count" widget="statinfo" />
</button>
<button class="oe_stat_button" name="action_view_mos" type="object"
attrs="{'invisible': [('type', 'not in', ['product', 'consu'])]}" icon="fa-list-alt" help="Manufactured in the last 365 days">
attrs="{'invisible': ['|', ('type', 'not in', ['product', 'consu']), ('bom_count', '=', 0)]}" icon="fa-list-alt" help="Manufactured in the last 365 days">
<div class="o_field_widget o_stat_info">
<span class="o_stat_value">
<field name="mrp_product_qty" widget="statinfo" nolabel="1" class="mr4"/>
@@ -116,7 +116,7 @@
<field string="Used In" name="used_in_bom_count" widget="statinfo" />
</button>
<button class="oe_stat_button" name="action_view_mos" type="object"
attrs="{'invisible': [('type', 'not in', ['product', 'consu'])]}" icon="fa-list-alt" help="Manufactured in the last 365 days">
attrs="{'invisible': ['|', ('type', 'not in', ['product', 'consu']), ('bom_count', '=', 0)]}" icon="fa-list-alt" help="Manufactured in the last 365 days">
<div class="o_field_widget o_stat_info">
<span class="o_stat_value">
<field name="mrp_product_qty" widget="statinfo" nolabel="1" class="mr4"/>
+3 -3
View File
@@ -12,7 +12,7 @@
string="Compute Price from BoM" type="object"
attrs="{'invisible': ['|', ('bom_count', '=', 0), '&amp;', ('valuation', '=', 'real_time'), ('cost_method', '=', 'fifo')]}"
help="Compute the price of the product using products and operations of related bill of materials, for manufactured products only."
class="oe_link oe_read_only"/>
class="oe_link oe_read_only pt-0"/>
</xpath>
</field>
</record>
@@ -29,7 +29,7 @@
string="Compute Price from BoM" type="object"
attrs="{'invisible': ['|', ('bom_count', '=', 0), '&amp;', ('valuation', '=', 'real_time'), ('cost_method', '=', 'fifo')]}"
help="Compute the price of the product using products and operations of related bill of materials, for manufactured products only."
class="oe_link oe_read_only"
class="oe_link oe_read_only pt-0"
colspan="2"/>
</xpath>
</field>
@@ -48,7 +48,7 @@
type="object"
attrs="{'invisible': ['|', ('bom_count', '=', 0), '&amp;', ('valuation', '=', 'real_time'), ('cost_method', '=', 'fifo')]}"
help="Compute the price of the product using products and operations of related bill of materials, for manufactured products only."
class="oe_link oe_read_only"/>
class="oe_link oe_read_only pt-0"/>
</xpath>
</data>
</field>
+2 -2
View File
@@ -50,7 +50,7 @@
<record id="product_template_form_view" model="ir.ui.view">
<field name="name">product.template.form.inherit</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="stock.view_template_property_form"/>
<field name="inherit_id" ref="product.product_template_form_view"/>
<field name="arch" type="xml">
<xpath expr="//page[@name='sales']" position="attributes">
<attribute name="invisible">0</attribute>
@@ -71,7 +71,7 @@
<!-- Product Catalog menus and sub menus -->
<menuitem id="pos_config_menu_catalog"
name="Product"
name="Products"
parent="point_of_sale.menu_point_root"/>
<menuitem id="menu_pos_products"
action="product_template_action_pos_product"
+9 -1
View File
@@ -91,7 +91,7 @@ class ProductProduct(models.Model):
digits=dp.get_precision('Product Price'),
help="This is the sum of the extra price of all attributes")
lst_price = fields.Float(
'Sale Price', compute='_compute_product_lst_price',
'Public Price', compute='_compute_product_lst_price',
digits=dp.get_precision('Product Price'), inverse='_set_product_lst_price',
help="The sale price is managed from the product template. Click on the 'Configure Variants' button to set the extra attribute prices.")
@@ -618,6 +618,14 @@ class ProductProduct(models.Model):
attributes = values.mapped('attribute_id')
return attributes == valid_attributes and values <= valid_values
@api.multi
def toggle_active(self):
""" Archiving related product.template if there is only one active product.product """
with_one_active = self.filtered(lambda product: len(product.product_tmpl_id.product_variant_ids) == 1)
for product in with_one_active:
product.product_tmpl_id.toggle_active()
return super(ProductProduct, self - with_one_active).toggle_active()
class ProductPackaging(models.Model):
_name = "product.packaging"
+1 -1
View File
@@ -70,7 +70,7 @@ class ProductTemplate(models.Model):
'Price', compute='_compute_template_price', inverse='_set_template_price',
digits=dp.get_precision('Product Price'))
list_price = fields.Float(
'Sales Price', default=1.0,
'Sale Price', default=1.0,
digits=dp.get_precision('Product Price'),
help="Price at which the product is sold to customers.")
lst_price = fields.Float(
@@ -93,10 +93,10 @@
<field name="model">product.template.attribute.value</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Attributes" create="0" delete="0">
<tree string="Attributes" create="0" delete="0" editable="bottom">
<field name="attribute_id"/>
<field name="name"/>
<field name="price_extra" />
<field name="price_extra"/>
</tree>
</field>
</record>
@@ -111,7 +111,7 @@
<field name="name" />
<field name="price_extra" />
<field name="exclude_for" widget="one2many_list" mode="tree">
<tree editable="bottom">
<tree editable="top">
<field name="product_tmpl_id" />
<field name="value_ids" widget="many2many_tags" options="{'no_create': true}" />
</tree>
+45 -39
View File
@@ -97,13 +97,13 @@
<page string="Inventory" name="inventory" groups="product.group_stock_packaging" attrs="{'invisible':[('type', '=', 'service')]}">
<group name="inventory">
<group name="group_lots_and_weight" string="Logistics" attrs="{'invisible': [('type', 'not in', ['product', 'consu'])]}">
<label for="weight"/>
<div class="o_row" name="weight">
<label for="weight" attrs="{'invisible':[('product_variant_count', '>', 1)]}"/>
<div class="o_row" name="weight" attrs="{'invisible':[('product_variant_count', '>', 1)]}">
<field name="weight"/>
<span><field name="weight_uom_name"/></span>
</div>
<label for="volume"/>
<div class="o_row" name="volume">
<label for="volume" attrs="{'invisible':[('product_variant_count', '>', 1)]}"/>
<div class="o_row" name="volume" attrs="{'invisible':[('product_variant_count', '>', 1)]}">
<field name="volume" string="Volume"/>
<span><field name="volume_uom_name"/></span>
</div>
@@ -153,6 +153,10 @@
<filter string="Future Activities" name="activities_upcoming_all"
domain="[('activity_ids.date_deadline', '&gt;', context_today().strftime('%Y-%m-%d'))
]"/>
<group expand="1" string="Group By">
<filter string="Product Type" name="type" context="{'group_by':'type'}"/>
<filter string="Product Category" name="categ_id" context="{'group_by':'categ_id'}"/>
</group>
</search>
</field>
</record>
@@ -212,54 +216,57 @@
<field name="arch" type="xml">
<form string="Variant Information">
<sheet>
<div class="oe_button_box" name="button_box">
<button class="oe_stat_button" type="object" name="toggle_active" icon="fa-archive">
<field name="active"
widget="boolean_button"
options='{"terminology": "archive"}'/>
<field name="type" invisible="1"/>
</button>
</div>
<field name="id" invisible="1"/>
<field name="image_medium" widget="image" class="oe_avatar"/>
<div class="oe_title">
<label class="oe_edit_only" for="name" string="Product Name"/>
<h1><field name="name" placeholder="e.g. Odoo Enterprise Subscription"/></h1>
<h1><field name="name" readonly="1" placeholder="e.g. Odoo Enterprise Subscription"/></h1>
<field name="attribute_value_ids" widget="many2many_tags" readonly="1"/>
<p>
<span>All general settings about this product are managed on</span>
<button name="open_product_template" type="object" string="the product template." class="oe_link oe_link_product pl-0 ml-1 mb-1"/>
</p>
</div>
<group>
<p>All general settings about this product are managed on <button name="open_product_template" type="object" string="the product template" class="oe_link"/></p>
</group>
<group string="Attributes">
<field name="attribute_value_ids" widget="many2many_tags" readonly="1"/>
</group>
<group>
<group name="codes" string="Codes">
<field name="barcode"/>
<field name="default_code"/>
<field name="barcode"/>
</group>
<group>
<field name="active"/>
<field name="type" invisible="1"/>
</group>
</group>
<group>
<group name="pricing" string="Pricing">
<field name="product_variant_count" invisible="1"/>
<field name="lst_price" widget='monetary' options="{'currency_field': 'currency_id', 'field_digits': True}" attrs="{'readonly': [('product_variant_count', '&gt;', 1)]}"/>
<field name="standard_price" widget='monetary' options="{'currency_field': 'currency_id', 'field_digits': True}"/>
<label for="lst_price"/>
<div class="o_row col-5 pl-0">
<field name="lst_price" widget='monetary' options="{'currency_field': 'currency_id', 'field_digits': True}" attrs="{'readonly': [('product_variant_count', '&gt;', 1)]}"/>
</div>
<field name="standard_price" widget='monetary' options="{'currency_field': 'currency_id'}"/>
<field name="currency_id" invisible='1'/>
</group>
<group name="weight">
<group name="weight" string="Weights" attrs="{'invisible':[('type', 'not in', ['product', 'consu'])]}">
<label for="volume"/>
<div class="o_row">
<field name="volume"/>
<span>m³</span>
</div>
<label for="weight"/>
<div class="o_row">
<field name="weight"/>
<span>kg</span>
</div>
</group>
</group>
</group>
<group name="packaging" string="Packaging"
colspan="4"
groups="product.group_stock_packaging">
<field name="packaging_ids" nolabel="1" context="{'tree_view_ref':'product.product_packaging_tree_view2', 'form_view_ref':'product.product_packaging_form_view2'}"/>
<group>
<group name="weight" string="Logistics" attrs="{'invisible':[('type', 'not in', ['product', 'consu'])]}">
<label for="volume"/>
<div class="o_row">
<field name="volume"/>
<span>m³</span>
</div>
<label for="weight"/>
<div class="o_row">
<field name="weight"/>
<span>kg</span>
</div>
</group>
<group name="packaging" string="Packaging" groups="product.group_stock_packaging">
<field name="packaging_ids" nolabel="1"
context="{'tree_view_ref':'product.product_packaging_tree_view2', 'form_view_ref':'product.product_packaging_form_view2'}"/>
</group>
</group>
</sheet>
</form>
@@ -294,7 +301,6 @@
<field name="model">product.product</field>
<field eval="7" name="priority"/>
<field name="arch" type="xml">
<tree string="Product Variants">
<field name="default_code"/>
<field name="name"/>
+3 -4
View File
@@ -2,7 +2,6 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from datetime import timedelta
from odoo import api, fields, models, _
from odoo.addons.base.models.res_partner import WARNING_MESSAGE, WARNING_HELP
from odoo.tools.float_utils import float_round
@@ -45,9 +44,9 @@ class ProductTemplate(models.Model):
action = self.env.ref('purchase.action_purchase_order_report_all').read()[0]
action['domain'] = ['&', ('state', 'in', ['purchase', 'done']), ('product_tmpl_id', 'in', self.ids)]
action['context'] = {
'search_default_last_year_purchase': 1,
'search_default_status': 1, 'search_default_order_month': 1,
'graph_measure': 'unit_quantity'
'graph_measure': 'unit_quantity',
'search_default_orders': 1,
'time_ranges': {'field': 'date_approve', 'range': 'last_365_days'}
}
return action
@@ -56,8 +56,6 @@
<search string="Purchase Orders">
<filter string="Quotations" name="quotes" domain="[('state','=','draft')]"/>
<filter string="Orders" name="orders" domain="[('state','!=','draft'),('state','!=','cancel')]"/>
<filter string="Purchased Last 365 Days" name="last_year_purchase"
domain="[('date_order', '&gt;', (context_today() - relativedelta(days=365)).strftime('%Y-%m-%d'))]"/>
<field name="partner_id"/>
<field name="product_id"/>
<group expand="0" string="Extended Filters">
@@ -87,9 +85,9 @@
<field name="res_model">purchase.report</field>
<field name="view_type">form</field>
<field name="view_mode">graph,pivot</field>
<field name="context">{'search_default_orders': 1}</field>
<field name="view_id"></field> <!-- force empty -->
<field name="help">Purchase Analysis allows you to easily check and analyse your company purchase history and performance. From this menu you can track your negotiation performance, the delivery performance of your vendors, etc.</field>
<field name="target">current</field>
</record>
<menuitem id="purchase_report" name="Reporting" parent="purchase.menu_purchase_root" sequence="99"
+12 -9
View File
@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from datetime import timedelta
from datetime import timedelta, time
from odoo import api, fields, models
from odoo.tools.float_utils import float_round
@@ -26,12 +25,14 @@ class ProductProduct(models.Model):
r = {}
if not self.user_has_groups('sales_team.group_sale_salesman'):
return r
date_from = fields.Datetime.to_string(fields.datetime.now() - timedelta(days=365))
date_from = fields.Datetime.to_string(fields.datetime.combine(fields.datetime.now() - timedelta(days=365),
time.min))
date_to = fields.Datetime.to_string(fields.datetime.combine(fields.datetime.today(), time.min))
domain = [
('state', 'in', ['sale', 'done']),
('state', 'in', ['sale', 'done', 'paid']),
('product_id', 'in', self.ids),
('date', '>', date_from)
('date', '>=', date_from),
('date', '<', date_to)
]
for group in self.env['sale.report'].read_group(domain, ['product_id', 'product_uom_qty'], ['product_id']):
r[group['product_id'][0]] = group['product_uom_qty']
@@ -44,9 +45,11 @@ class ProductProduct(models.Model):
action = self.env.ref('sale.report_all_channels_sales_action').read()[0]
action['domain'] = [('product_id', 'in', self.ids)]
action['context'] = {
'search_default_last_year': 1,
'pivot_measures': ['product_qty'],
'search_default_team_id': 1
'pivot_measures': ['product_uom_qty'],
'active_id': self._context.get('active_id'),
'search_default_Sales': 1,
'active_model': 'sale.report',
'time_ranges': {'field': 'date', 'range': 'last_365_days'},
}
return action
+5 -3
View File
@@ -50,9 +50,11 @@ class ProductTemplate(models.Model):
action = self.env.ref('sale.report_all_channels_sales_action').read()[0]
action['domain'] = [('product_tmpl_id', 'in', self.ids)]
action['context'] = {
'search_default_last_year': 1,
'pivot_measures': ['product_qty'],
'search_default_team_id': 1
'pivot_measures': ['product_uom_qty'],
'active_id': self._context.get('active_id'),
'active_model': 'sale.report',
'search_default_Sales': 1,
'time_ranges': {'field': 'date', 'range': 'last_365_days'}
}
return action
@@ -1,38 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="report_all_channels_sales_view_pivot" model="ir.ui.view">
<field name="name">report.all.channels.sales.pivot</field>
<field name="model">report.all.channels.sales</field>
<field name="arch" type="xml">
<pivot string="Sales by Channel Analysis" disable_linking="True">
<field name="name" type="row"/>
<field name="price_total" string="Total Price" type="measure"/>
</pivot>
</field>
</record>
<record id="report_all_channels_sales_view_search" model="ir.ui.view">
<field name="name">report.all.channels.sales.search</field>
<field name="model">report.all.channels.sales</field>
<field name="arch" type="xml">
<search string="Sales by Channel Analysis">
<field name="date_order"/>
<field name="product_id"/>
<filter string="Date" name="current_year" date="date_order" default_period="this_year"/>
<filter string="Last 365 Days" name="last_year" domain="[('date_order', '&gt;=', (context_today() - datetime.timedelta(days=365)).strftime('%Y-%m-%d'))]"/>
<group expand="1" string="Group By">
<filter string="Sales Team" name="team_id" context="{'group_by':'team_id'}"/>
</group>
</search>
</field>
</record>
<record id="report_all_channels_sales_action" model="ir.actions.act_window">
<field name="name">Sales by Channel</field>
<field name="res_model">report.all.channels.sales</field>
<field name="name">Sales Analysis</field>
<field name="res_model">sale.report</field>
<field name="view_mode">pivot</field>
<field name="view_id" ref="report_all_channels_sales_view_pivot"/>
<field name="search_view_id" ref="report_all_channels_sales_view_search"/>
<field name="context">{'search_default_team_id': 1, 'search_default_current_year': 1}</field>
</record>
</odoo>
+2 -2
View File
@@ -958,7 +958,7 @@
<field name="arch" type="xml">
<button name="toggle_active" position="before">
<button class="oe_stat_button" name="action_view_sales"
type="object" icon="fa-signal" groups="sales_team.group_sale_salesman" help="Sold in the last 365 days">
type="object" icon="fa-signal" groups="sales_team.group_sale_salesman" help="Sold in the last 365 days" attrs="{'invisible': [('sale_ok', '=', False)]}">
<div class="o_field_widget o_stat_info">
<span class="o_stat_value">
<field name="sales_count" widget="statinfo" nolabel="1" class="mr4"/>
@@ -986,7 +986,7 @@
<field name="arch" type="xml">
<button name="toggle_active" position="before">
<button class="oe_stat_button" name="action_view_sales"
type="object" icon="fa-signal" groups="sales_team.group_sale_salesman" help="Sold in the last 365 days">
type="object" icon="fa-signal" groups="sales_team.group_sale_salesman" help="Sold in the last 365 days" attrs="{'invisible': [('sale_ok', '=', False)]}">
<div class="o_field_widget o_stat_info">
<span class="o_stat_value">
<field name="sales_count" widget="statinfo" nolabel="1" class="mr4"/>
+1 -1
View File
@@ -344,7 +344,7 @@
<!-- change attrs of fields added in view_template_property_form
to restrict the display for templates -->
<xpath expr="//group[@name='group_lots_and_weight']" position="attributes">
<attribute name="attrs">{'invisible':['|', ('type', 'not in', ['product', 'consu']), ('product_variant_count', '&gt;', 1)]}</attribute>
<attribute name="attrs">{'invisible':['|', ('type', 'not in', ['product', 'consu'])]}</attribute>
</xpath>
<xpath expr="//group[@name='group_lots_and_weight']" position="inside">
+8 -8
View File
@@ -40,12 +40,12 @@
<field name="standard_price"
attrs="{'readonly':[('valuation','=','real_time')]}"
widget='monetary' options="{'currency_field': 'currency_id', 'field_digits': True}"
class="float-left"/>
<div name="update_cost_price" class="col-lg-2">
class="float-left oe_inline"/>
<div name="update_cost_price">
<button string="Update Cost" type="action"
name="%(action_view_change_standard_price)d"
attrs="{'invisible':['|', '|', ('valuation','!=', 'real_time'), ('cost_method', 'not in', ['average', 'standard']), ('product_variant_count', '>', 1)]}"
class="oe_link oe_read_only"/>
name="%(action_view_change_standard_price)d"
attrs="{'invisible':['|', '|', ('valuation','!=', 'real_time'), ('cost_method', 'not in', ['average', 'standard']), ('product_variant_count', '>', 1)]}"
class="oe_link pt-0 float-left oe_inline"/>
</div>
</field>
</data>
@@ -64,15 +64,15 @@
</field>
<field name="standard_price" position="replace">
<label for="standard_price"/>
<div name="standard_price_div">
<div name="standard_price_div" class="row ml-0">
<field name="standard_price"
attrs="{'readonly':[('valuation','=','real_time')]}"
widget='monetary' options="{'currency_field': 'currency_id', 'field_digits': True}" class="float-left"/>
<div name="update_cost_price" class="col-lg-2">
<div name="update_cost_price">
<button string="Update Cost" type="action"
name="%(action_view_change_standard_price)d"
attrs="{'invisible':['|',('valuation','!=', 'real_time'), ('cost_method', 'not in', ['standard', 'average'])]}"
class="oe_link oe_read_only" colspan="2"/>
class="oe_link pt-0 float-left"/>
</div>
</div>
</field>