- We would be delighted to assist you along the way. Contact us at
-
- help@odoo.com if you have any question. You can also discover
- how to get the best out of Odoo CRM with our
-
+ We would be delighted to assist you along the way. Contact us through our
+ support form if you have any question.
+ You can also discover how to get the best out of Odoo CRM with our
+
User Documentation
or with our
diff --git a/addons/crm/wizard/base_partner_merge.py b/addons/crm/wizard/base_partner_merge.py
index 44320807797..18fd4c6a3e6 100644
--- a/addons/crm/wizard/base_partner_merge.py
+++ b/addons/crm/wizard/base_partner_merge.py
@@ -406,7 +406,7 @@ class MergePartnerAutomatic(models.TransientModel):
:param models : dict mapping a model name with its foreign key with res_partner table
"""
return any(
- self.env[model].search_count([(field, 'in', aggr_ids)], limit=1)
+ self.env[model].search_count([(field, 'in', aggr_ids)])
for model, field in models.iteritems()
)
diff --git a/addons/delivery/models/stock_picking.py b/addons/delivery/models/stock_picking.py
index ebe6dc06b38..c39f1c4e721 100644
--- a/addons/delivery/models/stock_picking.py
+++ b/addons/delivery/models/stock_picking.py
@@ -51,8 +51,11 @@ class StockPicking(models.Model):
_inherit = 'stock.picking'
def _default_uom(self):
- uom_categ_id = self.env.ref('product.product_uom_categ_kgm').id
- return self.env['product.uom'].search([('category_id', '=', uom_categ_id), ('factor', '=', 1)], limit=1)
+ weight_uom_id = self.env.ref('product.product_uom_kgm', raise_if_not_found=False)
+ if not weight_uom_id:
+ uom_categ_id = self.env.ref('product.product_uom_categ_kgm').id
+ weight_uom_id = self.env['product.uom'].search([('category_id', '=', uom_categ_id), ('factor', '=', 1)], limit=1)
+ return weight_uom_id
@api.one
@api.depends('pack_operation_ids')
diff --git a/addons/event_sale/models/event.py b/addons/event_sale/models/event.py
index 65371c15047..5eba5703918 100644
--- a/addons/event_sale/models/event.py
+++ b/addons/event_sale/models/event.py
@@ -36,7 +36,7 @@ class EventTicket(models.Model):
name = fields.Char(string='Name', required=True, translate=True)
event_id = fields.Many2one('event.event', string="Event", required=True, ondelete='cascade')
product_id = fields.Many2one('product.product', string='Product',
- required=True, domain=["|", ("event_type_id", "!=", False), ("event_ok", "=", True)],
+ required=True, domain=[("event_ok", "=", True)],
default=_default_product_id)
registration_ids = fields.One2many('event.registration', 'event_ticket_id', string='Registrations')
price = fields.Float(string='Price', digits=dp.get_precision('Product Price'))
@@ -44,6 +44,7 @@ class EventTicket(models.Model):
is_expired = fields.Boolean(string='Is Expired', compute='_compute_is_expired')
price_reduce = fields.Float(string="Price Reduce", compute="_compute_price_reduce", digits=dp.get_precision('Product Price'))
+ price_reduce_taxinc = fields.Float(compute='_get_price_reduce_tax', string='Price Reduce Tax inc')
# seats fields
seats_availability = fields.Selection([('limited', 'Limited'), ('unlimited', 'Unlimited')],
string='Available Seat', required=True, store=True, compute='_compute_seats', default="limited")
@@ -71,6 +72,13 @@ class EventTicket(models.Model):
discount = product.lst_price and (product.lst_price - product.price) / product.lst_price or 0.0
record.price_reduce = (1.0 - discount) * record.price
+ def _get_price_reduce_tax(self):
+ for record in self:
+ # sudo necessary here since the field is most probably accessed through the website
+ tax_ids = record.sudo().product_id.taxes_id.filtered(lambda r: r.company_id == record.event_id.company_id)
+ taxes = tax_ids.compute_all(record.price_reduce, record.event_id.company_id.currency_id, 1.0, product=record.product_id)
+ record.price_reduce_taxinc = taxes['total_included']
+
@api.multi
@api.depends('seats_max', 'registration_ids.state')
def _compute_seats(self):
diff --git a/addons/google_calendar/models/google_calendar.py b/addons/google_calendar/models/google_calendar.py
index 007bbffeaf9..fb2e2e4f611 100644
--- a/addons/google_calendar/models/google_calendar.py
+++ b/addons/google_calendar/models/google_calendar.py
@@ -795,6 +795,7 @@ class GoogleCalendar(models.AbstractModel):
actToDo = event.OP
actSrc = event.OP.src
+ # To avoid redefining 'self', all method below should use 'recs' instead of 'self'
recs = self.with_context(curr_attendee=event.OE.attendee_id)
if isinstance(actToDo, NothingToDo):
@@ -828,12 +829,9 @@ class GoogleCalendar(models.AbstractModel):
if event_to_synchronize[base_event][0][1].OE.event_id:
parent_event['id'] = "%s-%s" % (event_to_synchronize[base_event][0][1].OE.event_id, new_google_event_id)
- res = self.update_from_google(parent_event, event.GG.event, "copy")
+ res = recs.update_from_google(parent_event, event.GG.event, "copy")
else:
- self.create_from_google(event, my_partner_id)
-
- parent_event['id'] = "%s-%s" % (event_to_synchronize[base_event][0][1].OE.event_id, new_google_event_id)
- res = recs.update_from_google(parent_event, event.GG.event, "copy")
+ recs.create_from_google(event, my_partner_id)
else:
parent_oe_id = event_to_synchronize[base_event][0][1].OE.event_id
if parent_oe_id:
diff --git a/addons/hr/models/res_partner.py b/addons/hr/models/res_partner.py
index 47bfe7e0534..8772bc46040 100644
--- a/addons/hr/models/res_partner.py
+++ b/addons/hr/models/res_partner.py
@@ -2,6 +2,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, models
+from openerp.exceptions import AccessError
class Partner(models.Model):
@@ -13,12 +14,10 @@ class Partner(models.Model):
""" Extend the mail's static mention suggestions by adding the employees. """
suggestions = super(Partner, self).get_static_mention_suggestions()
- employee_group_id = self.env['ir.model.data'].xmlid_to_res_id('base.group_user')
- self._cr.execute("""
- SELECT P.id, P.name, P.email
- FROM res_users U
- INNER JOIN res_groups_users_rel R ON U.id = R.uid
- INNER JOIN res_partner P ON P.id = U.partner_id
- WHERE R.gid = %s AND U.active = 't'""", (employee_group_id,))
- suggestions.append(self._cr.dictfetchall())
- return suggestions
+ try:
+ employee_group = self.env.ref('base.group_user')
+ for user in employee_group.users:
+ suggestions.append((user.partner_id.id, user.name, user.email))
+ return suggestions
+ except AccessError:
+ return suggestions
diff --git a/addons/hr_attendance/models/hr_employee.py b/addons/hr_attendance/models/hr_employee.py
index 7fcd8ee8ff4..a4dac9883ea 100644
--- a/addons/hr_attendance/models/hr_employee.py
+++ b/addons/hr_attendance/models/hr_employee.py
@@ -74,7 +74,7 @@ class HrEmployee(models.Model):
@api.multi
def attendance_manual(self, next_action, entered_pin=None):
self.ensure_one()
- if self.env['res.users'].browse(SUPERUSER_ID).has_group('hr_attendance.group_hr_attendance_use_pin') and (self.user_id and self.user_id.id != self._uid or not self.user_id):
+ if not (entered_pin is None) or self.env['res.users'].browse(SUPERUSER_ID).has_group('hr_attendance.group_hr_attendance_use_pin') and (self.user_id and self.user_id.id != self._uid or not self.user_id):
if entered_pin != self.pin:
return {'warning': _('Wrong PIN')}
return self.attendance_action(next_action)
diff --git a/addons/hr_expense/views/hr_expense_views.xml b/addons/hr_expense/views/hr_expense_views.xml
index 03623c29fbf..773202963ef 100644
--- a/addons/hr_expense/views/hr_expense_views.xml
+++ b/addons/hr_expense/views/hr_expense_views.xml
@@ -562,7 +562,7 @@
- We would be delighted to assist you along the way. Contact us at
-
- help@odoo.com if you have any question. You can also discover
- how to get the best out of Odoo Project with our
-
+ We would be delighted to assist you along the way. Contact us through our
+ support form if you have any question.
+ You can also discover how to get the best out of Odoo Project with our
+
User Documentation
or with our
diff --git a/addons/project/views/project_views.xml b/addons/project/views/project_views.xml
index 2569283bb45..08f3b80c8c7 100644
--- a/addons/project/views/project_views.xml
+++ b/addons/project/views/project_views.xml
@@ -238,12 +238,10 @@
diff --git a/addons/web_editor/static/src/js/summernote.js b/addons/web_editor/static/src/js/summernote.js
index 5c344fbbcd1..9d7304caf75 100644
--- a/addons/web_editor/static/src/js/summernote.js
+++ b/addons/web_editor/static/src/js/summernote.js
@@ -134,7 +134,7 @@ dom.hasProgrammaticStyle = function (node) {
};
dom.mergeFilter = function (prev, cur, parent) {
// merge text nodes
- if (prev && (dom.isText(prev) || ("H1 H2 H3 H4 H5 H6 LI P".indexOf(prev.tagName) !== -1 && prev !== cur.parentNode)) && dom.isText(cur)) {
+ if (prev && (dom.isText(prev) || (['H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'LI', 'P'].indexOf(prev.tagName) !== -1 && prev !== cur.parentNode)) && dom.isText(cur)) {
return true;
}
if (prev && prev.tagName === "P" && dom.isText(cur)) {
diff --git a/addons/website/models/ir_http.py b/addons/website/models/ir_http.py
index f5054202f61..012802649f1 100644
--- a/addons/website/models/ir_http.py
+++ b/addons/website/models/ir_http.py
@@ -371,7 +371,7 @@ class PageConverter(werkzeug.routing.PathConverter):
query = query and query.startswith('website.') and query[8:] or query
if query:
domain += [('key', 'like', query)]
- website_id = request.context.get('website_id') or request.registry['website'].search(cr, uid, [], limit=1)[0]
+ website_id = request.context.get('website_id') or request.env['website'].search([], limit=1).id
domain += ['|', ('website_id', '=', website_id), ('website_id', '=', False)]
views = View.search_read(domain, fields=['key', 'priority', 'write_date'], order='name')
diff --git a/addons/website/models/website.py b/addons/website/models/website.py
index a747b85726b..f630eef13a9 100644
--- a/addons/website/models/website.py
+++ b/addons/website/models/website.py
@@ -527,7 +527,7 @@ class Website(models.Model):
of the same.
:rtype: list({name: str, url: str})
"""
- request.context = dict(request.context, **context)
+ request.context = dict(request.context, **self.env.context)
router = request.httprequest.app.get_db_router(request.db)
# Force enumeration to be performed as public user
url_set = set()
diff --git a/addons/website/static/src/less/website.snippets.less b/addons/website/static/src/less/website.snippets.less
index 1a290e65767..4a9e304299f 100644
--- a/addons/website/static/src/less/website.snippets.less
+++ b/addons/website/static/src/less/website.snippets.less
@@ -112,7 +112,6 @@ table.table_desc tr td {
height: 100%;
.item {
height: 100%;
- background-size: cover;
}
.carousel-control {
cursor: pointer;
diff --git a/addons/website/static/src/less/website.wrapwrap.less b/addons/website/static/src/less/website.wrapwrap.less
index 9151e26e7ba..e572a11a975 100644
--- a/addons/website/static/src/less/website.wrapwrap.less
+++ b/addons/website/static/src/less/website.wrapwrap.less
@@ -37,6 +37,16 @@ footer {
display: none!important;
}
+.o_text_overflow {
+ .text-overflow()
+}
+
+.o_div_text_overflow * > div {
+ // .text-overflow() we don't want wordwrap
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
// Odoo options classes
.jumbotron {
diff --git a/addons/website/views/website_templates.xml b/addons/website/views/website_templates.xml
index 6cce24534a4..c791d330435 100644
--- a/addons/website/views/website_templates.xml
+++ b/addons/website/views/website_templates.xml
@@ -77,7 +77,7 @@
- We would be delighted to assist you along the way. Contact us at
-
- help@odoo.com if you have any question. You can also discover
- how to get the best out of Odoo with our
+ We would be delighted to assist you along the way. Contact us through our
+ support form if you have any question.
+ You can also discover how to get the best out of Odoo with our
User Documentation
or with our
diff --git a/addons/website_portal/views/website_portal_templates.xml b/addons/website_portal/views/website_portal_templates.xml
index 67a240a8343..3e5924938a7 100644
--- a/addons/website_portal/views/website_portal_templates.xml
+++ b/addons/website_portal/views/website_portal_templates.xml
@@ -133,7 +133,7 @@
- Contact
+ Saleman
diff --git a/addons/website_portal_sale/models/payment.py b/addons/website_portal_sale/models/payment.py
index ec601dd1d36..d94b429bf18 100644
--- a/addons/website_portal_sale/models/payment.py
+++ b/addons/website_portal_sale/models/payment.py
@@ -16,8 +16,13 @@ class PaymentTransaction(models.Model):
def _generate_and_pay_invoice(self, tx, acquirer_name):
tx.sale_order_id._force_lines_to_invoice_policy_order()
- created_invoice = tx.sale_order_id.action_invoice_create()
- created_invoice = self.env['account.invoice'].browse(created_invoice)
+ # force company to ensure journals/accounts etc. are correct
+ # company_id needed for default_get on account.journal
+ # force_company needed for company_dependent fields
+ ctx_company = {'company_id': tx.sale_order_id.company_id.id,
+ 'force_company': tx.sale_order_id.company_id.id}
+ created_invoice = tx.sale_order_id.with_context(**ctx_company).action_invoice_create()
+ created_invoice = self.env['account.invoice'].browse(created_invoice).with_context(**ctx_company)
if created_invoice:
_logger.info('<%s> transaction completed, auto-generated invoice %s (ID %s) for %s (ID %s)',
diff --git a/addons/website_sale/__manifest__.py b/addons/website_sale/__manifest__.py
index 45fa7f8f8ec..a02e4627ce1 100644
--- a/addons/website_sale/__manifest__.py
+++ b/addons/website_sale/__manifest__.py
@@ -12,6 +12,8 @@ Odoo E-Commerce
""",
'depends': ['website', 'sale', 'payment', 'website_payment', 'website_portal_sale', 'website_mail', 'website_form', 'rating'],
'data': [
+ 'security/ir.model.access.csv',
+ 'security/website_sale.xml',
'data/data.xml',
'data/web_planner_data.xml',
'views/views.xml',
@@ -24,8 +26,6 @@ Odoo E-Commerce
'views/snippets.xml',
'views/report_shop_saleorder.xml',
'views/res_config_view.xml',
- 'security/ir.model.access.csv',
- 'security/website_sale.xml',
],
'demo': [
'data/demo.xml',
diff --git a/addons/website_sale/models/sale_order.py b/addons/website_sale/models/sale_order.py
index d22932915a0..1d7c24abcb1 100644
--- a/addons/website_sale/models/sale_order.py
+++ b/addons/website_sale/models/sale_order.py
@@ -302,6 +302,27 @@ class Website(models.Model):
DEFAULT_PAYMENT_TERM = 'account.account_payment_term_immediate'
return self.env.ref(DEFAULT_PAYMENT_TERM, False).id or partner.property_payment_term_id.id
+ @api.multi
+ def _prepare_sale_order_values(self, partner, pricelist):
+ self.ensure_one()
+ affiliate_id = request.session.get('affiliate_id')
+ salesperson_id = affiliate_id if self.env['res.users'].sudo().browse(affiliate_id).exists() else request.website.salesperson_id.id
+ addr = partner.address_get(['delivery', 'invoice'])
+ values = {
+ 'partner_id': partner.id,
+ 'pricelist_id': pricelist.id,
+ 'payment_term_id': self.sale_get_payment_term(partner),
+ 'team_id': self.salesteam_id.id,
+ 'partner_invoice_id': addr['invoice'],
+ 'partner_shipping_id': addr['delivery'],
+ 'user_id': salesperson_id or self.salesperson_id.id,
+ }
+ company = self.company_id or pricelist.company_id
+ if company:
+ values['company_id'] = company.id
+
+ return values
+
@api.multi
def sale_get_order(self, force_create=False, code=None, update_pricelist=False, force_pricelist=False):
""" Return the current sales order after mofications specified by params.
@@ -337,25 +358,8 @@ class Website(models.Model):
# create so if needed
if not sale_order and (force_create or code):
# TODO cache partner_id session
- affiliate_id = request.session.get('affiliate_id')
- if self.env['res.users'].sudo().browse(affiliate_id).exists():
- salesperson_id = affiliate_id
- else:
- salesperson_id = request.website.salesperson_id.id
- addr = partner.address_get(['delivery', 'invoice'])
- so_data = {
- 'partner_id': partner.id,
- 'pricelist_id': pricelist_id,
- 'payment_term_id': self.sale_get_payment_term(partner),
- 'team_id': self.salesteam_id.id,
- 'partner_invoice_id': addr['invoice'],
- 'partner_shipping_id': addr['delivery'],
- 'user_id': salesperson_id or self.salesperson_id.id,
- }
- company = self.company_id or self.env['product.pricelist'].browse(pricelist_id).sudo().company_id
- if company:
- so_data['company_id'] = company.id
-
+ pricelist = self.env['product.pricelist'].browse(pricelist_id).sudo()
+ so_data = self._prepare_sale_order_values(partner, pricelist)
sale_order = self.env['sale.order'].sudo().create(so_data)
# set fiscal position
diff --git a/addons/website_sale/static/src/js/website_sale.js b/addons/website_sale/static/src/js/website_sale.js
index 1205951b039..1bb49194f37 100644
--- a/addons/website_sale/static/src/js/website_sale.js
+++ b/addons/website_sale/static/src/js/website_sale.js
@@ -233,7 +233,7 @@ odoo.define('website_sale.website_sale', function (require) {
var precision = 2;
if ($(".decimal_precision").length) {
- precision = parseInt($(".decimal_precision").first().data('precision'));
+ precision = parseInt($(".decimal_precision").last().data('precision'));
}
var formatted = _.str.sprintf('%.' + precision + 'f', price).split('.');
formatted[0] = utils.insert_thousand_seps(formatted[0]);
diff --git a/addons/website_sale/views/templates.xml b/addons/website_sale/views/templates.xml
index 71b110dfca0..bec827eac68 100644
--- a/addons/website_sale/views/templates.xml
+++ b/addons/website_sale/views/templates.xml
@@ -1735,14 +1735,14 @@