From 9ace05671415539d09b46ffa8b9b3a4f66c8f5c6 Mon Sep 17 00:00:00 2001 From: Arnaud Joset Date: Wed, 19 Aug 2020 09:41:22 +0000 Subject: [PATCH] [IMP] account,sale: html field for terms & conditions Before this commit, the terms and conditions could not be html formatted text. closes odoo/odoo#56512 Taskid: 2304199 Related: odoo/upgrade#1689 Signed-off-by: Yannick Tivisse (yti) --- addons/account/__manifest__.py | 1 + addons/account/controllers/__init__.py | 1 + addons/account/controllers/terms.py | 22 ++++++++ addons/account/models/company.py | 6 +++ addons/account/models/res_config_settings.py | 13 +++++ addons/account/static/src/css/account.css | 4 ++ .../views/res_config_settings_views.xml | 51 ++++++++++++------- addons/account/views/terms_template.xml | 26 ++++++++++ addons/sale/models/sale.py | 15 ++++-- addons/sale/views/sale_portal_templates.xml | 9 +++- addons/website_sale/__init__.py | 1 - 11 files changed, 126 insertions(+), 23 deletions(-) create mode 100644 addons/account/controllers/terms.py create mode 100644 addons/account/views/terms_template.xml diff --git a/addons/account/__manifest__.py b/addons/account/__manifest__.py index 0a77f1600f4..b3f27b9f7fd 100644 --- a/addons/account/__manifest__.py +++ b/addons/account/__manifest__.py @@ -46,6 +46,7 @@ You could use this simplified accounting in case you work with an (external) acc 'views/res_partner_bank_views.xml', 'views/report_statement.xml', 'views/account_report.xml', + 'views/terms_template.xml', 'data/mail_template_data.xml', 'wizard/account_validate_move_view.xml', 'views/res_company_views.xml', diff --git a/addons/account/controllers/__init__.py b/addons/account/controllers/__init__.py index 1a195b71756..4cb0be3e577 100644 --- a/addons/account/controllers/__init__.py +++ b/addons/account/controllers/__init__.py @@ -3,3 +3,4 @@ from . import onboarding from . import portal +from . import terms diff --git a/addons/account/controllers/terms.py b/addons/account/controllers/terms.py new file mode 100644 index 00000000000..55087d2dcc9 --- /dev/null +++ b/addons/account/controllers/terms.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import http, _ +from odoo.http import request + + +class TermsController(http.Controller): + + @http.route('/terms', type='http', auth='public', website=True, sitemap=True) + def terms_conditions(self, **kwargs): + use_invoice_terms = request.env['ir.config_parameter'].sudo().get_param('account.use_invoice_terms') + if not (use_invoice_terms and request.env.company.terms_type == 'html'): + return request.render('http_routing.http_error', { + 'status_code': _('Oops'), + 'status_message': _("""The requested page is invalid, or doesn't exist anymore.""")}) + values = { + 'use_invoice_terms': use_invoice_terms, + 'company': request.env.company + } + return request.render("account.account_terms_conditions_page", values) + diff --git a/addons/account/models/company.py b/addons/account/models/company.py index cf1b2d541b3..33297625a6d 100644 --- a/addons/account/models/company.py +++ b/addons/account/models/company.py @@ -104,6 +104,12 @@ class ResCompany(models.Model): account_invoice_onboarding_state = fields.Selection(DASHBOARD_ONBOARDING_STATES, string="State of the account invoice onboarding panel", default='not_done') account_dashboard_onboarding_state = fields.Selection(DASHBOARD_ONBOARDING_STATES, string="State of the account dashboard onboarding panel", default='not_done') invoice_terms = fields.Text(string='Default Terms and Conditions', translate=True) + terms_type = fields.Selection([('plain', 'Terms as Notes'), ('html', 'Terms as Web Page')], + string='Terms & Conditions format', default='plain') + invoice_terms_html = fields.Html(string='Default Terms and Conditions as a Web page', translate=True, + default="""

Terms & Conditions

+

Your conditions...

""") + account_setup_bill_state = fields.Selection(ONBOARDING_STEP_STATES, string="State of the onboarding bill step", default='not_done') # Needed in the Point of Sale diff --git a/addons/account/models/res_config_settings.py b/addons/account/models/res_config_settings.py index 457c00481b3..909394d92f4 100644 --- a/addons/account/models/res_config_settings.py +++ b/addons/account/models/res_config_settings.py @@ -100,6 +100,12 @@ class ResConfigSettings(models.TransientModel): invoice_is_email = fields.Boolean(string='Send Email', related='company_id.invoice_is_email', readonly=False) incoterm_id = fields.Many2one('account.incoterms', string='Default incoterm', related='company_id.incoterm_id', help='International Commercial Terms are a series of predefined commercial terms used in international transactions.', readonly=False) invoice_terms = fields.Text(related='company_id.invoice_terms', string="Terms & Conditions", readonly=False) + invoice_terms_html = fields.Html(related='company_id.invoice_terms_html', string="Terms & Conditions as a Web page", + readonly=False) + terms_type = fields.Selection( + related='company_id.terms_type', readonly=False) + preview_ready = fields.Boolean(string="Display preview button", compute='_compute_terms_preview') + use_invoice_terms = fields.Boolean( string='Default Terms & Conditions', config_parameter='account.use_invoice_terms') @@ -163,6 +169,13 @@ class ResConfigSettings(models.TransientModel): } return res + @api.depends('terms_type') + def _compute_terms_preview(self): + for setting in self: + # We display the preview button only if the terms_type is html in the setting but also on the company + # to avoid landing on an error page (see terms.py controller) + setting.preview_ready = self.env.company.terms_type == 'html' and setting.terms_type == 'html' + @api.model def create(self, values): # Optimisation purpose, saving a res_config even without changing any values will trigger the write of all diff --git a/addons/account/static/src/css/account.css b/addons/account/static/src/css/account.css index c38173708c5..486b8225bfa 100644 --- a/addons/account/static/src/css/account.css +++ b/addons/account/static/src/css/account.css @@ -36,3 +36,7 @@ width: 100%; } } + +.oe_account_terms { + flex: auto !important; +} diff --git a/addons/account/views/res_config_settings_views.xml b/addons/account/views/res_config_settings_views.xml index ee16fb31aec..c793dfa1a8c 100644 --- a/addons/account/views/res_config_settings_views.xml +++ b/addons/account/views/res_config_settings_views.xml @@ -245,23 +245,6 @@ -
-
- -
-
-
-
@@ -323,6 +306,40 @@
+
+
+ +
+
+
+

Customer Payments

diff --git a/addons/account/views/terms_template.xml b/addons/account/views/terms_template.xml new file mode 100644 index 00000000000..24fd9e3a040 --- /dev/null +++ b/addons/account/views/terms_template.xml @@ -0,0 +1,26 @@ + + + + + + diff --git a/addons/sale/models/sale.py b/addons/sale/models/sale.py index 3a185418000..3e90debc941 100644 --- a/addons/sale/models/sale.py +++ b/addons/sale/models/sale.py @@ -12,7 +12,6 @@ from odoo.osv import expression from odoo.tools import float_is_zero, float_compare - from werkzeug.urls import url_encode @@ -109,7 +108,11 @@ class SaleOrder(models.Model): @api.model def _default_note(self): - return self.env['ir.config_parameter'].sudo().get_param('account.use_invoice_terms') and self.env.company.invoice_terms or '' + use_invoice_terms = self.env['ir.config_parameter'].sudo().get_param('account.use_invoice_terms') + if use_invoice_terms and self.env.company.terms_type == "html": + baseurl = self.env['ir.config_parameter'].sudo().get_param('web.base.url') + return _('Terms & Conditions: %s/terms', baseurl) + return use_invoice_terms and self.env.company.invoice_terms or '' @api.model def _get_default_team(self): @@ -207,6 +210,7 @@ class SaleOrder(models.Model): ], string='Invoice Status', compute='_get_invoice_status', store=True, readonly=True) note = fields.Text('Terms and conditions', default=_default_note) + terms_type = fields.Selection(related='company_id.terms_type') amount_untaxed = fields.Monetary(string='Untaxed Amount', store=True, readonly=True, compute='_amount_all', tracking=5) amount_by_group = fields.Binary(string="Tax amount by group", compute='_amount_by_group', help="type: [(name, amount, base, formated amount, formated base)]") @@ -377,8 +381,11 @@ class SaleOrder(models.Model): if user_id and self.user_id.id != user_id: values['user_id'] = user_id - if self.env['ir.config_parameter'].sudo().get_param('account.use_invoice_terms') and self.env.company.invoice_terms: - values['note'] = self.with_context(lang=self.partner_id.lang).env.company.invoice_terms + if self.env['ir.config_parameter'].sudo().get_param('account.use_invoice_terms'): + if self.terms_type == 'html' and self.env.company.invoice_terms_html: + values['note'] = _('Terms & Conditions: %s/terms', self.get_base_url()) + elif self.env.company.invoice_terms: + values['note'] = self.with_context(lang=self.partner_id.lang).env.company.invoice_terms if not self.env.context.get('not_self_saleperson') or not self.team_id: values['team_id'] = self.env['crm.team']._get_default_team_id(domain=['|', ('company_id', '=', self.company_id.id), ('company_id', '=', False)],user_id=user_id) self.update(values) diff --git a/addons/sale/views/sale_portal_templates.xml b/addons/sale/views/sale_portal_templates.xml index bba47adabd4..9bdef5e0382 100644 --- a/addons/sale/views/sale_portal_templates.xml +++ b/addons/sale/views/sale_portal_templates.xml @@ -537,7 +537,14 @@

Terms & Conditions


- + + + + Terms & Conditions: + + + +
diff --git a/addons/website_sale/__init__.py b/addons/website_sale/__init__.py index 8b3520af782..d809777293d 100644 --- a/addons/website_sale/__init__.py +++ b/addons/website_sale/__init__.py @@ -14,7 +14,6 @@ def pre_init_hook(cr): companies = env['res.company'].search([]) for company in companies: company.terms_type = 'html' - company.invoice_terms = _('Terms & Conditions: %s/terms', company.get_base_url()) def uninstall_hook(cr, registry):