[MERGE] base: Improve multi-company UX
TaskID: 2000277 closes odoo/odoo#33876 Signed-off-by: Yannick Tivisse (yti) <yti@odoo.com>
This commit is contained in:
@@ -8,8 +8,6 @@ class ResConfigSettings(models.TransientModel):
|
||||
|
||||
_inherit = 'res.config.settings'
|
||||
|
||||
group_multi_company = fields.Boolean("Manage multiple companies", implied_group='base.group_multi_company')
|
||||
group_toggle_company = fields.Boolean("Toggle multiple companies", implied_group='base.group_toggle_company')
|
||||
company_id = fields.Many2one('res.company', string='Company', required=True,
|
||||
default=lambda self: self.env.company)
|
||||
user_default_rights = fields.Boolean(
|
||||
|
||||
@@ -117,20 +117,17 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="multi_company">
|
||||
<div id="multi_company" groups="base.group_multi_company">
|
||||
<field name="company_id" invisible="1"/>
|
||||
<h2>Multi-companies</h2>
|
||||
<div class="row mt16 o_settings_container" name="multi_company">
|
||||
<div class="col-12 col-lg-6 o_setting_box">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="group_multi_company"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label string="Multi-companies" for="group_multi_company"/>
|
||||
<label string="Multi-companies" for="multi_company"/>
|
||||
<div class="text-muted">
|
||||
Manage multiple legal entities with separate accounting
|
||||
</div>
|
||||
<div class="content-group" attrs="{'invisible': [('group_multi_company','=',False)]}">
|
||||
<div class="content-group">
|
||||
<div class="mt16">
|
||||
<button name="%(base.action_res_company_form)d" icon="fa-arrow-right" type="action" string="Companies" class="btn-link"/>
|
||||
</div>
|
||||
@@ -141,19 +138,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-lg-6 o_setting_box">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="group_toggle_company"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label string="Multi-companies by Tab" for="group_toggle_company"/>
|
||||
<div class="text-muted">
|
||||
Manage multiple companies on the same browser tab. Be careful that this advanced tool should
|
||||
only be used for reporting purpose.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-lg-6 o_setting_box" title="Configure company rules to automatically create SO/PO when one of your company sells/buys to another of your company." attrs="{'invisible': [('group_multi_company', '=', False)]}" id="inter_company">
|
||||
<div class="col-12 col-lg-6 o_setting_box" title="Configure company rules to automatically create SO/PO when one of your company sells/buys to another of your company." id="inter_company">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="module_inter_company_rules" widget="upgrade_boolean"/>
|
||||
</div>
|
||||
|
||||
@@ -85,18 +85,13 @@ class MailController(http.Controller):
|
||||
# - Guess the supposed necessary company to access the record via the method
|
||||
# _get_mail_redirect_suggested_company
|
||||
# - If no company, then redirect to the messaging
|
||||
# - If the multi company per tag group is activated, merge the suggested company
|
||||
# withe the companies on the cookie
|
||||
# - else, use this company as enabled company
|
||||
# - Merge the suggested company with the companies on the cookie
|
||||
# - Make a new access test if it succeeds, redirect to the record. Otherwise,
|
||||
# redirect to the messaging.
|
||||
suggested_company = record_sudo._get_mail_redirect_suggested_company()
|
||||
if not suggested_company:
|
||||
raise AccessError()
|
||||
if user.has_group('base.group_toggle_company'):
|
||||
cids += [suggested_company.id]
|
||||
else:
|
||||
cids = [suggested_company.id]
|
||||
cids += [suggested_company.id]
|
||||
record_sudo.sudo(uid).with_context(allowed_company_ids=cids).check_access_rule('read')
|
||||
except AccessError:
|
||||
return cls._redirect_to_messaging()
|
||||
|
||||
@@ -164,6 +164,10 @@
|
||||
<field name="user_ids" eval="[(4, ref('base.user_admin')), (4, ref('base.user_demo'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="base.group_multi_company" model="res.groups">
|
||||
<field name="users" eval="[(4, ref('base.user_admin')), (4, ref('base.user_demo'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="base.main_company" model="res.company">
|
||||
<field name="name">My Company (San Francisco)</field>
|
||||
</record>
|
||||
|
||||
@@ -56,7 +56,6 @@ class Http(models.AbstractModel):
|
||||
"web.base.url": self.env['ir.config_parameter'].sudo().get_param('web.base.url', default=''),
|
||||
"show_effect": True,
|
||||
"display_switch_company_menu": user.has_group('base.group_multi_company') and len(user.company_ids) > 1,
|
||||
"toggle_company": user.has_group('base.group_toggle_company'),
|
||||
"cache_hashes": {
|
||||
"load_menus": hashlib.sha1(menu_json_utf8).hexdigest(),
|
||||
"qweb": qweb_checksum,
|
||||
|
||||
@@ -31,7 +31,6 @@ var SwitchCompanyMenu = Widget.extend({
|
||||
this._onSwitchCompanyClick = _.debounce(this._onSwitchCompanyClick, 1500, true);
|
||||
this.allowed_company_ids = String(session.user_context.allowed_company_ids).split(',');
|
||||
this.user_companies = session.user_companies.allowed_companies;
|
||||
this.toggle_company = session.toggle_company;
|
||||
|
||||
var hash = $.bbq.getState()
|
||||
if (!hash.cids || hash.cids === undefined) {
|
||||
@@ -52,16 +51,21 @@ var SwitchCompanyMenu = Widget.extend({
|
||||
* @param {MouseEvent} ev
|
||||
*/
|
||||
_onSwitchCompanyClick: function (ev) {
|
||||
ev.preventDefault();
|
||||
var companyID = $(ev.currentTarget).parent().data('company-id');
|
||||
ev.stopPropagation();
|
||||
var dropdownItem = $(ev.currentTarget).parent()
|
||||
var dropdownMenu = dropdownItem.parent()
|
||||
var companyID = dropdownItem.data('company-id');
|
||||
var hash = $.bbq.getState()
|
||||
var allowed_company_ids = _.map(hash.cids.split(','), function(company_id) {return parseInt(company_id);});
|
||||
if ($($(ev.currentTarget).parent()).find('.fa-square-o').length) {
|
||||
if (dropdownItem.find('.fa-square-o').length) {
|
||||
// 1 enabled company: Stay in single company mode
|
||||
if (this.allowed_company_ids.length === 1) {
|
||||
allowed_company_ids = [companyID]
|
||||
dropdownMenu.find('.fa-check-square').removeClass('fa-check-square').addClass('fa-square-o');
|
||||
dropdownItem.find('.fa-square-o').removeClass('fa-square-o').addClass('fa-check-square');
|
||||
allowed_company_ids = [companyID]
|
||||
} else { // Multi company mode
|
||||
allowed_company_ids.push(companyID);
|
||||
dropdownItem.find('.fa-square-o').removeClass('fa-square-o').addClass('fa-check-square');
|
||||
}
|
||||
}
|
||||
session.setCompanies(companyID, allowed_company_ids);
|
||||
@@ -76,14 +80,19 @@ var SwitchCompanyMenu = Widget.extend({
|
||||
* @param {MouseEvent} ev
|
||||
*/
|
||||
_onToggleCompanyClick: function (ev) {
|
||||
var companyID = $(ev.currentTarget).parent().data('company-id');
|
||||
ev.stopPropagation();
|
||||
var dropdownItem = $(ev.currentTarget).parent()
|
||||
var dropdownMenu = dropdownItem.parent()
|
||||
var companyID = dropdownItem.data('company-id');
|
||||
var hash = $.bbq.getState()
|
||||
var allowed_company_ids = _.map(hash.cids.split(','), function(company_id) {return parseInt(company_id);});
|
||||
var current_company_id = allowed_company_ids[0];
|
||||
if ($(ev.currentTarget).find('.fa-square-o').length) {
|
||||
if (dropdownItem.find('.fa-square-o').length) {
|
||||
allowed_company_ids.push(companyID);
|
||||
dropdownItem.find('.fa-square-o').removeClass('fa-square-o').addClass('fa-check-square');
|
||||
} else {
|
||||
allowed_company_ids.splice(allowed_company_ids.indexOf(companyID), 1);
|
||||
dropdownItem.find('.fa-check-square').addClass('fa-square-o').removeClass('fa-check-square');
|
||||
}
|
||||
session.setCompanies(current_company_id, allowed_company_ids);
|
||||
},
|
||||
|
||||
@@ -1570,6 +1570,16 @@
|
||||
</t>
|
||||
<t t-foreach="widget.user_companies" t-as="company">
|
||||
<div role="menuitem" href="#" class="dropdown-item d-flex py-0 px-0" data-menu="company" t-att-data-company-id="company[0]">
|
||||
<div class="ml-auto pl-3 pr-3 border border-top-0 border-left-0 border-bottom-0 toggle_company o_py">
|
||||
<span style="height: 2rem;">
|
||||
<t t-if="widget.allowed_company_ids.includes(company[0].toString())">
|
||||
<i class="fa fa-fw fa-check-square pt-2"></i>
|
||||
</t>
|
||||
<t t-if="!widget.allowed_company_ids.includes(company[0].toString())">
|
||||
<i class="fa fa-fw fa-square-o pt-2"></i>
|
||||
</t>
|
||||
</span>
|
||||
</div>
|
||||
<div class="d-flex flex-grow-1 align-items-center py-0 log_into pl-3 o_py" t-att-style="company[0] === widget.current_company ? 'background-color: lightgrey;' : ''">
|
||||
<t t-if="widget.allowed_company_ids.includes(company[0].toString())">
|
||||
<span class='mr-3 company_label'>
|
||||
@@ -1582,18 +1592,6 @@
|
||||
</span>
|
||||
</t>
|
||||
</div>
|
||||
<t t-if="widget.toggle_company">
|
||||
<div class="ml-auto pl-3 pr-3 border border-top-0 border-right-0 border-bottom-0 toggle_company o_py">
|
||||
<span style="height: 2rem;">
|
||||
<t t-if="widget.allowed_company_ids.includes(company[0].toString())">
|
||||
<i class="fa fa-fw fa-check-square pt-2"></i>
|
||||
</t>
|
||||
<t t-if="!widget.allowed_company_ids.includes(company[0].toString())">
|
||||
<i class="fa fa-fw fa-square-o pt-2"></i>
|
||||
</t>
|
||||
</span>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
|
||||
@@ -80,7 +80,6 @@ The kernel of Odoo, needed for all installation.
|
||||
'data/res_bank_demo.xml',
|
||||
'data/res_partner_demo.xml',
|
||||
'data/res_partner_image_demo.xml',
|
||||
'data/res_groups_demo.xml',
|
||||
],
|
||||
'test': [],
|
||||
'installable': True,
|
||||
|
||||
@@ -110,9 +110,5 @@
|
||||
<field name="category_id" ref="module_category_usability"/>
|
||||
</record>
|
||||
|
||||
<record id="group_toggle_company" model="res.groups">
|
||||
<field name="category_id" ref="module_category_hidden"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<record id="group_toggle_company" model="res.groups">
|
||||
<field name="users" eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"/>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
@@ -43,20 +43,23 @@ class Company(models.Model):
|
||||
with tools.file_open(img_path, 'rb') as f:
|
||||
if original:
|
||||
return base64.b64encode(f.read())
|
||||
# Modify the source image to change the color of the 'O'.
|
||||
# Modify the source image to add a colored bar on the bottom
|
||||
# This could seem overkill to modify the pixels 1 by 1, but
|
||||
# Pillow doesn't provide an easy way to do it, and this
|
||||
# is acceptable for a 16x16 image.
|
||||
color = (randrange(32, 224, 24), randrange(32, 224, 24), randrange(32, 224, 24))
|
||||
original = Image.open(f)
|
||||
new_image = Image.new('RGBA', original.size)
|
||||
for y in range(original.size[1]):
|
||||
for x in range(original.size[0]):
|
||||
height = original.size[1]
|
||||
width = original.size[0]
|
||||
bar_size = 1
|
||||
for y in range(height):
|
||||
for x in range(width):
|
||||
pixel = original.getpixel((x, y))
|
||||
if pixel[0] == 0 and pixel[1] == 0 and pixel[2] == 0:
|
||||
new_image.putpixel((x, y), (0, 0, 0, 0))
|
||||
if height - bar_size <= y + 1 <= height:
|
||||
new_image.putpixel((x, y), (color[0], color[1], color[2], 255))
|
||||
else:
|
||||
new_image.putpixel((x, y), (color[0], color[1], color[2], pixel[3]))
|
||||
new_image.putpixel((x, y), (pixel[0], pixel[1], pixel[2], pixel[3]))
|
||||
stream = io.BytesIO()
|
||||
new_image.save(stream, format="ICO")
|
||||
return base64.b64encode(stream.getvalue())
|
||||
|
||||
@@ -41,10 +41,6 @@
|
||||
<field name="users" eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="group_toggle_company" model="res.groups">
|
||||
<field name="name">Allow to toggle company visibility in the company switch bar</field>
|
||||
</record>
|
||||
|
||||
<record model="res.groups" id="group_partner_manager">
|
||||
<field name="name">Contact Creation</field>
|
||||
<field name="users" eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"/>
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
<field name="currency_id" options="{'no_create': True, 'no_open': True}" id="company_currency" context="{'active_test': False}"/>
|
||||
<field name="parent_id" groups="base.group_multi_company"/>
|
||||
<field name="sequence" invisible="1"/>
|
||||
<field name="favicon" widget="image" class="float-left oe_avatar"/>
|
||||
<field name="favicon" widget="image" class="float-left oe_avatar" groups="base.group_no_one"/>
|
||||
</group>
|
||||
<group name="social_media"/>
|
||||
</group>
|
||||
|
||||
Reference in New Issue
Block a user