[MERGE] base/res_config: Clean model and behavior of configuration forms

Purpose:
========

The res.config.settings are quite a mess. The API is not well know and the general usage in the common modules is bad.

Specifications
==============

Clean use of ir.values in models
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- clean use of ir.values -> those should be only real default values for existing fields in other models.
- Use ir.config_parameter or something else if conversion is required

reset values when option is disabled
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

propagate checkboxes in settings. Ex: "use <my feature> opens <feature_value> configuration". Code should handle both <my_feature> and <feature_value>. Unactivating a feature should disable it really.

SALES
default terms & conditions
WEBSITE
Google Analytics
Google Analytics in dashboard
INVENTORY
Security Lead Time for Sales -> reset to 0
Security Lead Time for Purchase -> reset to 0
No Rescheduling Propagation -> reset to 1
MANUFACTURING
Security Lead Time -> reset to 0

clean alias congiguration
~~~~~~~~~~~~~~~~~~~~~~~~~

crm, project: remove unnecessary and unused generate_sales_team/project_alias, conf is done on sales team / project
crm: generate_lead_from_alias cleaned
hr_expense: correctly take into account "Use Mailgateway" settings, reset alias if not set

pos: mutli sales price settings cleaned
sales: multi sales price settings cleaned, default deposit product cleaned
website: has_google_analytics, has_google_analytics_dashboard, has_google_maps settings cleaned
website_sale: multi sales prices settings cleaned
print: default_provider_id

Ease google analytic settings
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

it's hard to get all the google analytics working. Setup steps are still confusing. And if you set up analytics API first (before creating an account), you get a traceback in the dashboard...

review google analytics id wizard
    - How to get my Tracking ID
    - How to get my API Client ID
    - open those links in new tabs

make sure any traceback pops up if the user enter a client ID without a Tracking ID. It is the case for now. One way is to block the
user with a warning: Please enter your Tracking ID.

as soon as an ID is set, activate related features and populate fields in website settings + some changes in labels

only display Google Analytics in Dashboard in website settings if Google Analytics is checked
+ blocking warning if the user enters a Client ID without any Tracking ID

Reorganise files according to the guidelines
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Declare models in camel case, place python files in models, xml views in views...

Remove some useless/unused code
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Some chunck of code are never called or are useless.

Clean ir.actions.todo models
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Remove some useless fields:
- type: Historically we used ir.actions.todo to make complex things. Now we only use them to redirect to a specific action when a module is installed. All our ir.actions.todo type is `automatic`
- Note: Useless
- Group_id: All our ir.actions.todo are launched by the administrator. No need to specify groups on it.

Prevent to be redirected everywhere on update
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Prevent to have more than one open ir.actions.todo. This avoid this use case:
- Install ecommerce, be redirect to the theme selection
- Install note, be redirected to /shop.

We just take the last defined ir.actions.todo into account.

Stay on a config setting form by pressing apply
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

If we click on Apply, we want to stay on the config page to see the new fields coming from the module you just installed

Keep the current behavior when installing a module from the App menuitem, which is either jumping to the app switcher or jumping to a specific action if defined on this module

Clean default method to get/set the values on a config form
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Currently there are 4 types on fields on res_config:
- `default_`: These fields should use ir.values and they have been cleaned in a previous section of this commit message
- `group_`: They define security groups
- `module_`: They allow to install/uninstall modules
- Other fields: They are the other fields that are implemented in a quite messy way.

Currently all the methods beginning by `get_default` are used to fetch their default values, usually by looking in the ir.config_parameter table.
Currently all the methods beginning by `set_` are used to set their values, usually in the ir.config_parameter table.

This section purpose is to replace all the occurences of `get_default_foo` and `set_foo`. As these methods won't be called anymore, a warning is logged to notice its deprecation. They are replaced by the generic methods `get_values` and `set_values` that should be overridden to define the behavior of the added fields.

Add a test on res_config on page loading and saving
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Try to create and execute all res_config models. Target settings that can't be loaded or saved and avoid remaining methods get_default_foo` or `set_foo` that won't be executed.
This commit is contained in:
Yannick Tivisse
2017-06-19 17:38:19 +02:00
165 changed files with 807 additions and 745 deletions
+1 -1
View File
@@ -56,7 +56,7 @@ Core mechanisms for the accounting modules. To display the menuitems, install th
'views/report_agedpartnerbalance.xml',
'views/tax_adjustments.xml',
'wizard/wizard_tax_adjustments_view.xml',
'views/res_config_view.xml',
'views/account_config_settings_views.xml',
'views/web_planner_data.xml',
'views/account_journal_dashboard_view.xml',
'report/account_report_payment_receipt_templates.xml',
+1 -1
View File
@@ -11,5 +11,5 @@ from . import account_analytic_line
from . import account_journal_dashboard
from . import product
from . import company
from . import res_config
from . import account_config_settings
from . import web_planner
@@ -60,34 +60,28 @@ class AccountConfigSettings(models.TransientModel):
module_l10n_eu_service = fields.Boolean(string="EU Digital Goods VAT")
@api.model
def get_default_tax_fields(self, fields):
default_purchase_tax_id = self.env['ir.config_parameter'].sudo().get_param('account.default_purchase_tax_id', default=False)
default_sale_tax_id = self.env['ir.config_parameter'].sudo().get_param('account.default_sale_tax_id', default=False)
return dict(default_purchase_tax_id=int(default_purchase_tax_id), default_sale_tax_id=int(default_sale_tax_id))
def get_values(self):
res = super(AccountConfigSettings, self).get_values()
params = self.env['ir.config_parameter'].sudo()
res.update(
default_purchase_tax_id=params.get_param('account.default_purchase_tax_id', default=False),
default_sale_tax_id=params.get_param('account.default_sale_tax_id', default=False)
)
return res
@api.multi
def set_default_tax_fields(self):
def set_values(self):
super(AccountConfigSettings, self).set_values()
self.env['ir.config_parameter'].sudo().set_param("account.default_purchase_tax_id", self.default_purchase_tax_id.id)
self.env['ir.config_parameter'].sudo().set_param("account.default_sale_tax_id", self.default_sale_tax_id.id)
@api.depends('company_id')
def _compute_has_chart_of_accounts(self):
self.has_chart_of_accounts = bool(self.company_id.chart_template_id)
def set_group_multi_currency(self):
if self.group_multi_currency:
self.env.ref('base.group_user').write({'implied_ids': [(4, self.env.ref('product.group_sale_pricelist').id)]})
return True
def set_default_product_taxes(self):
""" Set the product taxes if they have changed """
ir_values_obj = self.env['ir.values']
if self.default_sale_tax_id:
ir_values_obj.sudo().set_default('product.template', "taxes_id", [self.default_sale_tax_id.id], for_all_users=True, company_id=self.company_id.id)
if self.default_purchase_tax_id:
ir_values_obj.sudo().set_default('product.template', "supplier_taxes_id", [self.default_purchase_tax_id.id], for_all_users=True, company_id=self.company_id.id)
def set_chart_of_accounts(self):
""" install a chart of accounts for the given company (if required) """
if self.chart_template_id and not self.has_chart_of_accounts and self.company_id.expects_chart_of_accounts:
if self.company_id.chart_template_id and self.chart_template_id != self.company_id.chart_template_id:
@@ -108,6 +102,10 @@ class AccountConfigSettings(models.TransientModel):
})
wizard.execute()
@api.depends('company_id')
def _compute_has_chart_of_accounts(self):
self.has_chart_of_accounts = bool(self.company_id.chart_template_id)
@api.onchange('group_analytic_accounting')
def onchange_analytic_accounting(self):
if self.group_analytic_accounting:
+1 -1
View File
@@ -147,7 +147,7 @@ class AccountChartTemplate(models.Model):
todo = self.env['ir.actions.todo']
action_rec = self.env['ir.model.data'].xmlid_to_object('account.action_wizard_multi_chart')
if action_rec:
todo.create({'action_id': action_rec.id, 'name': _('Choose Accounting Template'), 'type': 'automatic'})
todo.create({'action_id': action_rec.id, 'name': _('Choose Accounting Template')})
return True
@api.model
+1 -1
View File
@@ -19,7 +19,7 @@ It assigns manager and user access rights to the Administrator for the accountin
'data/account_accountant_data.xml',
'security/account_accountant_security.xml',
'views/account_accountant_templates.xml',
'views/res_config_view.xml',
'views/account_config_settings_views.xml',
'views/product_views.xml',
],
'demo': ['data/account_accountant_demo.xml'],
+1 -1
View File
@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import res_config
from . import account_config_settings
@@ -24,7 +24,7 @@ Allows to automatically select analytic accounts based on criterions:
'security/account_analytic_default_security.xml',
'views/account_analytic_default_view.xml',
'views/product_views.xml',
'views/res_config_view.xml',
'views/account_config_settings_views.xml',
],
'installable': True,
}
+1 -1
View File
@@ -26,7 +26,7 @@ Keeps track of depreciations, and creates corresponding journal entries.
'views/account_invoice_views.xml',
'views/account_asset_templates.xml',
'views/product_views.xml',
'views/res_config_view.xml',
'views/account_config_settings_views.xml',
'report/account_asset_report_views.xml',
'data/account_asset_data.xml',
],
+1 -1
View File
@@ -34,7 +34,7 @@ Three reports are available:
'security/account_budget_security.xml',
'views/account_analytic_account_views.xml',
'views/account_budget_views.xml',
'views/res_config_view.xml',
'views/account_config_settings_views.xml',
],
'demo': ['data/account_budget_demo.xml'],
}
+1 -1
View File
@@ -15,7 +15,7 @@ Allow users to login through OAuth2 Provider.
'data/auth_oauth_data.yml',
'views/auth_oauth_views.xml',
'views/res_users_views.xml',
'views/res_config_views.xml',
'views/base_config_settings_views.xml',
'views/auth_oauth_templates.xml',
'security/ir.model.access.csv',
],
+1 -1
View File
@@ -2,6 +2,6 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import auth_oauth
from . import base_config_settings
from . import ir_config_parameter
from . import res_config
from . import res_users
@@ -15,36 +15,25 @@ class BaseConfigSettings(models.TransientModel):
def get_uri(self):
return "%s/auth_oauth/signin" % (self.env['ir.config_parameter'].get_param('web.base.url'))
def _compute_server_uri(self):
uri = self.get_uri()
for setting in self:
setting.server_uri_google = uri
auth_oauth_google_enabled = fields.Boolean(string='Allow users to sign in with Google')
auth_oauth_google_client_id = fields.Char(string='Client ID')
server_uri_google = fields.Char(compute='_compute_server_uri', string='Server uri')
server_uri_google = fields.Char(string='Server uri')
@api.model
def default_get(self, fields):
settings = super(BaseConfigSettings, self).default_get(fields)
settings.update(self.get_oauth_providers(fields))
return settings
@api.model
def get_oauth_providers(self, fields):
def get_values(self):
res = super(BaseConfigSettings, self).get_values()
google_provider = self.env.ref('auth_oauth.provider_google', False)
return {
'auth_oauth_google_enabled': google_provider.enabled,
'auth_oauth_google_client_id': google_provider.client_id,
'server_uri_google': self.get_uri()
}
res.update(
auth_oauth_google_enabled=google_provider.enabled,
auth_oauth_google_client_id=google_provider.client_id,
server_uri_google=self.get_uri(),
)
return res
@api.multi
def set_oauth_providers(self):
self.ensure_one()
def set_values(self):
super(BaseConfigSettings, self).set_values()
google_provider = self.env.ref('auth_oauth.provider_google', False)
rg = {
google_provider.write({
'enabled': self.auth_oauth_google_enabled,
'client_id': self.auth_oauth_google_client_id,
}
google_provider.write(rg)
})
+1 -1
View File
@@ -17,7 +17,7 @@ Allow users to sign up and reset their password
],
'data': [
'data/auth_signup_data.xml',
'views/res_config_views.xml',
'views/base_config_settings_views.xml',
'views/res_users_views.xml',
'views/auth_signup_login_templates.xml',
],
+2 -2
View File
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
from . import res_config
from . import res_users
from . import base_config_settings
from . import res_partner
from . import res_users
@@ -12,18 +12,21 @@ class BaseConfigSettings(models.TransientModel):
auth_signup_template_user_id = fields.Many2one('res.users', string='Template user for new users created through signup')
@api.model
def get_default_auth_signup_template_user_id(self, fields):
get_param = self.env['ir.config_parameter'].get_param
def get_values(self):
res = super(BaseConfigSettings, self).get_values()
get_param = self.env['ir.config_parameter'].sudo().get_param
# we use safe_eval on the result, since the value of the parameter is a nonempty string
return {
'auth_signup_reset_password': safe_eval(get_param('auth_signup.reset_password', 'False')),
'auth_signup_uninvited': safe_eval(get_param('auth_signup.allow_uninvited', 'False')),
'auth_signup_template_user_id': safe_eval(get_param('auth_signup.template_user_id', 'False')),
}
res.update(
auth_signup_reset_password=safe_eval(get_param('auth_signup.reset_password', 'False')),
auth_signup_uninvited=safe_eval(get_param('auth_signup.allow_uninvited', 'False')),
auth_signup_template_user_id=safe_eval(get_param('auth_signup.template_user_id', 'False')),
)
return res
@api.multi
def set_auth_signup_template_user_id(self):
self.ensure_one()
set_param = self.env['ir.config_parameter'].set_param
def set_values(self):
super(BaseConfigSettings, self).set_values()
set_param = self.env['ir.config_parameter'].sudo().set_param
# we store the repr of the values, since the value of the parameter is a required string
set_param('auth_signup.reset_password', repr(self.auth_signup_reset_password))
set_param('auth_signup.allow_uninvited', repr(self.auth_signup_uninvited))
+1 -1
View File
@@ -18,7 +18,7 @@ This wizard will activate the CRON job and the Scheduler and will start the auto
'data': [
'data/ir_cron_data.xml',
'views/ir_translation_views.xml',
'views/res_config_views.xml',
'views/base_config_settings_views.xml',
'wizard/base_gengo_translations_view.xml',
],
'demo': ['data/res_company_demo.xml'],
+1 -1
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import base_config_settings
from . import ir_translation
from . import res_company
from . import res_config
+1 -1
View File
@@ -13,7 +13,7 @@ Shows you a list of applications features to install from.
""",
'depends': ['base', 'web'],
'data': [
'views/res_config_views.xml',
'views/base_config_settings_views.xml',
'views/res_partner_views.xml',
],
'demo': [],
+1 -1
View File
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import res_config
from . import base_config_settings
@@ -37,21 +37,27 @@ class BaseConfigSettings(models.TransientModel):
external_report_layout = fields.Selection(related="company_id.external_report_layout")
@api.model
def get_default_fields(self, fields):
default_external_email_server = self.env['ir.config_parameter'].sudo().get_param('base_setup.default_external_email_server', default=False)
default_user_rights = self.env['ir.config_parameter'].sudo().get_param('base_setup.default_user_rights', default=False)
default_custom_report_footer = self.env['ir.config_parameter'].sudo().get_param('base_setup.default_custom_report_footer', default=False)
return {
'default_external_email_server': default_external_email_server,
'default_user_rights': default_user_rights,
'default_custom_report_footer': default_custom_report_footer,
}
def get_values(self):
res = super(BaseConfigSettings, self).get_values()
params = self.env['ir.config_parameter'].sudo()
default_external_email_server = params.get_param('base_setup.default_external_email_server', default=False)
default_user_rights = params.get_param('base_setup.default_user_rights', default=False)
default_custom_report_footer = params.get_param('base_setup.default_custom_report_footer', default=False)
res.update(
default_external_email_server=default_external_email_server,
default_user_rights=default_user_rights,
default_custom_report_footer=default_custom_report_footer,
company_share_partner=not self.env.ref('base.res_partner_rule').active,
)
return res
@api.multi
def set_default_fields(self):
def set_values(self):
super(BaseConfigSettings, self).set_values()
self.env['ir.config_parameter'].sudo().set_param("base_setup.default_external_email_server", self.default_external_email_server)
self.env['ir.config_parameter'].sudo().set_param("base_setup.default_user_rights", self.default_user_rights)
self.env['ir.config_parameter'].sudo().set_param("base_setup.default_custom_report_footer", self.default_custom_report_footer)
self.env.ref('base.res_partner_rule').write({'active': not self.company_share_partner})
@api.multi
def open_company(self):
@@ -71,18 +77,6 @@ class BaseConfigSettings(models.TransientModel):
action['views'] = [[self.env.ref('base.view_users_form').id, 'form']]
return action
@api.model
def get_default_company_share_partner(self, fields):
return {
'company_share_partner': not self.env.ref('base.res_partner_rule').active
}
@api.multi
def set_default_company_share_partner(self):
partner_rule = self.env.ref('base.res_partner_rule')
for config in self:
partner_rule.write({'active': not config.company_share_partner})
@api.model
def _prepare_report_view_action(self, template):
template_id = self.env.ref(template)
+1 -1
View File
@@ -39,6 +39,6 @@ only the country code will be validated.
'data': [
'views/res_partner_views.xml',
'views/res_company_views.xml',
'views/res_config_view.xml',
'views/account_config_settings_views.xml',
],
}
+1 -1
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import account_config_settings
from . import res_company
from . import res_partner
from . import res_config
+1 -2
View File
@@ -45,7 +45,6 @@ Dashboard for CRM will include:
'data/crm_data.xml',
'data/crm_stage_data.xml',
'data/sales_config_settings_data.xml',
'data/crm_lead_data.xml',
'data/web_planner_data.xml',
'data/mail_template_data.xml',
@@ -65,7 +64,7 @@ Dashboard for CRM will include:
'views/crm_lead_views.xml',
'views/calendar_views.xml',
'views/res_partner_views.xml',
'views/res_config_views.xml',
'views/sale_config_settings_views.xml',
'views/crm_team_views.xml',
],
'demo': [
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate='1'>
<function id="default_generate_sales_team_alias"
model="ir.values" name="set_default"
eval="('sale.config.settings', 'generate_sales_team_alias', True)"/>
</data>
</odoo>
+1 -1
View File
@@ -6,6 +6,6 @@ from . import calendar
from . import crm_lead
from . import crm_stage
from . import crm_team
from . import res_config
from . import sale_config_settings
from . import res_partner
from . import web_planner
-7
View File
@@ -120,13 +120,6 @@ class Team(models.Model):
if not self.use_opportunities and self.dashboard_graph_model == 'crm.opportunity.report':
raise ValidationError(_("Dashboard graph content cannot be Pipeline if the sales channel doesn't use it. (Pipeline is unchecked.)"))
@api.model
def create(self, vals):
generate_alias_name = self.env['ir.values'].get_default('sale.config.settings', 'generate_sales_team_alias')
if generate_alias_name and not vals.get('alias_name'):
vals['alias_name'] = vals.get('name')
return super(Team, self).create(vals)
@api.multi
def write(self, vals):
result = super(Team, self).write(vals)
-82
View File
@@ -1,82 +0,0 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models
class CRMSettings(models.TransientModel):
_inherit = 'sale.config.settings'
generate_sales_team_alias = fields.Boolean("Automatically generate an email alias at the sales channel creation",
help="Odoo will generate an email alias based on the sales channel name")
alias_prefix = fields.Char('Default Alias Name for Leads')
alias_domain = fields.Char('Alias Domain', default=lambda self: self.env["ir.config_parameter"].sudo().get_param("mail.catchall.domain"))
# TDE TODO: as it is not linked to ir.values anymore, it should be renamed, but not in stable
default_generate_lead_from_alias = fields.Boolean('Manual Assignation of Emails')
group_use_lead = fields.Boolean(string="Leads", implied_group='crm.group_use_lead')
module_crm_phone_validation = fields.Boolean("Phone Validation")
module_crm_voip = fields.Boolean("Asterisk (VoIP)")
def _find_default_lead_alias_id(self):
alias = self.env.ref('crm.mail_alias_lead_info', False)
if not alias:
alias = self.env['mail.alias'].search([
('alias_model_id.model', '=', 'crm.lead'),
('alias_force_thread_id', '=', False),
('alias_parent_model_id.model', '=', 'crm.team'),
('alias_parent_thread_id', '=', False),
('alias_defaults', '=', '{}')
], limit=1)
return alias
@api.model
def get_default_generate_sales_team_alias(self, fields):
return {
'generate_sales_team_alias': self.env['ir.values'].get_default('sale.config.settings', 'generate_sales_team_alias')
}
@api.multi
def set_default_generate_sales_team_alias(self):
IrValues = self.env['ir.values']
if self.env['res.users'].has_group('base.group_erp_manager'):
IrValues = IrValues.sudo()
IrValues.set_default('sale.config.settings', 'generate_sales_team_alias', self.generate_sales_team_alias)
@api.model
def get_default_default_generate_lead_from_alias(self, fields):
return {
'default_generate_lead_from_alias': self.env['ir.config_parameter'].sudo().get_param('sale_config_settings.default_generate_lead_from_alias')
}
@api.multi
def set_default_default_generate_lead_from_alias(self):
self.env['ir.config_parameter'].sudo().set_param('sale_config_settings.default_generate_lead_from_alias', self.default_generate_lead_from_alias)
@api.onchange('group_use_lead')
def _onchange_group_use_lead(self):
""" Reset alias / leads configuration if leads are not used """
if not self.group_use_lead:
self.default_generate_lead_from_alias = False
@api.onchange('default_generate_lead_from_alias')
def _onchange_default_generate_lead_from_alias(self):
if self.default_generate_lead_from_alias:
self.alias_prefix = self.alias_prefix or 'info'
else:
self.alias_prefix = False
@api.model
def get_default_alias_prefix(self, fields):
alias = self._find_default_lead_alias_id()
return {'alias_prefix': alias.alias_name if alias else False}
@api.multi
def set_default_alias_prefix(self):
for record in self:
alias = self._find_default_lead_alias_id()
if alias:
alias.write({'alias_name': record.alias_prefix})
else:
self.env['mail.alias'].with_context(alias_model_name='crm.lead', alias_parent_model_name='crm.team').create({'alias_name': record.alias_prefix})
return True
+59
View File
@@ -0,0 +1,59 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models
class SaleConfigSettings(models.TransientModel):
_inherit = 'sale.config.settings'
alias_prefix = fields.Char('Default Alias Name for Leads')
alias_domain = fields.Char('Alias Domain', default=lambda self: self.env["ir.config_parameter"].sudo().get_param("mail.catchall.domain"))
generate_lead_from_alias = fields.Boolean('Manual Assignation of Emails')
group_use_lead = fields.Boolean(string="Leads", implied_group='crm.group_use_lead')
module_crm_phone_validation = fields.Boolean("Phone Validation")
module_crm_voip = fields.Boolean("Asterisk (VoIP)")
def _find_default_lead_alias_id(self):
alias = self.env.ref('crm.mail_alias_lead_info', False)
if not alias:
alias = self.env['mail.alias'].search([
('alias_model_id.model', '=', 'crm.lead'),
('alias_force_thread_id', '=', False),
('alias_parent_model_id.model', '=', 'crm.team'),
('alias_parent_thread_id', '=', False),
('alias_defaults', '=', '{}')
], limit=1)
return alias
@api.onchange('group_use_lead')
def _onchange_group_use_lead(self):
""" Reset alias / leads configuration if leads are not used """
if not self.group_use_lead:
self.generate_lead_from_alias = False
@api.onchange('generate_lead_from_alias')
def _onchange_generate_lead_from_alias(self):
self.alias_prefix = 'info' if self.generate_lead_from_alias else False
@api.model
def get_values(self):
res = super(SaleConfigSettings, self).get_values()
alias = self._find_default_lead_alias_id()
res.update(
alias_prefix=alias.alias_name if alias else False,
generate_lead_from_alias=self.env['ir.config_parameter'].sudo().get_param('crm.generate_lead_from_alias')
)
return res
@api.multi
def set_values(self):
super(SaleConfigSettings, self).set_values()
self.env['ir.config_parameter'].sudo().set_param('crm.generate_lead_from_alias', self.generate_lead_from_alias)
alias = self._find_default_lead_alias_id()
if alias:
alias.write({'alias_name': self.alias_prefix})
else:
self.env['mail.alias'].with_context(
alias_model_name='crm.lead',
alias_parent_model_name='crm.team').create({'alias_name': self.alias_prefix})
@@ -25,7 +25,7 @@
title="Emails received to that address generate new leads not assigned to any sales channel yet. This can be made when converting them into opportunities. Incoming emails can be automatically assigned to specific sales channels. To do so, set an email alias on the sales channel."
groups="base.group_no_one">
<div class="o_setting_left_pane">
<field name="default_generate_lead_from_alias"/>
<field name="generate_lead_from_alias"/>
</div>
<div class="o_setting_right_pane">
<label string="Manually Assignation of Incoming Emails"/>
@@ -33,11 +33,11 @@
Generate unassigned leads from incoming emails. Leads coming from
that email will be assigned manually.
</div>
<div class="content-group" attrs="{'invisible': [('default_generate_lead_from_alias','=',False)]}">
<div class="content-group" attrs="{'invisible': [('generate_lead_from_alias','=',False)]}">
<div class="mt16">
<label string="Alias" class="o_light_label"/>
<field name="alias_prefix" class="oe_inline"
attrs="{'required': [('default_generate_lead_from_alias', '=', True)]}"/>
attrs="{'required': [('generate_lead_from_alias', '=', True)]}"/>
<span>@</span>
<field name="alias_domain" readonly="1" class="oe_inline"/>
</div>
+1 -1
View File
@@ -16,7 +16,7 @@ The module adds the possibility to synchronize Google Calendar with Odoo
'data/google_calendar_data.xml',
'data/google_calendar_data.xml',
'security/ir.model.access.csv',
'views/res_config_views.xml',
'views/base_config_settings_views.xml',
'views/res_users_views.xml',
'views/google_calendar_templates.xml',
],
+2 -2
View File
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import base_config_settings
from . import calendar
from . import res_users
from . import google_calendar
from . import res_config
from . import res_users
@@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models
class BaseConfigSettings(models.TransientModel):
_inherit = 'base.config.settings'
cal_client_id = fields.Char("Client_id")
cal_client_secret = fields.Char("Client_key")
server_uri = fields.Char('URI for tuto')
def set_values(self):
super(BaseConfigSettings, self).set_values()
set_param = self.env['ir.config_parameter'].set_param
set_param('google_calendar_client_id', (self.cal_client_id or '').strip())
set_param('google_calendar_client_secret', (self.cal_client_secret or '').strip())
@api.model
def get_values(self):
res = super(BaseConfigSettings, self).get_values()
get_param = self.env['ir.config_parameter'].sudo().get_param
res.update(
cal_client_id=get_param('google_calendar_client_id', default=''),
cal_client_secret=get_param('google_calendar_client_secret', default=''),
server_uri="%s/google_account/authentication" % get_param('web.base.url', default="http://yourcompany.odoo.com"),
)
return res
@@ -1,25 +0,0 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import fields, models
class CalendarSettings(models.TransientModel):
_inherit = 'base.config.settings'
cal_client_id = fields.Char("Client_id")
cal_client_secret = fields.Char("Client_key")
server_uri = fields.Char('URI for tuto')
def set_calset(self):
set_param = self.env['ir.config_parameter'].set_param
set_param('google_calendar_client_id', (self.cal_client_id or '').strip())
set_param('google_calendar_client_secret', (self.cal_client_secret or '').strip())
def get_default_all(self, fields):
get_param = self.env['ir.config_parameter'].get_param
cal_client_id = get_param('google_calendar_client_id', default='')
cal_client_secret = get_param('google_calendar_client_secret', default='')
server_uri = "%s/google_account/authentication" % get_param('web.base.url', default="http://yourcompany.odoo.com")
return dict(cal_client_id=cal_client_id, cal_client_secret=cal_client_secret, server_uri=server_uri)
+1 -1
View File
@@ -12,7 +12,7 @@
'data/google_drive_data.xml',
'views/google_drive_views.xml',
'views/google_drive_templates.xml',
'views/res_config_views.xml',
'views/base_config_settings_views.xml',
],
'demo': [
'data/google_drive_demo.xml'
+1 -1
View File
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import base_config_settings
from . import google_drive
from . import res_config
@@ -7,11 +7,7 @@ from odoo import api, fields, models
class BaseConfigSettings(models.TransientModel):
_inherit = "base.config.settings"
@api.model
def _default_google_drive_authorization_code(self):
return self.env['ir.config_parameter'].sudo().get_param('google_drive_authorization_code')
google_drive_authorization_code = fields.Char(string='Authorization Code', default=_default_google_drive_authorization_code)
google_drive_authorization_code = fields.Char(string='Authorization Code')
google_drive_uri = fields.Char(compute='_compute_drive_uri', string='URI', help="The URL to generate the authorization code from Google")
@api.depends('google_drive_authorization_code')
@@ -20,14 +16,20 @@ class BaseConfigSettings(models.TransientModel):
for config in self:
config.google_drive_uri = google_drive_uri
@api.multi
def set_google_authorization_code(self):
self.ensure_one()
ICP = self.env['ir.config_parameter']
@api.model
def get_values(self):
res = super(BaseConfigSettings, self).get_values()
res.update(
google_drive_authorization_code=self.env['ir.config_parameter'].sudo().get_param('google_drive_authorization_code'),
)
return res
def set_values(self):
super(BaseConfigSettings, self).set_values()
params = self.env['ir.config_parameter'].sudo()
authorization_code = self.google_drive_authorization_code
refresh_token = False
if authorization_code and authorization_code != ICP.get_param('google_drive_authorization_code'):
if authorization_code and authorization_code != params.get_param('google_drive_authorization_code'):
refresh_token = self.env['google.service'].generate_refresh_token('drive', authorization_code)
ICP.set_param('google_drive_authorization_code', authorization_code)
ICP.set_param('google_drive_refresh_token', refresh_token)
params.set_param('google_drive_authorization_code', authorization_code)
params.set_param('google_drive_refresh_token', refresh_token)
+1 -1
View File
@@ -25,7 +25,7 @@ actions(Check in/Check out) performed by them.
'report/hr_employee_badge.xml',
'views/hr_department_view.xml',
'views/hr_employee_view.xml',
'views/res_config_view.xml',
'views/attendance_config_settings_views.xml',
],
'demo': [
'data/hr_attendance_demo.xml'
+1 -1
View File
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
from . import attendance_config_settings
from . import hr_attendance
from . import hr_employee
from . import res_config
+1 -1
View File
@@ -39,7 +39,7 @@ This module also uses analytic accounting and is compatible with the invoice on
'report/report_expense_sheet.xml',
'views/hr_dashboard.xml',
'views/hr_expense.xml',
'views/res_config_views.xml',
'views/hr_expense_config_settings_views.xml',
'data/web_planner_data.xml',
],
'demo': ['data/hr_expense_demo.xml'],
+1 -1
View File
@@ -4,5 +4,5 @@ from . import account_move_line
from . import hr_department
from . import hr_expense
from . import product_template
from . import res_config
from . import hr_expense_config_settings
from . import web_planner
+2 -1
View File
@@ -309,7 +309,8 @@ class HrExpense(models.Model):
@api.model
def get_empty_list_help(self, help_message):
if help_message:
alias_record = self.env.ref('hr_expense.mail_alias_expense')
use_mailgateway = self.env['ir.config_parameter'].sudo().get_param('hr_expense.use_mailgateway')
alias_record = use_mailgateway and self.env.ref('hr_expense.mail_alias_expense') or False
if alias_record and alias_record.alias_domain and alias_record.alias_name:
link = "<a id='o_mail_test' href='mailto:%(email)s?subject=Lunch%%20with%%20customer%%3A%%20%%2412.32'>%(email)s</a>" % {
'email': '%s@%s' % (alias_record.alias_name, alias_record.alias_domain)
@@ -0,0 +1,40 @@
# -*- coding: utf-8 -*-
from odoo import api, fields, models
class HrExpenseConfigSettings(models.TransientModel):
_name = 'hr.expense.config.settings'
_inherit = 'res.config.settings'
alias_prefix = fields.Char('Default Alias Name for Expenses')
alias_domain = fields.Char('Alias Domain', default=lambda self: self.env["ir.config_parameter"].sudo().get_param("mail.catchall.domain"))
group_analytic_accounting = fields.Boolean(
string='Analytic Accounting',
implied_group='analytic.group_analytic_accounting')
group_uom = fields.Boolean(
string="Units of Measure",
implied_group='product.group_uom')
use_mailgateway = fields.Boolean(string='Let your employees record expenses by email')
module_project = fields.Boolean(string="Project")
module_sale = fields.Boolean(string="Customer Billing")
@api.model
def get_values(self):
res = super(HrExpenseConfigSettings, self).get_values()
res.update(
alias_prefix=self.env.ref('hr_expense.mail_alias_expense').alias_name,
use_mailgateway=self.env['ir.config_parameter'].sudo().get_param('hr_expense.use_mailgateway'),
)
return res
@api.multi
def set_values(self):
super(HrExpenseConfigSettings, self).set_values()
self.env.ref('hr_expense.mail_alias_expense').write({'alias_name': self.alias_prefix})
self.env['ir.config_parameter'].sudo().set_param('hr_expense.use_mailgateway', self.use_mailgateway)
@api.onchange('use_mailgateway')
def _onchange_use_mailgateway(self):
if not self.use_mailgateway:
self.alias_prefix = False
-27
View File
@@ -1,27 +0,0 @@
# -*- coding: utf-8 -*-
from odoo import api, fields, models
class HrExpenseConfigSettings(models.TransientModel):
_name = 'hr.expense.config.settings'
_inherit = 'res.config.settings'
alias_prefix = fields.Char('Default Alias Name for Expenses')
alias_domain = fields.Char('Alias Domain', default=lambda self: self.env["ir.config_parameter"].sudo().get_param("mail.catchall.domain"))
group_analytic_accounting = fields.Boolean(string='Analytic Accounting',
implied_group='analytic.group_analytic_accounting')
group_uom = fields.Boolean("Units of Measure",
implied_group='product.group_uom')
default_alias_email = fields.Boolean(string='Let your employees record expenses by email', default_model='hr.expense.config.settings')
module_project = fields.Boolean(string="Project")
module_sale = fields.Boolean(string="Customer Billing")
@api.model
def get_default_alias_prefix(self, fields):
alias_name = self.env.ref('hr_expense.mail_alias_expense').alias_name
return {'alias_prefix': alias_name}
@api.multi
def set_default_alias_prefix(self):
for record in self:
self.env.ref('hr_expense.mail_alias_expense').write({'alias_name': record.alias_prefix})
@@ -16,14 +16,14 @@
<div class="row mt16 o_settings_container">
<div class="col-xs-12 col-md-6 o_setting_box" title="You can setup a generic email alias to create incoming expenses easily. Write an email with the receipt in attachment to create an expense line in one click. If the mail subject contains the product's internal reference between brackets, the product will be set automatically. Type the expense amount in the mail subject to set it on the expense too.">
<div class="o_setting_left_pane">
<field name="default_alias_email"/>
<field name="use_mailgateway"/>
</div>
<div class="o_setting_right_pane">
<label string="Emails" for="default_alias_email"/>
<label string="Emails" for="use_mailgateway"/>
<div class="text-muted">
Let your employees record expenses by email
</div>
<div class="content-group" attrs="{'invisible': ['|', ('default_alias_email', '=', False), ('alias_domain', 'in', ['localhost', '', False])]}">
<div class="content-group" attrs="{'invisible': ['|', ('use_mailgateway', '=', False), ('alias_domain', 'in', ['localhost', '', False])]}">
<div class="mt16">
<label string="Email Alias" class="o_light_label"/>
<field name="alias_prefix" class="oe_inline"/>
@@ -31,7 +31,7 @@
<field name="alias_domain" class="oe_inline" readonly="1"/>
</div>
</div>
<div class="content-group" attrs="{'invisible': ['|', ('default_alias_email', '=', False), ('alias_domain', 'not in', ['localhost', '', False])]}">
<div class="content-group" attrs="{'invisible': ['|', ('use_mailgateway', '=', False), ('alias_domain', 'not in', ['localhost', '', False])]}">
<div class="mt16">
<button type="action" name="base_setup.action_general_configuration" icon="fa-arrow-right" string="Setup your domain alias" class="btn-link"/>
</div>
+1 -1
View File
@@ -25,7 +25,7 @@ up a management by affair.
'security/hr_timesheet_security.xml',
'security/ir.model.access.csv',
'views/hr_timesheet_views.xml',
'views/res_config_views.xml',
'views/hr_timesheet_config_settings_views.xml',
'views/project_views.xml',
'report/hr_timesheet_report_view.xml',
'report/report_timesheet_templates.xml',
+1 -1
View File
@@ -2,5 +2,5 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import hr_timesheet
from . import res_config
from . import hr_timesheet_config_settings
from . import project
@@ -10,13 +10,14 @@ class FleetConfigSettings(models.TransientModel):
max_unused_cars = fields.Integer(string='Maximum unused cars')
@api.multi
def set_default_max_unused_cars(self):
def set_values(self):
super(FleetConfigSettings, self).set_values()
Param = self.env['ir.config_parameter'].sudo()
Param.set_param("l10n_be_hr_payroll_fleet.max_unused_cars", self.max_unused_cars)
@api.model
def get_default_max_unused_cars(self, fields):
def get_values(self):
res = super(FleetConfigSettings, self).get_values()
params = self.env['ir.config_parameter'].sudo()
max_unused_cars = params.get_param('l10n_be_hr_payroll_fleet.max_unused_cars', default=3)
return dict(max_unused_cars=int(max_unused_cars))
res.update(max_unused_cars=params.get_param('l10n_be_hr_payroll_fleet.max_unused_cars', default=3))
return res
+1 -1
View File
@@ -39,7 +39,7 @@ Here is how it works:
'report/isr_report.xml',
'views/res_bank_view.xml',
'views/account_invoice_view.xml',
'views/res_config_view.xml',
'views/account_config_settings_views.xml',
],
'demo': [
+1 -1
View File
@@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import account_config_settings
from . import account_invoice
from . import mail_compose_message
from . import mail_template
from . import res_bank
from . import res_company
from . import res_config
-1
View File
@@ -52,6 +52,5 @@
<record id="open_l10n_eu_service" model="ir.actions.todo">
<field name="action_id" ref="action_eu_service"/>
<field name="type">automatic</field>
</record>
</odoo>
+1 -1
View File
@@ -40,6 +40,6 @@ With this module you will have:
"data/account_tax_data.xml",
"data/fiscal_position_data.xml",
"data/account_chart_template_data.yml",
"views/res_config_view.xml",
"views/account_config_settings_views.xml",
],
}
+2 -2
View File
@@ -2,6 +2,6 @@
# Copyright 2016 Vauxoo (https://www.vauxoo.com) <info@vauxoo.com>
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
from . import chart_template
from . import account
from . import res_config
from . import account_config_settings
from . import chart_template
@@ -4,6 +4,6 @@ from odoo import fields, models
class AccountConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
_inherit = 'account.config.settings'
module_l10n_mx_edi = fields.Boolean('Mexican Electronic Invoicing')
+1 -1
View File
@@ -37,7 +37,7 @@ Main Features
'views/mail_channel_views.xml',
'views/mail_shortcode_views.xml',
'views/mail_activity_views.xml',
'views/res_config_views.xml',
'views/base_config_settings_views.xml',
'data/mail_data.xml',
'data/mail_channel_data.xml',
'data/mail_shortcode_data.xml',
+1 -1
View File
@@ -14,7 +14,7 @@ from . import mail_template
from . import mail_shortcode
from . import res_partner
from . import res_users
from . import res_config
from . import base_config_settings
from . import update
from . import ir_actions
from . import ir_autovacuum
@@ -8,7 +8,7 @@ from werkzeug import urls
from odoo import api, fields, models, tools
class BaseConfiguration(models.TransientModel):
class BaseConfigSettings(models.TransientModel):
""" Inherit the base settings to add a counter of failed email + configure
the alias domain. """
_inherit = 'base.config.settings'
@@ -18,14 +18,11 @@ class BaseConfiguration(models.TransientModel):
"the Odoo server, enter the domain name here.")
@api.model
def get_default_fail_counter(self, fields):
previous_date = datetime.datetime.now() - datetime.timedelta(days=30)
return {
'fail_counter': self.env['mail.mail'].sudo().search_count([('date', '>=', previous_date.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT)), ('state', '=', 'exception')]),
}
def get_values(self):
res = super(BaseConfigSettings, self).get_values()
previous_date = datetime.datetime.now() - datetime.timedelta(days=30)
@api.model
def get_default_alias_domain(self, fields):
alias_domain = self.env["ir.config_parameter"].get_param("mail.catchall.domain", default=None)
if alias_domain is None:
domain = self.env["ir.config_parameter"].get_param("web.base.url")
@@ -33,9 +30,16 @@ class BaseConfiguration(models.TransientModel):
alias_domain = urls.url_parse(domain).host
except Exception:
pass
return {'alias_domain': alias_domain or False}
@api.multi
def set_alias_domain(self):
for record in self:
self.env['ir.config_parameter'].set_param("mail.catchall.domain", record.alias_domain or '')
res.update(
fail_counter=self.env['mail.mail'].sudo().search_count([
('date', '>=', previous_date.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT)),
('state', '=', 'exception')]),
alias_domain=alias_domain or False,
)
return res
def set_values(self):
super(BaseConfigSettings, self).set_values()
self.env['ir.config_parameter'].set_param("mail.catchall.domain", self.alias_domain or '')
+1 -1
View File
@@ -30,7 +30,7 @@ professional emails and reuse templates in a few clicks.
'views/link_tracker_views.xml',
'views/mass_mailing_template.xml',
'views/mass_mailing_views.xml',
'views/res_config_views.xml',
'views/mass_mailing_config_settings_views.xml',
'security/ir.model.access.csv',
'views/editor_field_html.xml',
'views/themes_templates.xml',
+1 -1
View File
@@ -5,6 +5,6 @@ from . import mass_mailing
from . import mass_mailing_stats
from . import mail_mail
from . import mail_thread
from . import res_config
from . import mass_mailing_config_settings
from . import mass_mailing_report
from . import link_tracker
+20 -2
View File
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import fields, models
from odoo import api, fields, models
class MrpConfigSettings(models.TransientModel):
@@ -11,7 +11,7 @@ class MrpConfigSettings(models.TransientModel):
company_id = fields.Many2one('res.company', string='Company', required=True,
default=lambda self: self.env.user.company_id)
manufacturing_lead = fields.Float(related='company_id.manufacturing_lead', string="Manufacturing Lead Time")
default_use_manufacturing_lead = fields.Boolean(string="Default Manufacturing Lead Time", default_model='mrp.config.settings')
use_manufacturing_lead = fields.Boolean(string="Default Manufacturing Lead Time", oldname='default_use_manufacturing_lead')
group_product_variant = fields.Boolean("Attributes & Variants",
implied_group='product.group_product_variant')
module_mrp_byproduct = fields.Boolean("By-Products")
@@ -22,3 +22,21 @@ class MrpConfigSettings(models.TransientModel):
group_mrp_routings = fields.Boolean("Work Orders",
implied_group='mrp.group_mrp_routings')
module_mrp_repair = fields.Boolean("Repair")
@api.model
def get_values(self):
res = super(MrpConfigSettings, self).get_values()
res.update(
use_manufacturing_lead=self.env['ir.config_parameter'].sudo().get_param('mrp.use_manufacturing_lead')
)
return res
@api.multi
def set_values(self):
super(MrpConfigSettings, self).set_values()
self.env['ir.config_parameter'].sudo().set_param('mrp.use_manufacturing_lead', self.use_manufacturing_lead)
@api.onchange('use_manufacturing_lead')
def _onchange_use_manufacturing_lead(self):
if not self.use_manufacturing_lead:
self.manufacturing_lead = 0.0
@@ -130,15 +130,15 @@
</div>
<div class="col-md-6 col-xs-12 o_setting_box" id="security_lead_time">
<div class="o_setting_left_pane">
<field name="default_use_manufacturing_lead"/>
<field name="use_manufacturing_lead"/>
</div>
<div class="o_setting_right_pane">
<label string="Security Lead Time" for="default_use_manufacturing_lead"/>
<label string="Security Lead Time" for="use_manufacturing_lead"/>
<span class="fa fa-lg fa-building-o" title="Values set here are company-specific." groups="base.group_multi_company"/>
<div class="text-muted">
Schedule manufacturing orders earlier to avoid delays
</div>
<div class="content-group" attrs="{'invisible': [('default_use_manufacturing_lead','=',False)]}">
<div class="content-group" attrs="{'invisible': [('use_manufacturing_lead','=',False)]}">
<div class="mt16" >
Move forward deadline start dates by
<field name="manufacturing_lead" class="oe_inline"/> days
+1 -1
View File
@@ -16,7 +16,7 @@ pads (by default, http://etherpad.com/).
'depends': ['web', 'base_setup'],
'data': [
'views/pad.xml',
'views/res_config_view.xml',
'views/base_config_settings_views.xml',
],
'demo': ['data/pad_demo.xml'],
'web': True,
+1 -1
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import base_config_settings
from . import pad
from . import res_company
from . import res_config
+1 -1
View File
@@ -56,7 +56,7 @@ Main Features
'views/account_statement_report.xml',
'views/res_users_view.xml',
'views/res_partner_view.xml',
'views/res_config_view.xml',
'views/pos_config_settings_views.xml',
'views/report_statement.xml',
'views/report_userlabel.xml',
'views/report_saledetails.xml',
+1 -1
View File
@@ -6,9 +6,9 @@ from . import account_journal
from . import barcode_rule
from . import pos_category
from . import pos_config
from . import pos_config_settings
from . import pos_order
from . import pos_session
from . import product
from . import res_config
from . import res_partner
from . import res_users
@@ -3,7 +3,7 @@
from odoo import api, fields, models
class PosConfiguration(models.TransientModel):
class PosConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
_name = 'pos.config.settings'
@@ -17,11 +17,12 @@ class PosConfiguration(models.TransientModel):
implied_group='product.group_sale_pricelist',
help="""Allows to manage different prices based on rules per category of customers.
Example: 10% for retailers, promotion of 5 EUR on this product, etc.""")
default_sale_price = fields.Boolean("A single sale price per product", default_model='pos.config.settings')
default_pricelist_setting = fields.Selection([
use_pos_sale_price = fields.Boolean("A single sale price per product", oldname='default_sale_price')
pos_pricelist_setting = fields.Selection([
('percentage', 'Multiple prices per product (e.g. quantity, shop-specific)'),
('formula', 'Price computed from formulas (discounts, margins, rounding)')
], string="Multiple Prices per Products", default_model='pos.config.settings')
], string="Multiple Prices per Products",
oldname='default_pricelist_setting')
module_pos_restaurant = fields.Boolean(string="Restaurant")
module_pos_loyalty = fields.Boolean(string="Loyalty Program")
module_pos_discount = fields.Boolean(string="Global Discounts")
@@ -29,22 +30,22 @@ class PosConfiguration(models.TransientModel):
module_pos_reprint = fields.Boolean(string="Reprint Receipt")
module_pos_data_drinks = fields.Boolean(string="Import common drinks data")
@api.onchange('default_sale_price')
@api.onchange('use_pos_sale_price')
def _onchange_fix_sale_price(self):
if not self.default_sale_price:
self.default_pricelist_setting = False
if self.default_sale_price and not self.default_pricelist_setting:
self.default_pricelist_setting = 'percentage'
if not self.use_pos_sale_price:
self.pos_pricelist_setting = False
if self.use_pos_sale_price and not self.pos_pricelist_setting:
self.pos_pricelist_setting = 'percentage'
@api.onchange('default_pricelist_setting')
@api.onchange('pos_pricelist_setting')
def _onchange_sale_price(self):
if self.default_pricelist_setting == 'percentage':
if self.pos_pricelist_setting == 'percentage':
self.update({
'group_product_pricelist': True,
'group_sale_pricelist': True,
'group_pricelist_item': False,
})
elif self.default_pricelist_setting == 'formula':
elif self.pos_pricelist_setting == 'formula':
self.update({
'group_product_pricelist': False,
'group_sale_pricelist': True,
@@ -56,3 +57,16 @@ class PosConfiguration(models.TransientModel):
'group_sale_pricelist': False,
'group_pricelist_item': False,
})
def get_values(self):
res = super(PosConfigSettings, self).get_values()
res.update(
use_pos_sale_price=self.env['ir.config_parameter'].sudo().get_param('pos.use_pos_sale_price'),
pos_pricelist_setting=self.env['ir.config_parameter'].sudo().get_param('pos.pos_pricelist_setting'),
)
return res
def set_values(self):
super(PosConfigSettings, self).set_values()
self.env['ir.config_parameter'].sudo().set_param('pos.use_pos_sale_price', self.use_pos_sale_price)
self.env['ir.config_parameter'].sudo().set_param('pos.pos_pricelist_setting', self.pos_pricelist_setting)
@@ -55,23 +55,23 @@
</div>
<div class="col-xs-12 col-md-6 o_setting_box" title="There are two ways to manage pricelists: 1) Multiple prices per product (e.g. quantity, shop-specific) : must be set in the Sales tab of the product detail form. 2) Price computed from formulas (discounts, margins, rounding) : must be set in the pricelist form.">
<div class="o_setting_left_pane">
<field name="default_sale_price"/>
<field name="use_pos_sale_price"/>
</div>
<div class="o_setting_right_pane">
<label for="default_pricelist_setting"/>
<label for="pos_pricelist_setting"/>
<div class="text-muted">
Set shop-specific prices, seasonal discounts, etc.
</div>
<div class="content-group" attrs="{'invisible': [('default_sale_price','=',False)]}">
<div class="content-group" attrs="{'invisible': [('use_pos_sale_price','=',False)]}">
<div class="mt16">
<field name="group_product_pricelist" invisible="1"/>
<field name="group_sale_pricelist" invisible="1"/>
<field name="group_pricelist_item" invisible="1"/>
<field name="default_pricelist_setting" widget="radio" class="o_light_label"/>
<field name="pos_pricelist_setting" widget="radio" class="o_light_label"/>
</div>
<div>
<button name="%(product.product_pricelist_action2)d" icon="fa-arrow-right" type="action"
string="Pricelists" attrs="{'invisible': [('default_pricelist_setting', '=', False)]}" class="btn-link"/>
string="Pricelists" attrs="{'invisible': [('pos_pricelist_setting', '=', False)]}" class="btn-link"/>
</div>
</div>
</div>
@@ -14,14 +14,15 @@ class BaseConfigSettings(models.TransientModel):
" * Unchecked : Each company can see only its product (product where company is defined). Product not related to a company are visible for all companies.")
@api.model
def get_default_company_share_product(self, fields):
def get_values(self):
res = super(BaseConfigSettings, self).get_values()
product_rule = self.env.ref('product.product_comp_rule')
return {
'company_share_product': not bool(product_rule.active)
}
res.update(
company_share_product=not bool(product_rule.active),
)
return res
@api.multi
def set_auth_company_share_product(self):
self.ensure_one()
def set_values(self):
super(BaseConfigSettings, self).set_values()
product_rule = self.env.ref('product.product_comp_rule')
product_rule.write({'active': not bool(self.company_share_product)})
+1 -1
View File
@@ -40,7 +40,7 @@ Dashboard / Reports for Project Management will include:
'report/project_report_views.xml',
'views/project_views.xml',
'views/res_partner_views.xml',
'views/res_config_views.xml',
'views/project_config_settings_views.xml',
'views/project_templates.xml',
'data/web_planner_data.xml',
'data/project_mail_template_data.xml',
-4
View File
@@ -18,10 +18,6 @@
<field name="object">project.task</field>
</record>
<!-- alias domain: project.config.settings -->
<function id="default_alias_domain_project" model="ir.values" name="set_default" eval="('project.config.settings', 'generate_project_alias', 1)"/>
<!-- sale_timesheet and project define the same field without depending on each, which causes the field to be deleted when the module that created it
is deleted. To avoid this, we create xmlids manually for this field in both modules to prevent accidental deletion. To fix in saas-7 by moving the field definition-->
<record id="duplicate_field_xmlid" model="ir.model.data">
+1 -1
View File
@@ -2,7 +2,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import project
from . import project_config_settings
from . import res_company
from . import res_partner
from . import res_config
from . import web_planner
-3
View File
@@ -252,9 +252,6 @@ class Project(models.Model):
@api.model
def create(self, vals):
ir_values = self.env['ir.values'].get_default('project.config.settings', 'generate_project_alias')
if ir_values:
vals['alias_name'] = vals.get('alias_name') or vals.get('name')
# Prevent double project creation when 'use_tasks' is checked
self = self.with_context(project_creation_in_progress=True, mail_create_nosubscribe=True)
project = super(Project, self).create(vals)
@@ -14,11 +14,6 @@ class ProjectConfiguration(models.TransientModel):
module_hr_timesheet = fields.Boolean("Timesheets")
module_project_timesheet_synchro = fields.Boolean("Awesome Timesheet")
module_rating_project = fields.Boolean(string="Rating on Tasks")
generate_project_alias = fields.Selection([
(0, "Do not create an email alias automatically"),
(1, "Automatically generate an email alias at the project creation")
], string="Project Alias",
help="Odoo will generate an email alias at the project creation from project name.")
module_project_forecast = fields.Boolean(string="Forecasts")
module_hr_holidays = fields.Boolean("Leave Management")
module_hr_timesheet_attendance = fields.Boolean("Attendances")
@@ -26,10 +21,3 @@ class ProjectConfiguration(models.TransientModel):
module_hr_expense = fields.Boolean("Expenses")
module_project_issue = fields.Boolean("Issue Tracking")
group_subtask_project = fields.Boolean("Sub-tasks", implied_group="project.group_subtask_project")
@api.multi
def set_default_generate_project_alias(self):
check = self.env.user.has_group('base.group_system')
Values = check and self.env['ir.values'].sudo() or self.env['ir.values']
for config in self:
Values.set_default('project.config.settings', 'generate_project_alias', config.generate_project_alias)

Some files were not shown because too many files have changed in this diff Show More