[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) <yti@odoo.com>
This commit is contained in:
Arnaud Joset
2020-10-06 10:26:56 +00:00
committed by Yannick Tivisse
parent 4d7ebb8cf5
commit 9ace056714
11 changed files with 126 additions and 23 deletions
+1
View File
@@ -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',
+1
View File
@@ -3,3 +3,4 @@
from . import onboarding
from . import portal
from . import terms
+22
View File
@@ -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)
+6
View File
@@ -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="""<h1 style="text-align: center; ">Terms &amp; Conditions</h1>
<p>Your conditions...</p>""")
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
@@ -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
@@ -36,3 +36,7 @@
width: 100%;
}
}
.oe_account_terms {
flex: auto !important;
}
@@ -245,23 +245,6 @@
</div>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box" id="use_invoice_terms">
<div class="o_setting_left_pane">
<field name="use_invoice_terms"/>
</div>
<div class="o_setting_right_pane">
<label for="use_invoice_terms"/>
<span class="fa fa-lg fa-building-o" title="Values set here are company-specific." aria-label="Values set here are company-specific." groups="base.group_multi_company" role="img"/>
<div class="text-muted">
Show standard terms &amp; conditions on invoices/orders
</div>
<div class="content-group" attrs="{'invisible': [('use_invoice_terms','=',False)]}">
<div class="mt16">
<field name="invoice_terms" placeholder="Insert your terms &amp; conditions here..."/>
</div>
</div>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box" id="get_invoice_warnings">
<div class="o_setting_left_pane">
<field name="group_warning_account"/>
@@ -323,6 +306,40 @@
</div>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box" id="use_invoice_terms">
<div class="o_setting_left_pane">
<field name="use_invoice_terms"/>
</div>
<div class="o_setting_right_pane">
<label for="use_invoice_terms"/>
<span class="fa fa-lg fa-building-o" title="Values set here are company-specific." aria-label="Values set here are company-specific." groups="base.group_multi_company" role="img"/>
<div class="text-muted">
Show standard terms &amp; conditions on invoices/orders
</div>
<div class="content-group" attrs="{'invisible': [('use_invoice_terms','=',False)]}">
<div class="mt16">
<field name="terms_type" class="o_light_label" widget="radio"/>
<div class="d-flex">
<field name="invoice_terms"
attrs="{'invisible': [('terms_type', '=', 'html')]}"
class="oe_account_terms"
placeholder="Insert your terms &amp; conditions here..."/>
<field name="invoice_terms_html"
attrs="{'invisible': [('terms_type', '=', 'plain')]}"
class="oe_account_terms"
placeholder="Insert your terms &amp; conditions here..."/>
</div>
<field name="preview_ready" invisible="1"/>
<div attrs="{'invisible': [('preview_ready', '=', False)]}">
<a href="/terms">
<i class="fa fa-arrow-right"></i>
Preview
</a>
</div>
</div>
</div>
</div>
</div>
</div>
<h2>Customer Payments</h2>
<div class="row mt16 o_settings_container" id="pay_invoice_online_setting_container">
+26
View File
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<template id="account.account_terms_conditions_setting_banner" name="Account Terms and Conditions Setting Banner">
<div id="terms_conditions" t-ignore="true" class="text-center">
<span>This is a preview of your Terms &amp; Conditions.</span>
<a t-att-href="backend_url"><i class="fa fa-arrow-right mr-1"/>Back to settings</a>
</div>
<button type="button" class="close" data-dismiss="alert" aria-label="Close"> &#215; </button>
</template>
<template id="account_terms_conditions_page" name="Terms &amp; Conditions">
<t t-call="web.frontend_layout">
<t t-set="o_portal_fullwidth_alert" groups="account.group_account_manager">
<t t-call="account.account_terms_conditions_setting_banner">
<t t-set="backend_url" t-value="'/web#action=account.action_open_settings&amp;model=res.config.settings'"/>
</t>
</t>
<div class="oe_structure" id="oe_structure_terms_conditions"/>
<div class="container oe_website_terms_conditions">
<div id="o_terms_conditions">
<div t-field="company.invoice_terms_html"/>
</div>
</div>
</t>
</template>
</odoo>
+11 -4
View File
@@ -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)
+8 -1
View File
@@ -537,7 +537,14 @@
<section id="terms" class="mt-5" t-if="sale_order.note">
<h3 class="">Terms &amp; Conditions</h3>
<hr class="mt-0 mb-1"/>
<em t-field="sale_order.note"/>
<t t-if="sale_order.terms_type == 'html'">
<!-- Note is plain text. This ensures a clickable link -->
<t t-set="tc_url" t-value="'%s/terms' % (sale_order.get_base_url())"/>
<em>Terms &amp; Conditions: <a href="/terms"><t t-esc="tc_url"/></a></em>
</t>
<t t-else="">
<em t-field="sale_order.note"/>
</t>
</section>
<section class="mt-5" t-if="sale_order.payment_term_id">
-1
View File
@@ -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):