summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
authoreco-odoo <eco@odoo.com>2018-07-20 14:09:27 +0200
committerYannick Tivisse <yti@odoo.com>2018-08-10 16:08:47 +0200
commit89e358caa8627c5eff21ee63015dece0997db2b4 (patch)
tree8534521fd812ec993c31d6cc0271bdb213d94d00 /addons
parent33dee649a891fc5e0385862cfdc0890b000749f2 (diff)
[FIX] onboarding: Fix/Update onboarding to v2.0
Specification ============= - Fix lots of bug due to the BS4 migration - Improve steps - Validate some steps (Like the company configuration) in all the onboarding bars if done in one onboarding bar. - Only animate the confetti one time if a step is done, instead of on each view loading For more information, see: https://www.odoo.com/web#id=1869513&action=333&active_id=965&model=project.task&view_type=form&menu_id=4720
Diffstat (limited to 'addons')
-rw-r--r--addons/account/__manifest__.py1
-rw-r--r--addons/account/controllers/onboarding.py14
-rw-r--r--addons/account/models/account_invoice.py2
-rw-r--r--addons/account/models/account_journal_dashboard.py18
-rw-r--r--addons/account/models/company.py154
-rw-r--r--addons/account/models/res_config_settings.py1
-rw-r--r--addons/account/static/src/js/account_dashboard_setup_bar.js235
-rw-r--r--addons/account/static/src/xml/account_dashboard_setup_bar.xml37
-rw-r--r--addons/account/static/tests/account_dashboard_setup_bar_tests.js65
-rw-r--r--addons/account/views/account.xml1
-rw-r--r--addons/account/views/account_onboarding_templates.xml110
-rw-r--r--addons/account/views/res_config_settings_views.xml12
-rw-r--r--addons/account/wizard/setup_wizards.py8
-rw-r--r--addons/account/wizard/setup_wizards_view.xml26
-rw-r--r--addons/base_setup/models/res_config_settings.py2
-rw-r--r--addons/base_vat/views/res_company_views.xml3
-rw-r--r--addons/payment/models/res_company.py23
-rw-r--r--addons/payment/views/payment_acquirer_onboarding_templates.xml153
-rw-r--r--addons/payment/wizards/payment_acquirer_onboarding_wizard.py93
-rw-r--r--addons/sale/controllers/onboarding.py10
-rw-r--r--addons/sale/models/res_company.py125
-rw-r--r--addons/sale/models/sale.py1
-rw-r--r--addons/sale/static/src/img/onboarding_quotation_order_tooltip.jpgbin0 -> 12084 bytes
-rw-r--r--addons/sale/static/src/scss/sale_onboarding.scss11
-rw-r--r--addons/sale/views/assets.xml6
-rw-r--r--addons/sale/views/sale_onboarding_views.xml150
-rw-r--r--addons/sale/views/sale_views.xml2
-rw-r--r--addons/sale/wizard/payment_acquirer_onboarding_wizard.py30
-rw-r--r--addons/web/static/src/js/views/abstract_controller.js39
-rw-r--r--addons/web/static/src/scss/banner.scss3
-rw-r--r--addons/web/static/src/scss/form_view.scss14
-rw-r--r--addons/web/views/webclient_templates.xml1
-rw-r--r--addons/website_sale/models/res_company.py4
-rw-r--r--addons/website_sale/views/onboarding_views.xml17
-rw-r--r--addons/website_sale/wizard/payment_acquirer_onboarding_wizard.py2
-rw-r--r--addons/website_theme_install/models/__init__.py1
-rw-r--r--addons/website_theme_install/models/res_company.py28
-rw-r--r--addons/website_theme_install/views/views.xml11
38 files changed, 559 insertions, 854 deletions
diff --git a/addons/account/__manifest__.py b/addons/account/__manifest__.py
index 13d366f8200..1f0aa99d6a4 100644
--- a/addons/account/__manifest__.py
+++ b/addons/account/__manifest__.py
@@ -86,7 +86,6 @@ You could use this simplified accounting in case you work with an (external) acc
"static/src/xml/account_reconciliation.xml",
"static/src/xml/account_payment.xml",
"static/src/xml/account_report_backend.xml",
- "static/src/xml/account_dashboard_setup_bar.xml",
],
'installable': True,
'application': True,
diff --git a/addons/account/controllers/onboarding.py b/addons/account/controllers/onboarding.py
index 1fd91294489..879fd0a82fc 100644
--- a/addons/account/controllers/onboarding.py
+++ b/addons/account/controllers/onboarding.py
@@ -10,13 +10,15 @@ class OnboardingController(http.Controller):
It can be empty if the user has closed it or if he doesn't have
the permission to see it. """
+ company = request.env.user.company_id
if not request.env.user._is_admin() or \
- request.env.user.company_id.account_invoice_onboarding_closed:
+ company.account_invoice_onboarding_state == 'closed':
return {}
return {
'html': request.env.ref('account.account_invoice_onboarding_panel').render({
- 'company': request.env.user.company_id,
+ 'company': company,
+ 'state': company.get_and_update_account_invoice_onboarding_state()
})
}
@@ -25,13 +27,15 @@ class OnboardingController(http.Controller):
""" Returns the `banner` for the account dashboard onboarding panel.
It can be empty if the user has closed it or if he doesn't have
the permission to see it. """
+ company = request.env.user.company_id
if not request.env.user._is_admin() or \
- request.env.user.company_id.account_dashboard_onboarding_closed:
+ company.account_dashboard_onboarding_state == 'closed':
return {}
return {
'html': request.env.ref('account.account_dashboard_onboarding_panel').render({
- 'company': request.env.user.company_id,
+ 'company': company,
+ 'state': company.get_and_update_account_dashboard_onboarding_state()
})
- } \ No newline at end of file
+ }
diff --git a/addons/account/models/account_invoice.py b/addons/account/models/account_invoice.py
index 0ba6359b6af..58711dfb92f 100644
--- a/addons/account/models/account_invoice.py
+++ b/addons/account/models/account_invoice.py
@@ -607,7 +607,7 @@ class AccountInvoice(models.Model):
def message_post(self, **kwargs):
if self.env.context.get('mark_invoice_as_sent'):
self.filtered(lambda inv: not inv.sent).write({'sent': True})
- self.env.user.company_id.account_onboarding_sample_invoice_sent = True
+ self.env.user.company_id.set_onboarding_step_done('account_onboarding_sample_invoice_state')
return super(AccountInvoice, self.with_context(mail_post_autofollow=True)).message_post(**kwargs)
@api.model
diff --git a/addons/account/models/account_journal_dashboard.py b/addons/account/models/account_journal_dashboard.py
index a8e229883d1..da0c1dbb960 100644
--- a/addons/account/models/account_journal_dashboard.py
+++ b/addons/account/models/account_journal_dashboard.py
@@ -26,7 +26,6 @@ class account_journal(models.Model):
kanban_dashboard_graph = fields.Text(compute='_kanban_dashboard_graph')
show_on_dashboard = fields.Boolean(string='Show journal on dashboard', help="Whether this journal should be displayed on the dashboard or not", default=True)
color = fields.Integer("Color Index", default=0)
- account_setup_bank_data_done = fields.Boolean(string='Bank setup marked as done', related='company_id.account_setup_bank_data_done', help="Technical field used in the special view for the setup bar step.")
def _graph_title_and_key(self):
if self.type in ['sale', 'purchase']:
@@ -434,23 +433,10 @@ class account_journal(models.Model):
#####################
# Setup Steps Stuff #
#####################
- @api.model
- def retrieve_account_dashboard_setup_bar(self):
- """ Returns the data used by the setup bar on the Accounting app dashboard."""
- company = self.env.user.company_id
- return {
- 'show_setup_bar': not company.account_setup_bar_closed,
- 'company': company.account_setup_company_data_done,
- 'bank': company.account_setup_bank_data_done,
- 'fiscal_year': company.account_setup_fy_data_done,
- 'chart_of_accounts': company.account_setup_coa_done,
- 'initial_balance': company.opening_move_posted(),
- }
-
def mark_bank_setup_as_done_action(self):
""" Marks the 'bank setup' step as done in the setup bar and in the company."""
- self.company_id.account_setup_bank_data_done = True
+ self.company_id.set_onboarding_step_done('account_setup_bank_data_state')
def unmark_bank_setup_as_done_action(self):
""" Marks the 'bank setup' step as not done in the setup bar and in the company."""
- self.company_id.account_setup_bank_data_done = False
+ self.company_id.account_setup_bank_data_state = 'not_done'
diff --git a/addons/account/models/company.py b/addons/account/models/company.py
index 7e4ab7c216f..b659d0ad00e 100644
--- a/addons/account/models/company.py
+++ b/addons/account/models/company.py
@@ -71,33 +71,45 @@ Best Regards,'''))
account_opening_journal_id = fields.Many2one(string='Opening Journal', comodel_name='account.journal', related='account_opening_move_id.journal_id', help="Journal where the opening entry of this company's accounting has been posted.")
account_opening_date = fields.Date(string='Opening Date', related='account_opening_move_id.date', help="Date at which the opening entry of this company's accounting has been posted.")
- #Fields marking the completion of a setup step
- account_setup_company_data_done = fields.Boolean(string='Company Setup Marked As Done', help="Technical field holding the status of the company setup step.")
- account_setup_bank_data_done = fields.Boolean('Bank Setup Marked As Done', help="Technical field holding the status of the bank setup step.")
- account_setup_fy_data_done = fields.Boolean('Financial Year Setup Marked As Done', help="Technical field holding the status of the financial year setup step.")
- account_setup_coa_done = fields.Boolean(string='Chart of Account Checked', help="Technical field holding the status of the chart of account setup step.")
- account_setup_bar_closed = fields.Boolean(string='Setup Bar Closed', help="Technical field set to True when setup bar has been closed by the user.")
-
- # account invoice onboarding
- account_invoice_onboarding_closed = fields.Boolean(
- string="Account invoice onboarding panel closed",
- help="Refers to the account invoice onboarding panel closed state.")
- account_invoice_onboarding_folded = fields.Boolean(
- string="Account invoice onboarding panel folded",
- help="Refers to the account invoice onboarding panel folded state.")
-
- account_onboarding_invoice_layout_done = fields.Boolean("Onboarding invoice layout step done",
- compute="_compute_account_onboarding_invoice_layout_done")
- account_onboarding_sample_invoice_sent = fields.Boolean(
- "Onboarding sample invoice step completed", default=False)
+ # Fields marking the completion of a setup step
+ # YTI FIXME : The selection should be factorize as a static list in base, like ONBOARDING_STEP_STATES
+ account_setup_bank_data_state = fields.Selection([('not_done', "Not done"), ('just_done', "Just done"), ('done', "Done")], string="State of the onboarding bank data step", default='not_done')
+ account_setup_fy_data_state = fields.Selection([('not_done', "Not done"), ('just_done', "Just done"), ('done', "Done")], string="State of the onboarding fiscal year step", default='not_done')
+ account_setup_coa_state = fields.Selection([('not_done', "Not done"), ('just_done', "Just done"), ('done', "Done")], string="State of the onboarding charts of account step", default='not_done')
+ account_onboarding_invoice_layout_state = fields.Selection([('not_done', "Not done"), ('just_done', "Just done"), ('done', "Done")], string="State of the onboarding invoice layout step", default='not_done')
+ account_onboarding_sample_invoice_state = fields.Selection([('not_done', "Not done"), ('just_done', "Just done"), ('done', "Done")], string="State of the onboarding sample invoice step", default='not_done')
+ account_onboarding_sale_tax_state = fields.Selection([('not_done', "Not done"), ('just_done', "Just done"), ('done', "Done")], string="State of the onboarding sale tax step", default='not_done')
# account dashboard onboarding
- account_dashboard_onboarding_closed = fields.Boolean(
- string="Account dashboard onboarding panel closed",
- help="Refers to the account dashboard onboarding panel closed state.")
- account_dashboard_onboarding_folded = fields.Boolean(
- string="Account dashboard onboarding panel folded",
- help="Refers to the account dashboard onboarding panel folded state.")
+ account_invoice_onboarding_state = fields.Selection([('not_done', "Not done"), ('just_done', "Just done"), ('done', "Done"), ('closed', "Closed")], string="State of the account invoice onboarding panel", default='not_done')
+ account_dashboard_onboarding_state = fields.Selection([('not_done', "Not done"), ('just_done', "Just done"), ('done', "Done"), ('closed', "Closed")], string="State of the account dashboard onboarding panel", default='not_done')
+
+ def get_and_update_account_invoice_onboarding_state(self):
+ """ This method is called on the controller rendering method and ensures that the animations
+ are displayed only one time. """
+ return self.get_and_update_onbarding_state(
+ 'account_invoice_onboarding_state',
+ self.get_account_invoice_onboarding_steps_states_names()
+ )
+
+ # YTI FIXME: Define only one method that returns {'account': [], 'sale': [], ...}
+ def get_account_invoice_onboarding_steps_states_names(self):
+ """ Necessary to add/edit steps from other modules (payment acquirer in this case). """
+ return [
+ 'base_onboarding_company_state',
+ 'account_onboarding_invoice_layout_state',
+ 'account_onboarding_sample_invoice_state',
+ ]
+
+ def get_and_update_account_dashboard_onboarding_state(self):
+ """ This method is called on the controller rendering method and ensures that the animations
+ are displayed only one time. """
+ return self.get_and_update_onbarding_state('account_dashboard_onboarding_state', [
+ 'base_onboarding_company_state',
+ 'account_setup_bank_data_state',
+ 'account_setup_fy_data_state',
+ 'account_setup_coa_state',
+ ])
@api.multi
def _check_lock_dates(self, vals):
@@ -261,20 +273,6 @@ Best Regards,'''))
return super(ResCompany, self).write(values)
@api.model
- def setting_init_company_action(self):
- """ Called by the 'Company Data' button of the setup bar."""
- company = self.env.user.company_id
- view_id = self.env.ref('account.setup_view_company_form').id
- return {'type': 'ir.actions.act_window',
- 'name': _('Company Data'),
- 'res_model': 'res.company',
- 'target': 'new',
- 'view_mode': 'form',
- 'res_id': company.id,
- 'views': [[view_id, 'form']],
- }
-
- @api.model
def setting_init_bank_account_action(self):
""" Called by the 'Bank Accounts' button of the setup bar."""
view_id = self.env.ref('account.setup_bank_account_wizard').id
@@ -308,7 +306,7 @@ Best Regards,'''))
def setting_chart_of_accounts_action(self):
""" Called by the 'Chart of Accounts' button of the setup bar."""
company = self.env.user.company_id
- company.account_setup_coa_done = True
+ company.set_onboarding_step_done('account_setup_coa_state')
# If an opening move has already been posted, we open the tree view showing all the accounts
if company.opening_move_posted():
@@ -333,11 +331,6 @@ Best Regards,'''))
}
@api.model
- def setting_hide_setup_bar(self):
- """ Called by the cross button of the setup bar, to close it."""
- self.env.user.company_id.account_setup_bar_closed = True
-
- @api.model
def create_op_move_if_non_existant(self):
""" Creates an empty opening move in 'draft' state for the current company
if there wasn't already one defined. For this, the function needs at least
@@ -356,14 +349,6 @@ Best Regards,'''))
'journal_id': default_journal.id,
})
- def mark_company_setup_as_done_action(self):
- """ Marks the 'company' setup step as completed."""
- self.account_setup_company_data_done = True
-
- def unmark_company_setup_as_done_action(self):
- """ Marks the 'company' setup step as uncompleted."""
- self.account_setup_company_data_done = False
-
def opening_move_posted(self):
""" Returns true if this company has an opening account move and this move is posted."""
return bool(self.account_opening_move_id) and self.account_opening_move_id.state == 'posted'
@@ -430,36 +415,15 @@ Best Regards,'''))
'credit': debit_diff,
})
- @api.depends('logo', 'account_invoice_onboarding_closed')
- def _compute_account_onboarding_invoice_layout_done(self):
- """ The invoice onboarding step is marked as done if logo is filled
- and different from the default one. """
- for record in self:
- record.account_onboarding_invoice_layout_done = \
- record.account_invoice_onboarding_closed or (
- bool(record.logo) and record.logo != record._get_logo())
-
- @api.model
- def action_toggle_fold_account_invoice_onboarding(self):
- """ Toggle the onboarding panel `folded` state. """
- self.env.user.company_id.account_invoice_onboarding_folded =\
- not self.env.user.company_id.account_invoice_onboarding_folded
-
@api.model
def action_close_account_invoice_onboarding(self):
- """ Mark the onboarding panel as closed. """
- self.env.user.company_id.account_invoice_onboarding_closed = True
-
- @api.model
- def action_toggle_fold_account_dashboard_onboarding(self):
- """ Toggle the dashboard onboarding panel `folded` state. """
- self.env.user.company_id.account_dashboard_onboarding_folded =\
- not self.env.user.company_id.account_dashboard_onboarding_folded
+ """ Mark the invoice onboarding panel as closed. """
+ self.env.user.company_id.account_invoice_onboarding_state = 'closed'
@api.model
def action_close_account_dashboard_onboarding(self):
""" Mark the dashboard onboarding panel as closed. """
- self.env.user.company_id.account_dashboard_onboarding_closed = True
+ self.env.user.company_id.account_dashboard_onboarding_state = 'closed'
@api.model
def action_open_account_onboarding_invoice_layout(self):
@@ -469,6 +433,13 @@ Best Regards,'''))
return action
@api.model
+ def action_open_account_onboarding_sale_tax(self):
+ """ Onboarding step for the invoice layout. """
+ action = self.env.ref('account.action_open_account_onboarding_sale_tax').read()[0]
+ action['res_id'] = self.env.user.company_id.id
+ return action
+
+ @api.model
def _get_sample_invoice(self):
""" Get a sample invoice or create one if it does not exist. """
# use current user as partner
@@ -482,13 +453,7 @@ Best Regards,'''))
if len(sample_invoice) == 0:
# If there are no existing accounts or no journal, fail
- account = self.env['account.account'].search([('company_id', '=', company_id)], limit=1)
- if len(account) == 0:
- action = self.env.ref('account.action_account_config')
- msg = _(
- "We cannot find a chart of accounts for this company, you should configure it. \n"
- "Please go to Account Configuration and select or install a fiscal localization.")
- raise RedirectWarning(msg, action.id, _("Go to the configuration panel"))
+ account = self.env.user.company_id.get_chart_of_accounts_or_fail()
journal = self.env['account.journal'].search([('company_id', '=', company_id)], limit=1)
if len(journal) == 0:
@@ -537,3 +502,24 @@ Best Regards,'''))
'force_email': True,
}
return action
+
+ @api.multi
+ def action_save_onboarding_invoice_layout(self):
+ """ Set the onboarding step as done """
+ if bool(self.logo) and self.logo != self._get_logo():
+ self.set_onboarding_step_done('account_onboarding_invoice_layout_state')
+
+ @api.multi
+ def action_save_onboarding_sale_tax(self):
+ """ Set the onboarding step as done """
+ self.set_onboarding_step_done('account_onboarding_sale_tax_state')
+
+ def get_chart_of_accounts_or_fail(self):
+ account = self.env['account.account'].search([('company_id', '=', self.id)], limit=1)
+ if len(account) == 0:
+ action = self.env.ref('account.action_account_config')
+ msg = _(
+ "We cannot find a chart of accounts for this company, you should configure it. \n"
+ "Please go to Account Configuration and select or install a fiscal localization.")
+ raise RedirectWarning(msg, action.id, _("Go to the configuration panel"))
+ return account
diff --git a/addons/account/models/res_config_settings.py b/addons/account/models/res_config_settings.py
index 481e9af3218..d9e08ca9bbf 100644
--- a/addons/account/models/res_config_settings.py
+++ b/addons/account/models/res_config_settings.py
@@ -74,7 +74,6 @@ class ResConfigSettings(models.TransientModel):
module_account_taxcloud = fields.Boolean(string="Account TaxCloud")
tax_exigibility = fields.Boolean(string='Cash Basis', related='company_id.tax_exigibility')
tax_cash_basis_journal_id = fields.Many2one('account.journal', related='company_id.tax_cash_basis_journal_id', string="Tax Cash Basis Journal")
- account_hide_setup_bar = fields.Boolean(string='Hide Setup Bar', related='company_id.account_setup_bar_closed',help="Tick if you wish to hide the setup bar on the dashboard")
invoice_reference_type = fields.Selection(string='Communication',
related='company_id.invoice_reference_type', help='Default Reference Type on Invoices.')
account_bank_reconciliation_start = fields.Date(string="Bank Reconciliation Threshold",
diff --git a/addons/account/static/src/js/account_dashboard_setup_bar.js b/addons/account/static/src/js/account_dashboard_setup_bar.js
index 17aa1bad174..e69de29bb2d 100644
--- a/addons/account/static/src/js/account_dashboard_setup_bar.js
+++ b/addons/account/static/src/js/account_dashboard_setup_bar.js
@@ -1,235 +0,0 @@
-odoo.define('account.dashboard_setup_bar', function (require) {
-"use strict";
-
-var core = require('web.core');
-var field_utils = require('web.field_utils');
-var KanbanView = require('web.KanbanView');
-var KanbanModel = require('web.KanbanModel');
-var KanbanRenderer = require('web.KanbanRenderer');
-var KanbanController = require('web.KanbanController');
-var session = require('web.session');
-var view_registry = require('web.view_registry');
-
-var QWeb = core.qweb;
-var _t = core._t;
-var _lt = core._lt;
-
-var COMPANY_METHOD_TYPE = "company_object";
-
-var AccountSetupBarRenderer = KanbanRenderer.extend({
- events: _.extend({}, KanbanRenderer.prototype.events, {
- 'click .account_setup_dashboard_action': 'onActionClicked',
- }),
-
- //--------------------------------------------------------------------------
- // Private
- //--------------------------------------------------------------------------
-
- /**
- * Notifies the controller that the target has changed.
- *
- * @private
- * @param {string} target_name the name of the changed target
- * @param {string} value the new value
- */
- _notifyTargetChange: function (target_name, value) {
- this.trigger_up('dashboard_edit_target', {
- target_name: target_name,
- target_value: value,
- });
- },
- /**
- * @override
- * @private
- * @returns {Deferred}
- */
- _render: function () {
- var self = this;
-
- return this._super.apply(this, arguments).then(function () {
- var values = self.state.dashboardValues;
- var account_dashboard = QWeb.render('account.AccountDashboardSetupBar', {
- widget: self,
- values: values,
- });
- self.$el.prepend(account_dashboard);
- });
- },
-
- //--------------------------------------------------------------------------
- // Handlers
- //--------------------------------------------------------------------------
-
- /**
- * @private
- * @param {MouseEvent}
- */
- onActionClicked: function(e) {
- e.preventDefault();
- var self = this;
- var $action = $(e.currentTarget);
- var name_attr = $action.attr('name');
- var type_attr = $action.attr('type');
- var action_context = $action.data('context');
-
- if(type_attr == COMPANY_METHOD_TYPE) {
- self.trigger_up('company_button_action', {rpc_method: name_attr, context: action_context})
- }
- },
-});
-
-var AccountSetupBarModel = KanbanModel.extend({
- //--------------------------------------------------------------------------
- // Public
- //--------------------------------------------------------------------------
-
- /**
- * @override
- */
- init: function () {
- this.dashboardValues = {};
- this._super.apply(this, arguments);
- },
-
- /**
- * @override
- */
- get: function (localID) {
- var result = this._super.apply(this, arguments);
- if (this.dashboardValues[localID]) {
- result.dashboardValues = this.dashboardValues[localID];
- }
- return result;
- },
-
-
- /**
- * @œverride
- * @returns {Deferred}
- */
- load: function () {
- return this._loadDashboard(this._super.apply(this, arguments));
- },
- /**
- * @œverride
- * @returns {Deferred}
- */
- reload: function () {
- return this._loadDashboard(this._super.apply(this, arguments));
- },
-
- //--------------------------------------------------------------------------
- // Private
- //--------------------------------------------------------------------------
-
- /**
- * @abstract
- * @returns {Deferred<Object>} resolves to the required dashboard data
- */
- _fetchDashboardData: function () {
- return $.when(this._rpc({
- model: 'account.journal',
- method: 'retrieve_account_dashboard_setup_bar',
- args: [],
- }));
- },
- /**
- * @private
- * @param {Deferred} super_def a deferred that resolves with a dataPoint id
- * @returns {Deferred<string>} resolves to the dataPoint id
- */
- _loadDashboard: function (super_def) {
- var self = this;
- var dashboard_def = this._fetchDashboardData();
- return $.when(super_def, dashboard_def).then(function (id, dashboardValues) {
- self.dashboardValues[id] = dashboardValues;
- return id;
- });
- },
-});
-
-var AccountSetupBarController = KanbanController.extend({
- /* The company_button_action action allows the buttons of the setup bar to
- * trigger Python code defined in api.model functions in res.company model,
- * and to execute the action returned them.
- * It uses the 'type' attributes on buttons : if 'company_object', it will
- * run Python function 'name' of company model.
- */
- custom_events: _.extend({}, KanbanController.prototype.custom_events, {
- dashboard_open_action: '_onDashboardOpenAction',
- company_button_action: '_triggerCompanyButtonAction',
- }),
-
- start: function () {
- this._super();
- var self = this;
- core.bus.on('refresh_account_dashboard', this, function (){
- self.trigger_up('reload')
- });
- },
-
- //--------------------------------------------------------------------------
- // Handlers
- //--------------------------------------------------------------------------
-
- /**
- * @private
- * @param {OdooEvent} e
- */
- _onDashboardOpenAction: function (e) {
- var action_name = e.data.action_name;
- var action_context = e.data.action_context;
- return this.do_action(action_name, {
- additional_context: action_context,
- });
- },
-
- /**
- * Manages the clicks on the setup bar buttons.
- **/
- _triggerCompanyButtonAction: function (odooEvent) {
- var self = this
- if (odooEvent.data.rpc_method !== undefined) {
- self._rpc({
- model: 'res.company',
- method: odooEvent.data.rpc_method,
- args: [],
- })
- .then(
- function(rslt_action) {
- if (rslt_action !== undefined) {
- self.do_action(rslt_action, {
- action_context: odooEvent.data.context,
- on_close: function () {
- self.trigger_up('reload'); //Reloads the dashboard to refresh the status of the setup bar.
- },
- });
- }
- else { //Happens for any button not returning anything, like the cross to close the setup bar, for example.
- self.trigger_up('reload');
- }
- });
- }
- }
-});
-
-var AccountDashboardView = KanbanView.extend({
- config: _.extend({}, KanbanView.prototype.config, {
- Model: AccountSetupBarModel,
- Renderer: AccountSetupBarRenderer,
- Controller: AccountSetupBarController,
- }),
- display_name: _lt('Dashboard'),
- icon: 'fa-dashboard',
- searchview_hidden: false,
-});
-
-view_registry.add('account_setup_bar', AccountDashboardView);
-
-return {
- Model: AccountSetupBarModel,
- Renderer: AccountSetupBarRenderer,
- Controller: AccountSetupBarController,
-};
-
-});
diff --git a/addons/account/static/src/xml/account_dashboard_setup_bar.xml b/addons/account/static/src/xml/account_dashboard_setup_bar.xml
deleted file mode 100644
index a3e8600b894..00000000000
--- a/addons/account/static/src/xml/account_dashboard_setup_bar.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<templates>
- <!-- This template defines the setup bar, at the top of account module's dashboard -->
- <t t-name="account.AccountDashboardSetupBar">
- <div class="o_account_dashboard_header d-none d-md-block o_form_view" t-if="values['show_setup_bar']">
- <div class="o_form_statusbar">
- <div class="o_statusbar_status" data-original-title="" title="" >
- <button name="setting_chart_of_accounts_action" type="company_object" t-attf-class="btn o_arrow_button btn-secondary account_setup_dashboard_action #{values['chart_of_accounts'] and 'o_action_done' or ''}" >
- <i class="fa fa-check" t-if="values['chart_of_accounts']" role="img" aria-label="Current state" title="Current state" aria-current="step"/>
- <b class="o_account_dashboard_index">4</b>
- Chart of Accounts
- </button>
- <button name="setting_init_fiscal_year_action" type="company_object" t-attf-class="btn o_arrow_button btn-secondary account_setup_dashboard_action #{values['fiscal_year'] and 'o_action_done' or ''}">
- <i class="fa fa-check" t-if="values['fiscal_year']" role="img" aria-label="Current state" title="Current state" aria-current="step"/>
- <b class="o_account_dashboard_index">3</b>
- Fiscal Year
- </button>
- <button name="setting_init_bank_account_action" type="company_object" t-attf-class="btn o_arrow_button btn-secondary account_setup_dashboard_action #{values['bank'] and 'o_action_done' or ''}">
- <i class="fa fa-check" t-if="values['bank']" role="img" aria-label="Current state" title="Current state" aria-current="step"/>
- <b class="o_account_dashboard_index">2</b>
- Add a Bank Account
- </button>
- <button name="setting_init_company_action" type="company_object" t-attf-class="btn o_arrow_button btn-secondary account_setup_dashboard_action #{values['company'] and 'o_action_done' or ''}">
- <i class="fa fa-check" t-if="values['company']" role="img" aria-label="Current state" title="Current state" aria-current="step"/>
- <b class="o_account_dashboard_index">1</b>
- Company Data
- </button>
-
- <h4 class="text-muted">Configuration Steps</h4>
- </div>
- <div class="float-right" style="padding: 7px 0;">
- <button aria-label="Hide setup bar" data-dismiss="modal" type="company_object" name="setting_hide_setup_bar" class="account_setup_dashboard_action close">×</button>
- </div>
- </div>
- </div>
- </t>
-</templates>
diff --git a/addons/account/static/tests/account_dashboard_setup_bar_tests.js b/addons/account/static/tests/account_dashboard_setup_bar_tests.js
index 4729467a13d..e69de29bb2d 100644
--- a/addons/account/static/tests/account_dashboard_setup_bar_tests.js
+++ b/addons/account/static/tests/account_dashboard_setup_bar_tests.js
@@ -1,65 +0,0 @@
-odoo.define('account.setup_bar_tests', function (require) {
-"use strict";
-
-var testUtils = require('web.test_utils');
-var view_registry = require('web.view_registry');
-
-var createView = testUtils.createView;
-
-QUnit.module('Views', {}, function () {
-
-QUnit.module('Account Dashboard Setup Bar', {
- beforeEach: function() {
- this.data = {
- partner: {
- fields: {
- foo: {string: "Foo", type: "char"},
- },
- records: [
- {id: 1, foo: "yop"},
- {id: 2, foo: "blip"},
- {id: 3, foo: "gnap"},
- {id: 4, foo: "blip"},
- ]
- },
- };
- this.dashboard_data = {
- show_setup_bar: true,
- company: false,
- bank: false,
- fiscal_year: false,
- chart_of_accounts: false,
- initial_balance: false,
- };
- }
-});
-
-QUnit.test('setup bar basic rendering', function(assert) {
- assert.expect(2);
-
- var dashboard_data = this.dashboard_data;
- var kanban = createView({
- View: view_registry.get('account_setup_bar'),
- model: 'partner',
- data: this.data,
- arch: '<kanban class="o_kanban_test">' +
- '<templates><t t-name="kanban-box">' +
- '<div><field name="foo"/></div>' +
- '</t></templates>' +
- '</kanban>',
- mockRPC: function(route, args) {
- if (args.method === 'retrieve_account_dashboard_setup_bar') {
- assert.ok(true, "should call /retrieve_account_dashboard_setup_bar");
- return $.when(dashboard_data);
- }
- return this._super(route, args);
- },
- });
-
- assert.strictEqual(kanban.$('.o_account_dashboard_header').length, 1, "should render the setup bar");
- kanban.destroy();
-});
-
-});
-
-});
diff --git a/addons/account/views/account.xml b/addons/account/views/account.xml
index 70d525890d1..348e6fdeec2 100644
--- a/addons/account/views/account.xml
+++ b/addons/account/views/account.xml
@@ -22,7 +22,6 @@
<script type="text/javascript" src="/account/static/src/js/reconciliation/tour_reconciliation.js"></script>
<script type="text/javascript" src="/account/static/src/js/account_payment_field.js"></script>
- <script type="text/javascript" src="/account/static/src/js/account_dashboard_setup_bar.js"></script>
<script type="text/javascript" src="/account/static/src/js/section_and_note_fields_backend.js"></script>
<script type="text/javascript" src="/account/static/src/js/tour.js"></script>
diff --git a/addons/account/views/account_onboarding_templates.xml b/addons/account/views/account_onboarding_templates.xml
index 682da061ae0..47150b860ce 100644
--- a/addons/account/views/account_onboarding_templates.xml
+++ b/addons/account/views/account_onboarding_templates.xml
@@ -4,49 +4,69 @@
<template id="onboarding_invoice_layout_step">
<t t-call="base.onboarding_step">
<t t-set="title">Invoice Layout</t>
- <t t-set="description">Create and send professional looking invoices.</t>
+ <t t-set="description">Customize the look of your invoices.</t>
<t t-set="done_icon" t-value="'fa-star'" />
+ <t t-set="btn_text">Customize</t>
<t t-set="done_text">Looks great!</t>
<t t-set="method" t-value="'action_open_account_onboarding_invoice_layout'" />
<t t-set="model" t-value="'res.company'" />
- <t t-set="done" t-value="company.account_onboarding_invoice_layout_done" />
+ <t t-set="state" t-value="state.get('account_onboarding_invoice_layout_state')" />
</t>
</template>
<template id="onboarding_sample_invoice_step">
<t t-call="base.onboarding_step">
<t t-set="title">Sample Invoice</t>
- <t t-set="description">Quickly preview what your client sees by sending a sample invoice
- to yourself.
+ <t t-set="description">
+ Send an invoice to test the customer portal.
</t>
- <t t-set="btn_text">I'm ready</t>
+ <t t-set="btn_text">Send Sample</t>
<t t-set="done_text">Sample invoice sent!</t>
<t t-set="method" t-value="'action_open_account_onboarding_sample_invoice'" />
<t t-set="model" t-value="'res.company'" />
- <t t-set="done" t-value="company.account_onboarding_sample_invoice_sent" />
+ <t t-set="state" t-value="state.get('account_onboarding_sample_invoice_state')" />
+ </t>
+ </template>
+ <template id="onboarding_bank_account_step">
+ <t t-call="base.onboarding_step">
+ <t t-set="title">Bank Account</t>
+ <t t-set="description">Setup your bank account to sync bank feeds.</t>
+ <t t-set="btn_text">Add a bank</t>
+ <t t-set="done_text">Step Completed!</t>
+ <t t-set="method" t-value="'setting_init_bank_account_action'" />
+ <t t-set="model" t-value="'res.company'" />
+ <t t-set="state" t-value="state.get('account_setup_bank_data_state')" />
</t>
</template>
<template id="onboarding_fiscal_year_step">
<t t-call="base.onboarding_step">
<t t-set="title">Fiscal Year</t>
- <t t-set="description">Set the closing date of your legal reports.</t>
- <t t-set="btn_text">I'm ready</t>
+ <t t-set="description">Define your fiscal years opening &amp; closing dates.</t>
+ <t t-set="btn_text">Configure</t>
<t t-set="done_text">Step Completed!</t>
<t t-set="method" t-value="'setting_init_fiscal_year_action'" />
<t t-set="model" t-value="'res.company'" />
- <t t-set="done" t-value="company.account_setup_fy_data_done" />
+ <t t-set="state" t-value="state.get('account_setup_fy_data_state')" />
</t>
</template>
<template id="onboarding_chart_of_account_step">
<t t-call="base.onboarding_step">
<t t-set="title">Chart of Accounts</t>
- <t t-set="description">Setup your chart of accounts and enter the initial balances.</t>
- <t t-set="btn_text">I'm ready</t>
+ <t t-set="description">Setup your chart of accounts and record initial balances.</t>
+ <t t-set="btn_text">Review</t>
<t t-set="done_text">Chart of account set.</t>
<t t-set="method" t-value="'setting_chart_of_accounts_action'" />
<t t-set="model" t-value="'res.company'" />
- <t t-set="done" t-value="company.account_setup_coa_done" />
+ <t t-set="state" t-value="state.get('account_setup_coa_state')" />
</t>
</template>
+ <template id="dashboard_onboarding_company_step" primary="True"
+ inherit_id="base.onboarding_company_step">
+ <xpath expr="//t[@t-set='description']" position="replace">
+ <t t-set="description">
+ Setup your company's data for reports headers.
+ </t>
+ </xpath>
+ </template>
<!-- ONBOARDING PANELS -->
<template id="account_invoice_onboarding_panel" name="account.invoice.onboarding.panel">
<t t-call="base.onboarding_container">
@@ -54,9 +74,8 @@
<t t-set="bg_image">/account/static/src/img/account_invoice_onboarding_bg.jpg</t>
<t t-set="close_method">action_close_account_invoice_onboarding</t>
<t t-set="close_model">res.company</t>
- <t t-set="fold_method">action_toggle_fold_account_invoice_onboarding</t>
- <t t-set="fold_model">res.company</t>
- <t t-set="folded_by_default" t-value="company.account_invoice_onboarding_folded" />
+ <t t-set="text_completed">Congratulations! You are all set. You can now issue real invoices to your customers.</t>
+
<t t-call="base.onboarding_company_step" name="company_step" />
<t t-call="account.onboarding_invoice_layout_step" name="invoice_layout_step" />
<t t-call="account.onboarding_sample_invoice_step" name="sample_invoice_step" />
@@ -68,22 +87,33 @@
<t t-set="bg_image">/account/static/src/img/account_dashboard_onboarding_bg.jpg</t>
<t t-set="close_method">action_close_account_dashboard_onboarding</t>
<t t-set="close_model">res.company</t>
- <t t-set="fold_method">action_toggle_fold_account_dashboard_onboarding</t>
- <t t-set="fold_model">res.company</t>
- <t t-set="folded_by_default" t-value="company.account_dashboard_onboarding_folded" />
- <t t-call="base.onboarding_company_step" name="company_step" />
+
+ <t t-call="account.dashboard_onboarding_company_step" name="company_step" />
+ <t t-call="account.onboarding_bank_account_step" name="bank_account_step" />
<t t-call="account.onboarding_fiscal_year_step" name="fiscal_year_step" />
<t t-call="account.onboarding_chart_of_account_step" name="chart_of_account_step" />
</t>
</template>
<!-- INVOICE FORM -->
+ <record id="account_invoice_onboarding_invoice_layout_form" model="ir.ui.view">
+ <field name="name">account.invoice.layout.onboarding.form</field>
+ <field name="model">res.company</field>
+ <field name="inherit_id" ref="base.view_company_document_template_form" />
+ <field name="mode">primary</field>
+ <field name="priority">1000</field>
+ <field name="arch" type="xml">
+ <xpath expr="//button[@special='save']" position="replace">
+ <button string="Apply" class="btn btn-primary" type="object" name="action_save_onboarding_invoice_layout" />
+ </xpath>
+ </field>
+ </record>
<record id="action_open_account_onboarding_invoice_layout" model="ir.actions.act_window">
- <field name="name">Configure your document template</field>
+ <field name="name">Configure your document layout</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">res.company</field>
<field name="view_mode">form</field>
<field name="view_type">form</field>
- <field name="view_id" ref="base.view_company_document_template_form" />
+ <field name="view_id" ref="account_invoice_onboarding_invoice_layout_form" />
<field name="target">new</field>
</record>
<!-- SAMPLE INVOICE EMAIL -->
@@ -115,4 +145,42 @@
<field name="view_id" ref="email_compose_onboarding_sample_invoice" />
<field name="target">new</field>
</record>
+ <!-- SALE TAX -->
+ <template id="onboarding_sale_tax_step">
+ <t t-call="base.onboarding_step">
+ <t t-set="title">Taxes</t>
+ <t t-set="description">Choose a default tax.</t>
+ <t t-set="btn_text">I'm ready</t>
+ <t t-set="done_text">Step Completed!</t>
+ <t t-set="method" t-value="'action_open_account_onboarding_sale_tax'" />
+ <t t-set="model" t-value="'res.company'" />
+ <t t-set="state" t-value="state.get('account_onboarding_sale_tax_state')" />
+ </t>
+ </template>
+ <record id="account_invoice_onboarding_sale_tax_form" model="ir.ui.view">
+ <field name="name">account.invoice.layout.onboarding.form</field>
+ <field name="model">res.company</field>
+ <field name="mode">primary</field>
+ <field name="priority">1000</field>
+ <field name="arch" type="xml">
+ <form>
+ <div>Choose a default sales tax for your products.</div>
+ <label for="account_sale_tax_id" string="Sales tax"/>
+ <field name="account_sale_tax_id" />
+ <footer>
+ <button string="Apply" class="btn btn-primary" type="object" name="action_save_onboarding_sale_tax" />
+ <button string="Cancel" class="btn-secondary" special="cancel" />
+ </footer>
+ </form>
+ </field>
+ </record>
+ <record id="action_open_account_onboarding_sale_tax" model="ir.actions.act_window">
+ <field name="name">Sales tax</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">res.company</field>
+ <field name="view_mode">form</field>
+ <field name="view_type">form</field>
+ <field name="view_id" ref="account_invoice_onboarding_sale_tax_form" />
+ <field name="target">new</field>
+ </record>
</odoo>
diff --git a/addons/account/views/res_config_settings_views.xml b/addons/account/views/res_config_settings_views.xml
index c0df8501892..ffe56968f14 100644
--- a/addons/account/views/res_config_settings_views.xml
+++ b/addons/account/views/res_config_settings_views.xml
@@ -44,18 +44,6 @@
<t groups="account.group_account_user">
<h2>Setup</h2>
<div class="row mt16 o_settings_container" id="setup">
- <div class="col-12 col-lg-6 o_setting_box">
- <div class="o_setting_left_pane">
- <field name="account_hide_setup_bar" widget="upgrade_boolean"/>
- </div>
- <div class="o_setting_right_pane">
- <label for="account_hide_setup_bar" string='Hide the Configuration Steps bar'/>
- <div class="text-muted">
- Deactivate the "Configuration Steps" bar on the dashboard
- </div>
- </div>
- </div>
-
<div class="col-xs-12 col-md-6 o_setting_box">
<div class="o_setting_left_pane"/>
<div class="o_setting_right_pane">
diff --git a/addons/account/wizard/setup_wizards.py b/addons/account/wizard/setup_wizards.py
index 407a4b45e27..0c0d9fe43df 100644
--- a/addons/account/wizard/setup_wizards.py
+++ b/addons/account/wizard/setup_wizards.py
@@ -16,12 +16,6 @@ class FinancialYearOpeningWizard(models.TransientModel):
related="company_id.fiscalyear_last_month",
required=True,
help="The last day of the month will be taken if the chosen day doesn't exist.")
- account_setup_fy_data_done = fields.Boolean(string='Financial year setup marked as done', compute="_compute_setup_marked_done")
-
- @api.depends('company_id.account_setup_fy_data_done')
- def _compute_setup_marked_done(self):
- for record in self:
- record.account_setup_fy_data_done = record.company_id.account_setup_fy_data_done
@api.depends('company_id.account_opening_move_id')
def _compute_opening_move_posted(self):
@@ -41,7 +35,7 @@ class FinancialYearOpeningWizard(models.TransientModel):
@api.multi
def action_save_onboarding_fiscal_year(self):
- self.env.user.company_id.account_setup_fy_data_done = True
+ self.env.user.company_id.set_onboarding_step_done('account_setup_fy_data_state')
class SetupBarBankConfigWizard(models.TransientModel):
diff --git a/addons/account/wizard/setup_wizards_view.xml b/addons/account/wizard/setup_wizards_view.xml
index fa3c70e0c02..1c9e21c8592 100644
--- a/addons/account/wizard/setup_wizards_view.xml
+++ b/addons/account/wizard/setup_wizards_view.xml
@@ -2,26 +2,6 @@
<odoo>
<data>
-
- <record id="setup_view_company_form" model="ir.ui.view">
- <field name="name">account.setup.company.form</field>
- <field name="model">res.company</field>
- <field name="inherit_id" ref="base.view_company_form"/>
- <field name="mode">primary</field>
- <field name="priority">42000</field>
- <field name="arch" type="xml">
- <xpath expr="//form/sheet" position="after">
- <footer>
- <field name="account_setup_company_data_done" invisible="True"/>
- <button string="Mark as done" type="object" name="mark_company_setup_as_done_action" class="oe_highlight" attrs="{'invisible': [('account_setup_company_data_done','=',True)]}"/>
- <button string="Save" type="action" name="account.setup_wizard_close" attrs="{'invisible': [('account_setup_company_data_done','=',True)]}"/>
- <button string="Save" type="action" name="account.setup_wizard_close" class="oe_highlight" attrs="{'invisible': [('account_setup_company_data_done','=',False)]}"/>
- <button string="Unmark as done" type="object" name="unmark_company_setup_as_done_action" attrs="{'invisible': [('account_setup_company_data_done','=',False)]}"/>
- </footer>
- </xpath>
- </field>
- </record>
-
<record id="setup_financial_year_opening_form" model="ir.ui.view">
<field name="name">account.financial.year.op.setup.wizard.form</field>
<field name="model">account.financial.year.op</field>
@@ -49,7 +29,7 @@
</div>
</div>
<footer>
- <button name="action_save_onboarding_fiscal_year" string="OK"
+ <button name="action_save_onboarding_fiscal_year" string="Apply"
class="oe_highlight" type="object" />
<button special="cancel" string="Cancel" />
</footer>
@@ -110,9 +90,5 @@
</field>
</record>
- <record id="setup_wizard_close" model="ir.actions.act_window_close">
- <field name="name">Close setup wizards</field>
- </record>
-
</data>
</odoo>
diff --git a/addons/base_setup/models/res_config_settings.py b/addons/base_setup/models/res_config_settings.py
index a2d4c5a4511..3e548b015e2 100644
--- a/addons/base_setup/models/res_config_settings.py
+++ b/addons/base_setup/models/res_config_settings.py
@@ -39,7 +39,7 @@ class ResConfigSettings(models.TransientModel):
group_multi_currency = fields.Boolean(string='Multi-Currencies',
implied_group='base.group_multi_currency',
help="Allows to work in a multi currency environment")
- paperformat_id = fields.Many2one(related="company_id.paperformat_id", string='Paper format')
+ paperformat_id = fields.Many2one(related="company_id.paperformat_id", string='Paper Format')
external_report_layout = fields.Selection(related="company_id.external_report_layout")
show_effect = fields.Boolean(string="Show Effect", config_parameter='base_setup.show_effect')
diff --git a/addons/base_vat/views/res_company_views.xml b/addons/base_vat/views/res_company_views.xml
index bf85b2b7f88..f4af1016a00 100644
--- a/addons/base_vat/views/res_company_views.xml
+++ b/addons/base_vat/views/res_company_views.xml
@@ -5,9 +5,6 @@
<field name="model">res.company</field>
<field name="inherit_id" ref="base.view_company_form"/>
<field name="arch" type="xml">
- <field name="parent_id" position="after">
- <field name="vat_check_vies" help="If this checkbox is ticked, you will not be able to save a contact if its VAT number cannot be verified by the European VIES service." />
- </field>
<xpath expr="//field[@name='vat']" position="attributes">
<attribute name="string">VAT</attribute>
</xpath>
diff --git a/addons/payment/models/res_company.py b/addons/payment/models/res_company.py
index c2b52486563..277c44f06b1 100644
--- a/addons/payment/models/res_company.py
+++ b/addons/payment/models/res_company.py
@@ -1,15 +1,30 @@
-from odoo import _, api, fields, models
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo import api, fields, models
class ResCompany(models.Model):
_inherit = 'res.company'
- # Step is marked as done if one payment module is installed or
- # `custom` payment has been changed or `skip this step` has been clicked
- payment_acquirer_onboarding_done = fields.Boolean('Payment acquirer onboarding done', default=False)
+ payment_acquirer_onboarding_state = fields.Selection([('not_done', "Not done"), ('just_done', "Just done"), ('done', "Done")], string="State of the onboarding payment acquirer step", default='not_done')
+ # YTI FIXME: Check if it's really needed on the company. Should be enough on the wizard
+ payment_onboarding_payment_method = fields.Selection([
+ ('paypal', "PayPal"),
+ ('stripe', "Stripe"),
+ ('manual', "Manual"),
+ ], string="Selected onboarding payment method")
@api.model
def action_open_payment_onboarding_payment_acquirer(self):
""" Called by onboarding panel above the customer invoice list."""
+ # Fail if there are no existing accounts
+ self.env.user.company_id.get_chart_of_accounts_or_fail()
+
action = self.env.ref('payment.action_open_payment_onboarding_payment_acquirer_wizard').read()[0]
return action
+
+ def get_account_invoice_onboarding_steps_states_names(self):
+ """ Override. """
+ steps = super(ResCompany, self).get_account_invoice_onboarding_steps_states_names()
+ return steps + ['payment_acquirer_onboarding_state']
diff --git a/addons/payment/views/payment_acquirer_onboarding_templates.xml b/addons/payment/views/payment_acquirer_onboarding_templates.xml
index 011344f6c30..3c2d0b96fef 100644
--- a/addons/payment/views/payment_acquirer_onboarding_templates.xml
+++ b/addons/payment/views/payment_acquirer_onboarding_templates.xml
@@ -4,12 +4,12 @@
<template id="onboarding_payment_acquirer_step">
<t t-call="base.onboarding_step">
<t t-set="title">Payment Method</t>
- <t t-set="description">Choose the payment methods to collect payments on your invoices.</t>
+ <t t-set="description">Configure your payment methods.</t>
+ <t t-set="btn_text">Set Payments</t>
<t t-set="done_text">Payment method set!</t>
<t t-set="method" t-value="'action_open_payment_onboarding_payment_acquirer'" />
<t t-set="model" t-value="'res.company'" />
- <t t-set="id" t-value="company.id" />
- <t t-set="done" t-value="company.payment_acquirer_onboarding_done" />
+ <t t-set="state" t-value="state.get('payment_acquirer_onboarding_state')" />
</t>
</template>
<!-- add it in the account invoice onboarding panel -->
@@ -25,98 +25,67 @@
<field name="name">payment.acquirer.onboarding.wizard.form</field>
<field name="model">payment.acquirer.onboarding.wizard</field>
<field name="arch" type="xml">
- <form string="Choose a payment method">
- <div class="mb16">
- Configure our recommended payment methods or
- <a type="action" role="button" name="payment.action_payment_acquirer">
- see all other available methods.
- </a>
- </div>
- <div class="row">
- <div class="col-1 mb16">
- <field name="paypal_checked" nolabel="1" />
- </div>
- <div>
- <label for="paypal_checked" />
- </div>
- </div>
- <div class="row">
- <div attrs="{'invisible': [('paypal_checked', '=', False)]}"
- class="offset-1">
- <a href="https://www.paypal.com" target="_blank">PayPal</a>
- is the easiest way to accept payments. It's easy to configure and it offers
- <a href="https://www.paypal.com/us/webapps/mpp/merchant-fees"
- target="_blank">
- a transparent fee structure.
- </a>
- <group>
- <field name="paypal_email_account"
- attrs="{'required': [('paypal_checked', '=', True)]}" />
- <field name="paypal_seller_account" />
- <field name="paypal_pdt_token"
- attrs="{'required': [('paypal_checked', '=', True)]}" />
- </group>
- <separator />
- </div>
- </div>
- <div class="row">
- <div class="col-1 mb16">
- <field name="stripe_checked" nolabel="1" />
- </div>
- <div>
- <label for="stripe_checked" />
- </div>
- </div>
- <div class="row">
- <div attrs="{'invisible': [('stripe_checked', '=', False)]}"
- class="offset-1">
- <a href="https://stripe.com" target="_blank">Stripe</a>
- is a payment provider with
- <a href="https://stripe.com/pricing" target="_blank">
- a simple fee structure and no hidden costs.
- </a>
- No other gateway or merchant account is required. We recommend this solution
- to manage credit card payments.
- <group>
- <field name="stripe_secret_key"
- attrs="{'required': [('stripe_checked', '=', True)]}" />
- <field name="stripe_publishable_key"
- attrs="{'required': [('stripe_checked', '=', True)]}" />
- <a href="https://dashboard.stripe.com/account/apikeys" target="_blank">
- <span class="fa fa-arrow-right">Get my Stripe keys</span>
- </a>
- </group>
- <separator />
- </div>
- </div>
- <div class="row">
- <div class="col-1">
- <field name="manual_checked" nolabel="1" />
- </div>
- <div>
- <label for="manual_checked" />
- </div>
- </div>
- <div class="row">
- <div attrs="{'invisible': [('manual_checked', '=', False)]}"
- class="offset-1">
- Provide customers with instructions to pay outside of your platform (wire
- transfer, cash on delivery, etc.).
- <group>
- <field name="manual_name"
- attrs="{'required': [('manual_checked', '=', True)]}" />
- <field name="manual_post_msg"
- attrs="{'required': [('manual_checked', '=', True)]}" />
- </group>
+ <form string="Choose a payment method" class="o_onboarding_payment_acquirer_wizard">
+ <div class="container">
+ <div class="row align-items-start">
+ <div class="col col-2" name="left-column">
+ <field name="payment_method" widget="radio"/>
+ </div>
+ <div class="col offset-md-1" name="right-column">
+ <div attrs="{'invisible': [('payment_method', '!=', 'paypal')]}">
+ <p>
+ <a href="https://www.paypal.com" target="_blank">PayPal</a>
+ is the easiest way to accept payments. It's easy to configure
+ and it offers
+ <a href="https://www.paypal.com/us/webapps/mpp/merchant-fees"
+ target="_blank">
+ a transparent fee structure.
+ </a>
+ </p>
+ <group>
+ <field name="paypal_email_account" attrs="{'required': [('payment_method', '=', 'paypal')]}" />
+ <field name="paypal_seller_account" attrs="{'required': [('payment_method', '=', 'paypal')]}" />
+ <field name="paypal_pdt_token" attrs="{'required': [('payment_method', '=', 'paypal')]}" />
+ </group>
+ <p>
+ <a href="https://www.paypal.com/ca/webapps/mpp/product-selection" target="_blank">
+ <span class="fa fa-arrow-right"> Create a PayPal Account</span>
+ </a>
+ </p>
+ </div>
+ <div attrs="{'invisible': [('payment_method', '!=', 'stripe')]}">
+ <p>
+ <a href="https://stripe.com" target="_blank">Stripe</a>
+ is a payment provider with-->
+ <a href="https://stripe.com/pricing" target="_blank">
+ a simple fee structure and no hidden costs.
+ </a>
+ We recommend it to manage credit card payments.
+ </p>
+ <group>
+ <field name="stripe_secret_key"
+ attrs="{'required': [('payment_method', '=', 'stripe')]}" />
+ <field name="stripe_publishable_key"
+ attrs="{'required': [('payment_method', '=', 'stripe')]}" />
+ </group>
+ <p>
+ <a href="https://dashboard.stripe.com/account/apikeys" target="_blank">
+ <span class="fa fa-arrow-right"> Get my Stripe keys</span>
+ </a>
+ </p>
+ </div>
+ <div attrs="{'invisible': [('payment_method', '!=', 'manual')]}">
+ <group>
+ <field name="journal_name" attrs="{'required': [('payment_method', '=', 'manual')]}"/>
+ <field name="acc_number" attrs="{'required': [('payment_method', '=', 'manual')]}"/>
+ <field name="manual_post_msg" attrs="{'required': [('payment_method', '=', 'manual')]}"/>
+ </group>
+ </div>
+ </div>
</div>
</div>
<footer>
- <div class="mb16" name="skip_step_text">
- You can skip this step if invoices are pre-paid.
- </div>
- <button name="add_payment_methods" string="OK" class="oe_highlight"
- type="object" />
- <button name="action_skip_payment_onboarding_payment_acquirer_step" string="Skip this step"
+ <button name="add_payment_methods" string="Apply" class="oe_highlight"
type="object" />
<button special="cancel" string="Cancel" />
</footer>
diff --git a/addons/payment/wizards/payment_acquirer_onboarding_wizard.py b/addons/payment/wizards/payment_acquirer_onboarding_wizard.py
index 679facc45a9..7523ec5c8d6 100644
--- a/addons/payment/wizards/payment_acquirer_onboarding_wizard.py
+++ b/addons/payment/wizards/payment_acquirer_onboarding_wizard.py
@@ -8,63 +8,70 @@ from odoo.exceptions import UserError
class PaymentWizard(models.TransientModel):
_name = 'payment.acquirer.onboarding.wizard'
- paypal_checked = fields.Boolean('Paypal', default=lambda self: self._get_default_payment_acquirer_onboarding_value('paypal_checked'))
- paypal_email_account = fields.Char('Paypal Email ID', default=lambda self: self._get_default_payment_acquirer_onboarding_value('paypal_email_account'))
- paypal_seller_account = fields.Char('Paypal Merchant ID', default=lambda self: self._get_default_payment_acquirer_onboarding_value('paypal_seller_account'))
- paypal_pdt_token = fields.Char('Paypal PDT Token', default=lambda self: self._get_default_payment_acquirer_onboarding_value('paypal_pdt_token'))
+ payment_method = fields.Selection([
+ ('paypal', "PayPal"),
+ ('stripe', "Credit Card (via Stripe)"),
+ ('manual', "Wire Transfer"),
+ ], string="Payment Method", default=lambda self: self._get_default_payment_acquirer_onboarding_value('payment_method'))
+
+ paypal_email_account = fields.Char("PayPal Email ID", default=lambda self: self._get_default_payment_acquirer_onboarding_value('paypal_email_account'))
+ paypal_seller_account = fields.Char("Paypal Merchant ID", default=lambda self: self._get_default_payment_acquirer_onboarding_value('paypal_seller_account'))
+ paypal_pdt_token = fields.Char("Paypal PDT Token", default=lambda self: self._get_default_payment_acquirer_onboarding_value('paypal_pdt_token'))
- stripe_checked = fields.Boolean('Credit Card (via Stripe)', default=lambda self: self._get_default_payment_acquirer_onboarding_value('stripe_checked'))
stripe_secret_key = fields.Char(default=lambda self: self._get_default_payment_acquirer_onboarding_value('stripe_secret_key'))
stripe_publishable_key = fields.Char(default=lambda self: self._get_default_payment_acquirer_onboarding_value('stripe_publishable_key'))
- manual_checked = fields.Boolean('Manual Payment', default=lambda self: self._get_default_payment_acquirer_onboarding_value('manual_checked'))
- manual_name = fields.Char('Method name', default=lambda self: self._get_default_payment_acquirer_onboarding_value('manual_name'))
- manual_post_msg = fields.Html('Payment instructions', default=lambda self: self._get_default_payment_acquirer_onboarding_value('manual_post_msg'))
+ journal_name = fields.Char("Journal Name", default=lambda self: self._get_default_payment_acquirer_onboarding_value('journal_name'))
+ acc_number = fields.Char("Account Number", default=lambda self: self._get_default_payment_acquirer_onboarding_value('acc_number'))
+ manual_post_msg = fields.Html("Payment instructions")
+
+ @api.onchange('journal_name', 'acc_number')
+ def _set_manual_post_msg_value(self):
+ self.manual_post_msg = _('Please make a payment to %s %s') % (self.journal_name or _("Bank") , self.acc_number or _("Account"))
_payment_acquirer_onboarding_cache = {}
_data_fetched = False
- def _get_manual_payment(self, env=None):
+ def _get_manual_payment_acquirer(self, env=None):
if env is None:
env = self.env
- return env['payment.acquirer'].search(
- [('provider', '=', 'transfer'),
- ('sequence', '=', 2),
- ('company_id', '=', self.env.user.company_id.id)], limit=1)
+ module_id = env.ref('base.module_payment_transfer').id
+ return env['payment.acquirer'].search([('module_id', '=', module_id),
+ ('company_id', '=', env.user.company_id.id)], limit=1)
def _get_default_payment_acquirer_onboarding_value(self, key):
if not self.env.user._is_admin():
- raise UserError(_('Only administators can access this data.'))
+ raise UserError(_("Only administrators can access this data."))
if self._data_fetched:
return self._payment_acquirer_onboarding_cache.get(key, '')
self._data_fetched = True
+ self._payment_acquirer_onboarding_cache['payment_method'] = self.env.user.company_id.payment_onboarding_payment_method
+
installed_modules = self.env['ir.module.module'].sudo().search([
('name', 'in', ('payment_paypal', 'payment_stripe')),
('state', '=', 'installed'),
]).mapped('name')
if 'payment_paypal' in installed_modules:
- self._payment_acquirer_onboarding_cache['paypal_checked'] = True
acquirer = self.env.ref('payment.payment_acquirer_paypal')
self._payment_acquirer_onboarding_cache['paypal_email_account'] = acquirer['paypal_email_account']
self._payment_acquirer_onboarding_cache['paypal_seller_account'] = acquirer['paypal_seller_account']
self._payment_acquirer_onboarding_cache['paypal_pdt_token'] = acquirer['paypal_pdt_token']
if 'payment_stripe' in installed_modules:
- self._payment_acquirer_onboarding_cache['stripe_checked'] = True
acquirer = self.env.ref('payment.payment_acquirer_stripe')
self._payment_acquirer_onboarding_cache['stripe_secret_key'] = acquirer['stripe_secret_key']
self._payment_acquirer_onboarding_cache['stripe_publishable_key'] = acquirer['stripe_publishable_key']
- manual_payment = self._get_manual_payment()
- # manual payment is checked if the user has renamed it
- self._payment_acquirer_onboarding_cache['manual_checked'] = \
- (manual_payment['name'] != 'Wire Transfer')
- self._payment_acquirer_onboarding_cache['manual_name'] = manual_payment['name']
+ manual_payment = self._get_manual_payment_acquirer()
+ journal = manual_payment.journal_id
+
self._payment_acquirer_onboarding_cache['manual_post_msg'] = manual_payment['post_msg']
+ self._payment_acquirer_onboarding_cache['journal_name'] = journal.name if journal.name != "Bank" else ""
+ self._payment_acquirer_onboarding_cache['acc_number'] = journal.bank_acc_number
return self._payment_acquirer_onboarding_cache.get(key, '')
@@ -73,55 +80,51 @@ class PaymentWizard(models.TransientModel):
if module.state not in ('installed', 'to install', 'to upgrade'):
module.button_immediate_install()
- def _hook_on_save_onboarding_payment_acquirer(self):
- # if any payment method is selected activate "Online Payment" in invoicing settings
- self._install_module('account_payment')
-
@api.multi
def add_payment_methods(self):
- if self.paypal_checked is True:
+ """ Install required payment acquiers, configure them and mark the
+ onboarding step as done."""
+
+ if self.payment_method == 'paypal':
self._install_module('payment_paypal')
- if self.stripe_checked is True:
+ if self.payment_method == 'stripe':
self._install_module('payment_stripe')
- if self.paypal_checked is True or self.stripe_checked is True or self.manual_checked is True:
+ if self.payment_method in ('paypal', 'stripe', 'manual'):
- # the wizard is inherited in `sale`
- self._hook_on_save_onboarding_payment_acquirer()
+ self.env.user.company_id.payment_onboarding_payment_method = self.payment_method
# create a new env including the freshly installed module(s)
new_env = api.Environment(self.env.cr, self.env.uid, self.env.context)
- if self.paypal_checked is True:
+ if self.payment_method == 'paypal':
new_env.ref('payment.payment_acquirer_paypal').write({
'paypal_email_account': self.paypal_email_account,
'paypal_seller_account': self.paypal_seller_account,
'paypal_pdt_token': self.paypal_pdt_token,
'website_published': True,
})
- if self.stripe_checked is True:
+ if self.payment_method == 'stripe':
new_env.ref('payment.payment_acquirer_stripe').write({
'stripe_secret_key': self.stripe_secret_key,
'stripe_publishable_key': self.stripe_publishable_key,
'website_published': True,
})
- if self.manual_checked is True:
- self._get_manual_payment(new_env).write({
- 'name': self.manual_name,
- 'post_msg': self.manual_post_msg,
- 'website_published': True,
- })
- self._set_payment_acquirer_onboarding_step_done()
- # delete wizard data immediately to get rid of residual credentials
- self.unlink()
+ if self.payment_method == 'manual':
+ manual_acquirer = self._get_manual_payment_acquirer(new_env)
+ manual_acquirer.post_msg = self.manual_post_msg
+ manual_acquirer.website_published = True
- return {'type': 'ir.actions.act_window_close'}
+ journal = manual_acquirer.journal_id
+ journal.name = self.journal_name
+ journal.bank_acc_number = self.acc_number
- @api.multi
- def action_skip_payment_onboarding_payment_acquirer_step(self):
+ # delete wizard data immediately to get rid of residual credentials
+ self.unlink()
+ # the user clicked `apply` and not cancel so we can assume this step is done.
self._set_payment_acquirer_onboarding_step_done()
return {'type': 'ir.actions.act_window_close'}
def _set_payment_acquirer_onboarding_step_done(self):
- self.env.user.company_id.write({'payment_acquirer_onboarding_done': True})
+ self.env.user.company_id.set_onboarding_step_done('payment_acquirer_onboarding_state')
diff --git a/addons/sale/controllers/onboarding.py b/addons/sale/controllers/onboarding.py
index 6fa8950ae66..0ab5067cdb3 100644
--- a/addons/sale/controllers/onboarding.py
+++ b/addons/sale/controllers/onboarding.py
@@ -7,18 +7,20 @@ from odoo.http import request
class OnboardingController(http.Controller):
- @http.route('/sales/onboarding_quotation_panel', auth='user', type='json')
+ @http.route('/sales/sale_quotation_onboarding_panel', auth='user', type='json')
def sale_quotation_onboarding(self):
""" Returns the `banner` for the sale onboarding panel.
It can be empty if the user has closed it or if he doesn't have
the permission to see it. """
+ company = request.env.user.company_id
if not request.env.user._is_admin() or \
- request.env.user.company_id.sale_quotation_onboarding_closed:
+ company.sale_quotation_onboarding_state == 'closed':
return {}
return {
- 'html': request.env.ref('sale.onboarding_quotation_panel').render({
- 'company': request.env.user.company_id,
+ 'html': request.env.ref('sale.sale_quotation_onboarding_panel').render({
+ 'company': company,
+ 'state': company.get_and_update_sale_quotation_onboarding_state()
})
}
diff --git a/addons/sale/models/res_company.py b/addons/sale/models/res_company.py
index 01b2e7c1fdd..17a5bf2e39e 100644
--- a/addons/sale/models/res_company.py
+++ b/addons/sale/models/res_company.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
-from odoo import api, fields, models
+from odoo import api, fields, models, _
class ResCompany(models.Model):
@@ -11,60 +11,99 @@ class ResCompany(models.Model):
portal_confirmation_sign = fields.Boolean(string='Digital Signature')
portal_confirmation_pay = fields.Boolean(string='Electronic Payment')
- @api.depends('portal_confirmation_sign')
- def _get_sale_onboarding_signature_radio(self):
- """ Convert portal_confirmation_sign from boolean to radio. """
- for record in self:
- record.portal_confirmation_sign_radio = 'yes' if record.portal_confirmation_sign else 'no'
-
- @api.depends('portal_confirmation_sign')
- def _set_sale_onboarding_signature_radio(self):
- """ Convert portal_confirmation_sign from radio to boolean. """
- for record in self:
- record.portal_confirmation_sign = record.portal_confirmation_sign_radio == 'yes'
-
- # the target field, portal_confirmation_sign, is a boolean but we would like to render it as a radio button
- portal_confirmation_sign_radio = fields.Selection([('yes', "Yes"), ('no', "No")], "Digital Signature (radio)",
- compute=_get_sale_onboarding_signature_radio, inverse=_set_sale_onboarding_signature_radio)
-
# sale quotation onboarding
- sale_quotation_onboarding_closed = fields.Boolean(
- string="Onboarding sale quotation closed",
- help="Refers to the sale quotation onboarding panel closed state.")
- sale_quotation_onboarding_folded = fields.Boolean(
- string="Onboarding sale quotation folded",
- help="Refers to the sale quotation onboarding panel folded state.")
- sale_onboarding_quotation_layout_done = fields.Boolean("Onboarding quotation layout step done",
- compute="_compute_sale_onboarding_quotation_layout_done")
- sale_onboarding_payment_acquirer_done = fields.Boolean("Sale onboarding payment acquirer step done",
- default=False)
- sale_onboarding_signature_done = fields.Boolean("Sale onboarding signature step done",
- default=False)
+ sale_quotation_onboarding_state = fields.Selection([('not_done', "Not done"), ('just_done', "Just done"), ('done', "Done"), ('closed', "Closed")], string="State of the sale onboarding panel", default='not_done')
+ sale_onboarding_order_confirmation_state = fields.Selection([('not_done', "Not done"), ('just_done', "Just done"), ('done', "Done")], string="State of the onboarding confirmation order step", default='not_done')
+ sale_onboarding_sample_quotation_state = fields.Selection([('not_done', "Not done"), ('just_done', "Just done"), ('done', "Done")], string="State of the onboarding sample quotation step", default='not_done')
- @api.model
- def action_toggle_fold_sale_quotation_onboarding(self):
- """ Toggle the onboarding panel `folded` state. """
- self.env.user.company_id.sale_quotation_onboarding_folded =\
- not self.env.user.company_id.sale_quotation_onboarding_folded
+ sale_onboarding_payment_method = fields.Selection([
+ ('digital_signature', 'Digital signature, without payment'),
+ ('paypal', 'PayPal'),
+ ('stripe', 'Stripe'),
+ ('manual', 'Wire Transfer'),
+ ('none', 'No digital signature or payment'),
+ ], string="Sale onboarding selected payment method")
@api.model
def action_close_sale_quotation_onboarding(self):
""" Mark the onboarding panel as closed. """
- self.env.user.company_id.sale_quotation_onboarding_closed = True
+ self.env.user.company_id.sale_quotation_onboarding_state = 'closed'
@api.model
- def action_open_sale_onboarding_signature(self):
+ def action_open_sale_onboarding_payment_acquirer(self):
""" Called by onboarding panel above the quotation list."""
- action = self.env.ref('sale.action_open_sale_onboarding_signature').read()[0]
- action['res_id'] = self.env.user.company_id.id
+ self.env.user.company_id.get_chart_of_accounts_or_fail()
+ action = self.env.ref('sale.action_open_sale_onboarding_payment_acquirer_wizard').read()[0]
return action
+ def _get_sample_sales_order(self):
+ """ Get a sample quotation or create one if it does not exist. """
+ # use current user as partner
+ partner = self.env.user.partner_id
+ company_id = self.env.user.company_id.id
+ # is there already one?
+ sample_sales_order = self.env['sale.order'].search(
+ [('company_id', '=', company_id), ('partner_id', '=', partner.id),
+ ('state', '=', 'draft')], limit=1)
+ if len(sample_sales_order) == 0:
+ sample_sales_order = self.env['sale.order'].create({
+ 'partner_id': partner.id
+ })
+ # take any existing product or create one
+ product = self.env['product.product'].search([], limit=1)
+ if len(product) == 0:
+ product = self.env['product.product'].create({
+ 'name': _('Sample Product')
+ })
+ self.env['sale.order.line'].create({
+ 'name': _('Sample Order Line'),
+ 'product_id': product.id,
+ 'product_uom_qty': 10,
+ 'price_unit': 123,
+ 'order_id': sample_sales_order.id,
+ })
+ return sample_sales_order
+
@api.model
- def action_open_sale_onboarding_payment_acquirer(self):
- """ Called by onboarding panel above the quotation list."""
- action = self.env.ref('sale.action_open_sale_onboarding_payment_acquirer_wizard').read()[0]
+ def action_open_sale_onboarding_sample_quotation(self):
+ """ Onboarding step for sending a sample quotation. Open a window to compose an email,
+ with the edi_invoice_template message loaded by default. """
+ sample_sales_order = self._get_sample_sales_order()
+ template = self.env.ref('sale.email_template_edi_sale', False)
+ action = self.env.ref('sale.action_open_sale_onboarding_sample_quotation').read()[0]
+ action['context'] = {
+ 'default_res_id': sample_sales_order.id,
+ 'default_use_template': bool(template),
+ 'default_template_id': template and template.id or False,
+ 'default_model': 'sale.order',
+ 'default_composition_mode': 'comment',
+ 'mark_so_as_sent': True,
+ 'custom_layout': 'mail.mail_notification_paynow',
+ 'proforma': self.env.context.get('proforma', False),
+ 'force_email': True,
+ }
return action
@api.multi
- def action_save_onboarding_signature(self):
- self.sale_onboarding_signature_done = True
+ def action_save_onboarding_quotation_layout(self):
+ """ Set the onboarding step as done """
+ if bool(self.logo) and self.logo != self._get_logo():
+ self.set_onboarding_step_done('account_onboarding_invoice_layout_state')
+
+ def get_and_update_sale_quotation_onboarding_state(self):
+ """ This method is called on the controller rendering method and ensures that the animations
+ are displayed only one time. """
+ steps = [
+ 'base_onboarding_company_state',
+ 'account_onboarding_invoice_layout_state',
+ 'sale_onboarding_order_confirmation_state',
+ 'sale_onboarding_sample_quotation_state',
+ ]
+ return self.get_and_update_onbarding_state('sale_quotation_onboarding_state', steps)
+
+ @api.model
+ def action_open_sale_onboarding_quotation_layout(self):
+ """ Onboarding step for the quotation layout. """
+ action = self.env.ref('sale.action_open_sale_onboarding_quotation_layout').read()[0]
+ action['res_id'] = self.env.user.company_id.id
+ return action
diff --git a/addons/sale/models/sale.py b/addons/sale/models/sale.py
index 6b27fd427a9..0f8f69ff898 100644
--- a/addons/sale/models/sale.py
+++ b/addons/sale/models/sale.py
@@ -519,6 +519,7 @@ class SaleOrder(models.Model):
def message_post(self, **kwargs):
if self.env.context.get('mark_so_as_sent'):
self.filtered(lambda o: o.state == 'draft').with_context(tracking_disable=True).write({'state': 'sent'})
+ self.env.user.company_id.set_onboarding_step_done('sale_onboarding_sample_quotation_state')
return super(SaleOrder, self.with_context(mail_post_autofollow=True)).message_post(**kwargs)
@api.multi
diff --git a/addons/sale/static/src/img/onboarding_quotation_order_tooltip.jpg b/addons/sale/static/src/img/onboarding_quotation_order_tooltip.jpg
new file mode 100644
index 00000000000..548a1d35ef2
--- /dev/null
+++ b/addons/sale/static/src/img/onboarding_quotation_order_tooltip.jpg
Binary files differ
diff --git a/addons/sale/static/src/scss/sale_onboarding.scss b/addons/sale/static/src/scss/sale_onboarding.scss
new file mode 100644
index 00000000000..6f00b2a60d0
--- /dev/null
+++ b/addons/sale/static/src/scss/sale_onboarding.scss
@@ -0,0 +1,11 @@
+.o_onboarding_order_confirmation {
+ & span.o_onboarding_order_confirmation_help img {
+ display: none;
+ position: absolute;
+ bottom:0;
+ }
+ & span.o_onboarding_order_confirmation_help:hover img {
+ display: block
+ }
+
+} \ No newline at end of file
diff --git a/addons/sale/views/assets.xml b/addons/sale/views/assets.xml
index a736833aabc..519f86babf1 100644
--- a/addons/sale/views/assets.xml
+++ b/addons/sale/views/assets.xml
@@ -5,7 +5,11 @@
<script type="text/javascript" src="/sale/static/src/js/sale.js"></script>
</xpath>
</template>
-
+ <template id="assets_backend_onboarding" name="onboarding_assets" inherit_id="web.assets_backend">
+ <xpath expr="." position="inside">
+ <link rel="stylesheet" type="text/scss" href="/sale/static/src/scss/sale_onboarding.scss"/>
+ </xpath>
+ </template>
<template id="assets_frontend" inherit_id="web.assets_frontend" name="Sale frontend assets">
<xpath expr="." position="inside">
<link rel="stylesheet" type="text/scss" href="/sale/static/src/scss/sale_portal.scss"/>
diff --git a/addons/sale/views/sale_onboarding_views.xml b/addons/sale/views/sale_onboarding_views.xml
index 0f4ae9ede2e..3575729652a 100644
--- a/addons/sale/views/sale_onboarding_views.xml
+++ b/addons/sale/views/sale_onboarding_views.xml
@@ -1,107 +1,129 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- ONBOARDING STEPS -->
- <template id="onboarding_signature_step">
+ <template id="onboarding_quotation_layout_step">
<t t-call="base.onboarding_step">
- <t t-set="title">Signature</t>
- <t t-set="description">Request a digital signature to confirm orders.</t>
+ <t t-set="title">Quotation Layout</t>
+ <t t-set="description">Customize the look of your quotations.</t>
<t t-set="done_icon" t-value="'fa-star'" />
<t t-set="done_text">Looks great!</t>
- <t t-set="method" t-value="'action_open_sale_onboarding_signature'" />
+ <t t-set="method" t-value="'action_open_sale_onboarding_quotation_layout'" />
<t t-set="model" t-value="'res.company'" />
- <t t-set="done" t-value="company.sale_onboarding_signature_done" />
+ <t t-set="state" t-value="state.get('account_onboarding_invoice_layout_state')" />
</t>
</template>
- <template id="sale_onboarding_payment_acquirer_step" primary="True"
- inherit_id="payment.onboarding_payment_acquirer_step">
- <xpath expr="//t[@t-set='method']" position="replace">
+ <template id="sale_onboarding_order_confirmation_step">
+ <t t-call="base.onboarding_step">
+ <t t-set="title">Confirmation &amp; payment</t>
+ <t t-set="description">Choose how to confirm quotations and get paid.</t>
<t t-set="method" t-value="'action_open_sale_onboarding_payment_acquirer'" />
- </xpath>
- <xpath expr="//t[@t-set='done']" position="replace">
- <t t-set="done" t-value="company.sale_onboarding_payment_acquirer_done" />
- </xpath>
+ <t t-set="model" t-value="'res.company'" />
+ <t t-set="state" t-value="state.get('sale_onboarding_order_confirmation_state')" />
+ </t>
</template>
- <template id="onboarding_quotation_layout_step" primary="True" inherit_id="account.onboarding_invoice_layout_step">
- <xpath expr="//t[@t-set='title']" position="replace">
- <t t-set="title">Quotation Layout</t>
- </xpath>
- <xpath expr="//t[@t-set='description']" position="replace">
- <t t-set="description">Create and send professional looking quotations.</t>
- </xpath>
+ <template id="sale_onboarding_sample_quotation_step">
+ <t t-call="base.onboarding_step">
+ <t t-set="title">Sample Quotation</t>
+ <t t-set="description">Send a quotation to test the customer portal.</t>
+ <t t-set="method" t-value="'action_open_sale_onboarding_sample_quotation'" />
+ <t t-set="model" t-value="'res.company'" />
+ <t t-set="state" t-value="state.get('sale_onboarding_sample_quotation_state')" />
+ </t>
</template>
+
<!-- ONBOARDING PANEL-->
- <template id="onboarding_quotation_panel" name="sale.quotation.onboarding.panel">
+ <template id="sale_quotation_onboarding_panel" name="sale.quotation.onboarding.panel">
<t t-call="base.onboarding_container">
<t t-set="classes">o_onboarding_violet</t>
<t t-set="bg_image">/sale/static/src/img/sale_quotation_onboarding_bg.jpg</t>
<t t-set="close_method">action_close_sale_quotation_onboarding</t>
<t t-set="close_model">res.company</t>
- <t t-set="fold_method">action_toggle_fold_sale_quotation_onboarding</t>
- <t t-set="fold_model">res.company</t>
- <t t-set="folded_by_default" t-value="company.sale_quotation_onboarding_folded" />
-
<t t-call="base.onboarding_company_step" name="company_step" />
<t t-call="sale.onboarding_quotation_layout_step" name="quotation_layout_step" />
- <t t-call="sale.onboarding_signature_step" name="signature_step" />
- <t t-call="sale.sale_onboarding_payment_acquirer_step" name="payment_acquirer_step" />
+ <t t-call="sale.sale_onboarding_order_confirmation_step" name="payment_acquirer_step" />
+ <t t-call="sale.sale_onboarding_sample_quotation_step" name="sample_quotation_step" />
</t>
</template>
- <!-- SIGNATURE FORM -->
- <record model="ir.ui.view" id="sale_onboarding_signature_form">
- <field name="name">sale.onboarding.signature.form</field>
- <field name="model">res.company</field>
+ <!-- ORDER CONFIRMATION -->
+ <record id="sale_onboarding_order_confirmation_form" model="ir.ui.view">
+ <field name="name">sale.order.confirmation.onboarding.form</field>
+ <field name="model">sale.payment.acquirer.onboarding.wizard</field>
+ <field name="inherit_id" ref="payment.payment_acquirer_onboarding_wizard_form" />
+ <field name="mode">primary</field>
+ <field name="priority">1000</field>
<field name="arch" type="xml">
- <form string="Request an electronic signature">
- <div class="panel-body row"><!-- FIXME -->
- Quotations can be confirmed automatically based on a customer signature, in
- order to automate the delivery process. This functionality is convenient for all
- the parties and offers as much legal guarantee as a paper signature.
- <br />
- <br />
- Do you want to activate the digital signature?
+ <xpath expr="//div[@name='left-column']" position="attributes">
+ <attribute name="class">col col-4</attribute>
+ </xpath>
+ <xpath expr="//div[@name='right-column']" position="inside">
+ <div attrs="{'invisible': [('payment_method', '!=', 'digital_signature')]}">
+ Digital signature offers as much legal guarantee as a paper signature, with way
+ more convenience for all parties.
</div>
- <div class="panel-body row"><!-- FIXME -->
- <field name="portal_confirmation_sign_radio" widget="radio" />
+ <div attrs="{'invisible': [('payment_method', '!=', 'none')]}">
+ The salesperson confirms the quotation, after receiving an approval by email, a call, etc.
</div>
- <footer>
- <button name="action_save_onboarding_signature" string="OK" class="oe_highlight"
- type="object" />
- <button special="cancel" string="Cancel" />
- </footer>
- </form>
+ </xpath>
</field>
</record>
- <record id="action_open_sale_onboarding_signature" model="ir.actions.act_window">
- <field name="name">Request a digital signature</field>
+ <record id="action_open_sale_onboarding_payment_acquirer_wizard" model="ir.actions.act_window">
+ <field name="name">Choose a payment method</field>
<field name="type">ir.actions.act_window</field>
- <field name="res_model">res.company</field>
+ <field name="res_model">sale.payment.acquirer.onboarding.wizard</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
- <field name="view_id" ref="sale.sale_onboarding_signature_form" />
+ <field name="view_id" ref="sale_onboarding_order_confirmation_form" />
<field name="target">new</field>
</record>
- <!-- PAYMENT ACQUIRER -->
- <record id="sale_onboarding_payment_acquirer_form" model="ir.ui.view">
- <field name="name">sale.onboarding.payment.acquirer.form</field>
- <field name="model">sale.payment.acquirer.onboarding.wizard</field>
- <field name="inherit_id" ref="payment.payment_acquirer_onboarding_wizard_form"/>
+ <!-- QUOTATION LAYOUT -->
+ <record id="sale_onboarding_quotation_layout_form" model="ir.ui.view">
+ <field name="name">sale.onboarding.quotation.layout.form</field>
+ <field name="model">res.company</field>
+ <field name="inherit_id" ref="base.view_company_document_template_form" />
<field name="mode">primary</field>
<field name="priority">1000</field>
<field name="arch" type="xml">
- <xpath expr="//div[@name='skip_step_text']" position="replace">
- <div class="mb16">
- You can skip this step if you don't manage payments on quotations.
- </div>
+ <xpath expr="//button[@special='save']" position="replace">
+ <button string="Apply" class="btn btn-primary" type="object" name="action_save_onboarding_quotation_layout" />
</xpath>
- </field>
+ </field>
</record>
- <record id="action_open_sale_onboarding_payment_acquirer_wizard" model="ir.actions.act_window">
- <field name="name">Choose a payment method</field>
+ <record id="action_open_sale_onboarding_quotation_layout" model="ir.actions.act_window">
+ <field name="name">Configure your document layout</field>
<field name="type">ir.actions.act_window</field>
- <field name="res_model">sale.payment.acquirer.onboarding.wizard</field>
+ <field name="res_model">res.company</field>
+ <field name="view_mode">form</field>
<field name="view_type">form</field>
+ <field name="view_id" ref="sale_onboarding_quotation_layout_form" />
+ <field name="target">new</field>
+ </record>
+ <!-- SAMPLE QUOTATION -->
+ <record model="ir.ui.view" id="sale_onboarding_sample_quotation_form">
+ <field name="name">mail.compose.message.sale.onboarding.sample.quotation.form</field>
+ <field name="model">mail.compose.message</field>
+ <field name="inherit_id" ref="mail.email_compose_message_wizard_form" />
+ <field name="priority">1000</field>
+ <field name="mode">primary</field>
+ <field name="arch" type="xml">
+ <xpath expr="//span[@name='document_followers_text']" position="attributes">
+ <attribute name="invisible">1</attribute>
+ </xpath>
+ <xpath expr="//button[@name='save_as_template']" position="attributes">
+ <attribute name="invisible">1</attribute>
+ </xpath>
+ <xpath expr="//field[@name='template_id']" position="attributes">
+ <attribute name="invisible">1</attribute>
+ </xpath>
+ </field>
+ </record>
+
+ <record id="action_open_sale_onboarding_sample_quotation" model="ir.actions.act_window">
+ <field name="name">Send a sample quotation.</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">mail.compose.message</field>
<field name="view_mode">form</field>
- <field name="view_id" ref="sale.sale_onboarding_payment_acquirer_form" />
+ <field name="view_type">form</field>
+ <field name="view_id" ref="sale_onboarding_sample_quotation_form" />
<field name="target">new</field>
</record>
</odoo>
diff --git a/addons/sale/views/sale_views.xml b/addons/sale/views/sale_views.xml
index 69f9eabf864..6d63dbebf95 100644
--- a/addons/sale/views/sale_views.xml
+++ b/addons/sale/views/sale_views.xml
@@ -196,7 +196,7 @@
<field name="mode">primary</field>
<field name="arch" type="xml">
<xpath expr="//tree" position="attributes">
- <attribute name="banner_route">/sales/onboarding_quotation_panel</attribute>
+ <attribute name="banner_route">/sales/sale_quotation_onboarding_panel</attribute>
</xpath>
</field>
</record>
diff --git a/addons/sale/wizard/payment_acquirer_onboarding_wizard.py b/addons/sale/wizard/payment_acquirer_onboarding_wizard.py
index 6bc92ec825e..d81da663c13 100644
--- a/addons/sale/wizard/payment_acquirer_onboarding_wizard.py
+++ b/addons/sale/wizard/payment_acquirer_onboarding_wizard.py
@@ -1,18 +1,36 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
-
-from odoo import models
+from odoo import api, fields, models
class PaymentWizard(models.TransientModel):
+ """ Override for the sale quotation onboarding panel. """
+
_inherit = 'payment.acquirer.onboarding.wizard'
_name = 'sale.payment.acquirer.onboarding.wizard'
- def _hook_on_save_onboarding_payment_acquirer(self):
- """ Override. Activate the option in sales settings. """
- self.env.user.company_id.portal_confirmation_pay = True
+ def _get_default_payment_method(self):
+ return self.env.user.company_id.sale_onboarding_payment_method
+
+ payment_method = fields.Selection([
+ ('digital_signature', 'Digital signature, without payment'),
+ ('paypal', 'PayPal'),
+ ('stripe', 'Stripe'),
+ ('manual', 'Wire Transfer'),
+ ('none', 'No digital signature or payment'),
+ ], default=_get_default_payment_method)
+ #
def _set_payment_acquirer_onboarding_step_done(self):
""" Override. """
- self.env.user.company_id.sale_onboarding_payment_acquirer_done = True
+ self.env.user.company_id.set_onboarding_step_done('sale_onboarding_order_confirmation_state')
+
+ @api.multi
+ def add_payment_methods(self, *args, **kwargs):
+ self.env.user.company_id.sale_onboarding_payment_method = self.payment_method
+ if self.payment_method == 'digital_signature':
+ self.env.user.company_id.portal_confirmation_sign = True
+ if self.payment_method in ('paypal', 'stripe'):
+ self.env.user.company_id.portal_confirmation_pay = True # TODO self.digital_signature
+ return super(PaymentWizard, self).add_payment_methods(*args, **kwargs)
diff --git a/addons/web/static/src/js/views/abstract_controller.js b/addons/web/static/src/js/views/abstract_controller.js
index ef95ea72696..aed09c363cc 100644
--- a/addons/web/static/src/js/views/abstract_controller.js
+++ b/addons/web/static/src/js/views/abstract_controller.js
@@ -283,22 +283,22 @@ var AbstractController = AbstractAction.extend(ControlPanelMixin, {
});
},
/**
- * Renders the html provided by the route specified by the
- * bannerRoute attribute on the controller (banner_route in the template).
- * Renders it before the view output and add a css class 'o_has_banner' to it.
- * There can be only one banner displayed at a time.
- *
- * If the banner contains stylesheet links, they are moved to <head>
- * (and will only be fetched once).
- *
- * Route example:
- * @http.route('/module/hello', auth='user', type='json')
- * def hello(self):
- * return {'html': '<h1>hello, world</h1>'}
- *
- * @private
- * @returns {Deferred}
- */
+ * Renders the html provided by the route specified by the
+ * bannerRoute attribute on the controller (banner_route in the template).
+ * Renders it before the view output and add a css class 'o_has_banner' to it.
+ * There can be only one banner displayed at a time.
+ *
+ * If the banner contains stylesheet links or js files, they are moved to <head>
+ * (and will only be fetched once).
+ *
+ * Route example:
+ * @http.route('/module/hello', auth='user', type='json')
+ * def hello(self):
+ * return {'html': '<h1>hello, world</h1>'}
+ *
+ * @private
+ * @returns {Deferred}
+ */
_renderBanner: function () {
if (this.bannerRoute !== undefined) {
var self = this;
@@ -315,13 +315,16 @@ var AbstractController = AbstractAction.extend(ControlPanelMixin, {
if (self._$banner && self._$banner.remove) {
self._$banner.remove();
}
- // Stylesheets are moved to <head> and we wait for them to be loaded
- // to prevent displaying unstyled content.
+ // Css and js are moved to <head>
var defs = [];
$('link[rel="stylesheet"]', $banner).each(function (i, link) {
defs.push(ajax.loadCSS(link.href));
link.remove();
});
+ $('script[type="text/javascript"]', $banner).each(function (i, js) {
+ defs.push(ajax.loadJS(js.src));
+ js.remove();
+ });
return $.when.apply($, defs).then(function () {
$banner.prependTo(self.$el);
self._$banner = $banner;
diff --git a/addons/web/static/src/scss/banner.scss b/addons/web/static/src/scss/banner.scss
index b119d9ab273..d7237203897 100644
--- a/addons/web/static/src/scss/banner.scss
+++ b/addons/web/static/src/scss/banner.scss
@@ -1,5 +1,8 @@
.o_has_banner {
.o_view_nocontent {
top: 30%;
+ @media screen and (max-height: map-get($grid-breakpoints, 'md')) {
+ position: relative;
+ }
}
}
diff --git a/addons/web/static/src/scss/form_view.scss b/addons/web/static/src/scss/form_view.scss
index 65c75b4d406..755572ceb25 100644
--- a/addons/web/static/src/scss/form_view.scss
+++ b/addons/web/static/src/scss/form_view.scss
@@ -607,17 +607,15 @@
&.o_company_document_layout {
.image_selection_container {
div {
- width: 50%;
+ display: inline-block;
img {
margin-left: 0 !important;
}
}
}
- td {
- padding: 0 45px 0 0;
- }
img[name="logo"] {
- max-height: 300px;
+ max-height: 100px;
+ max-width: 300px;
}
}
}
@@ -648,6 +646,12 @@
width: 100%;
}
}
+ .o_onboarding_payment_acquirer_wizard {
+ a[type="action"] {
+ color: $link-color;
+ cursor: pointer;
+ }
+ }
}
@media print {
diff --git a/addons/web/views/webclient_templates.xml b/addons/web/views/webclient_templates.xml
index 5d1ff38695f..924c5353b9d 100644
--- a/addons/web/views/webclient_templates.xml
+++ b/addons/web/views/webclient_templates.xml
@@ -174,6 +174,7 @@
<link rel="stylesheet" type="text/scss" href="/web/static/src/scss/dropdown_menu.scss"/>
<link rel="stylesheet" type="text/scss" href="/web/static/src/scss/search_view_extra.scss"/>
<link rel="stylesheet" type="text/scss" href="/web/static/src/scss/data_export.scss"/>
+ <link rel="stylesheet" type="text/scss" href="/base/static/src/scss/onboarding.scss"/>
<link rel="stylesheet" type="text/scss" href="/web/static/src/scss/base_settings.scss"/>
<script type="text/javascript" src="/base/static/src/js/res_config_settings.js"></script>
diff --git a/addons/website_sale/models/res_company.py b/addons/website_sale/models/res_company.py
index c82e478ab26..aeaa4ffcbcf 100644
--- a/addons/website_sale/models/res_company.py
+++ b/addons/website_sale/models/res_company.py
@@ -7,11 +7,11 @@ from odoo import api, fields, models
class ResCompany(models.Model):
_inherit = 'res.company'
- website_sale_onboarding_payment_acquirer_done =\
- fields.Boolean("Website sale onboarding payment acquirer step done", default=False)
+ website_sale_onboarding_payment_acquirer_state = fields.Selection([('not_done', "Not done"), ('just_done', "Just done"), ('done', "Done")], string="State of the website sale onboarding payment acquirer step", default='not_done')
@api.model
def action_open_website_sale_onboarding_payment_acquirer(self):
""" Called by onboarding panel above the quotation list."""
+ self.env.user.company_id.get_chart_of_accounts_or_fail()
action = self.env.ref('website_sale.action_open_website_sale_onboarding_payment_acquirer_wizard').read()[0]
return action
diff --git a/addons/website_sale/views/onboarding_views.xml b/addons/website_sale/views/onboarding_views.xml
index 6004dfab302..8efd0a582f1 100644
--- a/addons/website_sale/views/onboarding_views.xml
+++ b/addons/website_sale/views/onboarding_views.xml
@@ -5,27 +5,18 @@
<xpath expr="//t[@t-set='method']" position="replace">
<t t-set="method" t-value="'action_open_website_sale_onboarding_payment_acquirer'" />
</xpath>
- <xpath expr="//t[@t-set='done']" position="replace">
- <t t-set="done" t-value="company.website_sale_onboarding_payment_acquirer_done" />
+ <xpath expr="//t[@t-set='state']" position="replace">
+ <t t-set="state" t-value="state.get('website_sale_onboarding_payment_acquirer_state')" />
</xpath>
</template>
- <record id="website_sale_onboarding_payment_acquirer_form" model="ir.ui.view">
- <field name="name">website.sale.onboarding.payment.acquirer.form</field>
- <field name="model">website.sale.payment.acquirer.onboarding.wizard</field>
- <field name="inherit_id" ref="payment.payment_acquirer_onboarding_wizard_form"/>
- <field name="mode">primary</field>
- <field name="priority">1000</field>
- <field name="arch" type="xml">
- <xpath expr="//div[@name='skip_step_text']" position="replace"/>
- </field>
- </record>
+
<record id="action_open_website_sale_onboarding_payment_acquirer_wizard" model="ir.actions.act_window">
<field name="name">Choose a payment method</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">website.sale.payment.acquirer.onboarding.wizard</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
- <field name="view_id" ref="website_sale_onboarding_payment_acquirer_form" />
+ <field name="view_id" ref="payment.payment_acquirer_onboarding_wizard_form" />
<field name="target">new</field>
</record>
</odoo>
diff --git a/addons/website_sale/wizard/payment_acquirer_onboarding_wizard.py b/addons/website_sale/wizard/payment_acquirer_onboarding_wizard.py
index 688b740d72e..18531d1c337 100644
--- a/addons/website_sale/wizard/payment_acquirer_onboarding_wizard.py
+++ b/addons/website_sale/wizard/payment_acquirer_onboarding_wizard.py
@@ -10,4 +10,4 @@ class PaymentWizard(models.TransientModel):
def _set_payment_acquirer_onboarding_step_done(self):
""" Override. """
- self.env.user.company_id.website_sale_onboarding_payment_acquirer_done = True
+ self.env.user.company_id.set_onboarding_step_done('website_sale_onboarding_payment_acquirer_state')
diff --git a/addons/website_theme_install/models/__init__.py b/addons/website_theme_install/models/__init__.py
index 480a1b847c7..de58fda6e31 100644
--- a/addons/website_theme_install/models/__init__.py
+++ b/addons/website_theme_install/models/__init__.py
@@ -2,4 +2,3 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import ir_module_module
-from . import res_company
diff --git a/addons/website_theme_install/models/res_company.py b/addons/website_theme_install/models/res_company.py
deleted file mode 100644
index ce1e3e719a7..00000000000
--- a/addons/website_theme_install/models/res_company.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# -*- coding: utf-8 -*-
-# Part of Odoo. See LICENSE file for full copyright and licensing details.
-
-from odoo import api, fields, models
-from ast import literal_eval
-
-
-class ResCompany(models.Model):
- _inherit = 'res.company'
-
- def _compute_website_theme_onboarding_done(self):
- """ The step is marked as done if one theme is installed. """
- # we need the same domain as the existing action
- action = self.env.ref('website_theme_install.theme_install_kanban_action').read()[0]
- domain = literal_eval(action['domain'])
- domain.append(('state', '=', 'installed'))
- installed_themes_count = self.env['ir.module.module'].sudo().search_count(domain)
- for record in self:
- record.website_theme_onboarding_done = (installed_themes_count > 0)
-
- website_theme_onboarding_done = fields.Boolean("Onboarding website theme step done",
- compute='_compute_website_theme_onboarding_done')
-
- @api.model
- def action_open_website_theme_selector(self):
- action = self.env.ref('website_theme_install.theme_install_kanban_action').read()[0]
- action['target'] = 'new'
- return action
diff --git a/addons/website_theme_install/views/views.xml b/addons/website_theme_install/views/views.xml
index 4ccb733a4e0..3b6cd89db61 100644
--- a/addons/website_theme_install/views/views.xml
+++ b/addons/website_theme_install/views/views.xml
@@ -95,15 +95,4 @@ action = {
<a href="/web#action=website_theme_install.theme_install_kanban_action">See themes here</a>
</xpath>
</template>
- <!-- ONBOARDING -->
- <template id="onboarding_website_theme_step">
- <t t-call="base.onboarding_step">
- <t t-set="title">Website Theme</t>
- <t t-set="description">Select a theme for your wonderful website.</t>
- <t t-set="btn_text">Let's start!</t>
- <t t-set="method" t-value="'action_open_website_theme_selector'" />
- <t t-set="model" t-value="'res.company'" />
- <t t-set="done" t-value="company.website_theme_onboarding_done" />
- </t>
- </template>
</odoo>