diff --git a/addons/calendar/calendar.py b/addons/calendar/calendar.py index 6d575ba3425..94c35add5e3 100644 --- a/addons/calendar/calendar.py +++ b/addons/calendar/calendar.py @@ -1765,7 +1765,7 @@ class mail_message(osv.Model): if context is None: context = {} if doc_model == 'calendar.event': - order = context.get('order', self._order) + order = context.get('order', self.pool[doc_model]._order) for virtual_id in self.pool[doc_model].get_recurrent_ids(cr, uid, doc_dict.keys(), [], order=order, context=context): doc_dict.setdefault(virtual_id, doc_dict[get_real_ids(virtual_id)]) return super(mail_message, self)._find_allowed_model_wise(cr, uid, doc_model, doc_dict, context=context) diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py index c73d5e1dbea..afaad2934b3 100644 --- a/addons/crm/crm_lead.py +++ b/addons/crm/crm_lead.py @@ -656,9 +656,11 @@ class crm_lead(FormatAddress, osv.osv): return True def _lead_create_contact(self, cr, uid, lead, name, is_company, parent_id=False, context=None): + if context is None: + context = {} partner = self.pool.get('res.partner') vals = {'name': name, - 'user_id': lead.user_id.id, + 'user_id': context.get('default_user_id') or lead.user_id.id, 'comment': lead.description, 'team_id': lead.team_id.id or False, 'parent_id': parent_id, diff --git a/addons/crm/wizard/crm_lead_to_opportunity.py b/addons/crm/wizard/crm_lead_to_opportunity.py index b08d8445b3d..89cc00a1b6e 100644 --- a/addons/crm/wizard/crm_lead_to_opportunity.py +++ b/addons/crm/wizard/crm_lead_to_opportunity.py @@ -101,7 +101,7 @@ class crm_lead2opportunity_partner(osv.osv_memory): data = self.browse(cr, uid, ids, context=context)[0] leads = lead.browse(cr, uid, lead_ids, context=context) for lead_id in leads: - partner_id = self._create_partner(cr, uid, lead_id.id, data.action, partner_id or lead_id.partner_id.id, context=context) + partner_id = self._create_partner(cr, uid, lead_id.id, data.action, partner_id or lead_id.partner_id.id, context=dict(context, default_user_id=data.user_id.id)) res = lead.convert_opportunity(cr, uid, [lead_id.id], partner_id, [], False, context=context) user_ids = vals.get('user_ids', False) if context.get('no_force_assignation'): @@ -145,9 +145,6 @@ class crm_lead2opportunity_partner(osv.osv_memory): lead_ids = context.get('active_ids', []) vals.update({'lead_ids': lead_ids, 'user_ids': [w.user_id.id]}) self._convert_opportunity(cr, uid, ids, vals, context=context) - for lead in lead_obj.browse(cr, uid, lead_ids, context=context): - if lead.partner_id and lead.partner_id.user_id != lead.user_id: - partner_obj.write(cr, uid, [lead.partner_id.id], {'user_id': lead.user_id.id}, context=context) return self.pool.get('crm.lead').redirect_opportunity_view(cr, uid, lead_ids[0], context=context) diff --git a/addons/mass_mailing/data/mass_mailing_data.xml b/addons/mass_mailing/data/mass_mailing_data.xml index 6cb326ab9a4..ed4d7e40beb 100644 --- a/addons/mass_mailing/data/mass_mailing_data.xml +++ b/addons/mass_mailing/data/mass_mailing_data.xml @@ -27,5 +27,19 @@ Newsletter + + + Process Mass Mailing Queue + + + 60 + minutes + -1 + + mail.mass_mailing + _process_mass_mailing_queue + () + + \ No newline at end of file diff --git a/addons/mass_mailing/views/mass_mailing.xml b/addons/mass_mailing/views/mass_mailing.xml index 36df24f5492..13e379c3793 100644 --- a/addons/mass_mailing/views/mass_mailing.xml +++ b/addons/mass_mailing/views/mass_mailing.xml @@ -902,20 +902,6 @@ - - - Process Mass Mailing Queue - - - 60 - minutes - -1 - - mail.mass_mailing - _process_mass_mailing_queue - () - -
- + diff --git a/addons/product_margin/product_margin.py b/addons/product_margin/product_margin.py index 7c62a8a97aa..175d6885b1b 100644 --- a/addons/product_margin/product_margin.py +++ b/addons/product_margin/product_margin.py @@ -103,9 +103,8 @@ class product_product(osv.osv): res[val.id]['total_cost'] = result[2] and result[2] or 0.0 res[val.id]['normal_cost'] = prod.standard_price * res[val.id]['purchase_num_invoiced'] res[val.id]['purchase_gap'] = res[val.id]['normal_cost'] - res[val.id]['total_cost'] + res[val.id]['total_margin'] = res[val.id]['turnover'] - res[val.id]['total_cost'] - if 'total_margin' in field_names: - res[val.id]['total_margin'] = res[val.id]['turnover'] - res[val.id]['total_cost'] if 'expected_margin' in field_names: res[val.id]['expected_margin'] = res[val.id]['sale_expected'] - res[val.id]['normal_cost'] if 'total_margin_rate' in field_names: diff --git a/addons/product_margin/product_margin_view.xml b/addons/product_margin/product_margin_view.xml index 9b4eede75a4..bc58a051987 100644 --- a/addons/product_margin/product_margin_view.xml +++ b/addons/product_margin/product_margin_view.xml @@ -8,8 +8,7 @@ - - + @@ -74,7 +73,7 @@ - + diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml index e7c2583e88b..86bd3c1142b 100644 --- a/addons/project/project_view.xml +++ b/addons/project/project_view.xml @@ -215,7 +215,7 @@ project.project form [] - list,form + tree,form {} diff --git a/addons/purchase/purchase_view.xml b/addons/purchase/purchase_view.xml index 6a962c80b05..4d91080967c 100644 --- a/addons/purchase/purchase_view.xml +++ b/addons/purchase/purchase_view.xml @@ -322,7 +322,7 @@ - + diff --git a/addons/purchase/tests/test_purchase_order.py b/addons/purchase/tests/test_purchase_order.py index 88848cfcdb1..4c723b320cb 100644 --- a/addons/purchase/tests/test_purchase_order.py +++ b/addons/purchase/tests/test_purchase_order.py @@ -76,10 +76,11 @@ class TestPurchaseOrder(AccountingTestCase): self.picking.do_new_transfer() self.assertEqual(self.po.order_line.mapped('qty_received'), [5.0, 5.0], 'Purchase: all products should be received"') - self.invoice = self.AccountInvoice.create({ - 'partner_id': self.partner_id.id, - 'purchase_id': self.po.id, - 'account_id': self.partner_id.property_account_payable_id.id, - }) + self.invoice = self.AccountInvoice.with_context( + type='in_invoice').create({ + 'partner_id': self.partner_id.id, + 'purchase_id': self.po.id, + 'account_id': self.partner_id.property_account_payable_id.id, + }) self.invoice.purchase_order_change() self.assertEqual(self.po.order_line.mapped('qty_invoiced'), [5.0, 5.0], 'Purchase: all products should be invoiced"') diff --git a/addons/web_editor/static/src/js/snippets.editor.js b/addons/web_editor/static/src/js/snippets.editor.js index 51cc5a31615..727b4818734 100644 --- a/addons/web_editor/static/src/js/snippets.editor.js +++ b/addons/web_editor/static/src/js/snippets.editor.js @@ -144,7 +144,7 @@ var BuildingBlock = Widget.extend({ return $from.closest(selector, parentNode); }, all: function ($from) { - return $from ? $from.find(selector) : $(selector); + return $from ? cssFind($from, selector) : $(selector); }, is: function ($from) { return $from.is(selector); @@ -167,15 +167,31 @@ var BuildingBlock = Widget.extend({ }); }, all: is_children ? function ($from) { - return ($from || self.$editable).find(selector); + return cssFind($from || self.$editable, selector); } : function ($from) { - return $from ? $from.find(selector) : self.$editable.filter(selector).add(self.$editable.find(selector)); + $from = $from || self.$editable; + return $from.filter(selector).add(cssFind($from, selector)); }, is: function ($from) { return $from.is(selector); } }; } + + /** + * jQuery find function behavior is: + * $('A').find('A B') <=> $('A A B') + * The searches behavior to find options' DOM needs to be + * $('A').find('A B') <=> $('A B') + * This is what this function does. + * + * @param {jQuery} $from - the jQuery element(s) from which to search + * @param {string} selector - the CSS selector to match + * @returns {jQuery} + */ + function cssFind($from, selector) { + return $from.find('*').filter(selector); + } }, fetch_snippet_templates: function () { diff --git a/addons/website_form/static/src/js/website_form.js b/addons/website_form/static/src/js/website_form.js index ad5dcaa5cb7..f3ccc9142d4 100644 --- a/addons/website_form/static/src/js/website_form.js +++ b/addons/website_form/static/src/js/website_form.js @@ -158,13 +158,15 @@ odoo.define('website_form.animation', function (require) { // Special cases for dates and datetimes } else if ($(input).hasClass('o_website_form_date')) { - return !self.is_datetime_valid(input.value, 'date'); + if (!self.is_datetime_valid(input.value, 'date')) { + return true; + } } else if ($(input).hasClass('o_website_form_datetime')) { - return !self.is_datetime_valid(input.value, 'datetime'); - - } else { - return !input.checkValidity(); + if (!self.is_datetime_valid(input.value, 'datetime')) { + return true; + } } + return !input.checkValidity(); }) // Update field color if invalid or erroneous diff --git a/addons/website_mail/controllers/main.py b/addons/website_mail/controllers/main.py index ca7678a458e..6272e75533b 100644 --- a/addons/website_mail/controllers/main.py +++ b/addons/website_mail/controllers/main.py @@ -63,6 +63,7 @@ def _message_post_helper(res_model='', res_id=None, message='', token='', token_ record = record.sudo() else: raise NotFound() + kw.pop('csrf_token', None) return record.with_context(mail_create_nosubscribe=nosubscribe).message_post(body=message, message_type=kw.pop('message_type', "comment"), subtype=kw.pop('subtype', "mt_comment"), diff --git a/addons/website_sale/models/sale_order.py b/addons/website_sale/models/sale_order.py index a9d5fcd41a4..68425099993 100644 --- a/addons/website_sale/models/sale_order.py +++ b/addons/website_sale/models/sale_order.py @@ -333,6 +333,9 @@ class Website(models.Model): partner.write({'last_website_so_id': sale_order.id}) if sale_order: + # case when user emptied the cart + if not request.session.get('sale_order_id'): + request.session['sale_order_id'] = sale_order.id # check for change of pricelist with a coupon pricelist_id = pricelist_id or partner.property_product_pricelist.id diff --git a/doc/cla/corporate/bloopark.md b/doc/cla/corporate/bloopark.md index 2664bbe3006..f6eeb53698b 100644 --- a/doc/cla/corporate/bloopark.md +++ b/doc/cla/corporate/bloopark.md @@ -18,3 +18,4 @@ Benjamin Bachmann bBachmann@bloopark.de https://github.com/benniphx Robert Rübner rruebner@bloopark.de https://github.com/rruebner Florian Fischer ffischer@bloopark.de https://github.com/florianfischer Mercerdes Scenna mscenna@bloopark.de https://github.com/mscenna +Andrei Poehlmann andrei.poehlmann90@gmail.com https://github.com/reinka diff --git a/doc/cla/corporate/eficent.md b/doc/cla/corporate/eficent.md new file mode 100644 index 00000000000..3723fbf0740 --- /dev/null +++ b/doc/cla/corporate/eficent.md @@ -0,0 +1,19 @@ +Spain, 2017-03-21 + +Eficent Business and IT Consulting Services, S.L. agrees to the terms of the +Odoo Corporate Contributor License Agreement v1.0. + +I declare that I am authorized and able to make this agreement and sign this +declaration. + +Signed, + +Jordi Ballester jordi.ballester@eficent.com https://github.com/jbeficent + +List of contributors: + +Aarón Henríquez ahenriquez@eficent.com https://github.com/aheficent +Lois Rilo lois.rilo@eficent.com https://github.com/lreficent +Gisela Mora gisela.mora@eficent.com https://github.com/gmeficent +Miquel Raich miquel.raich@eficent.com https://github.com/mreficent +Jordi Ballester jordi.ballester@eficent.com https://github.com/jbeficent diff --git a/openerp/addons/base/ir/ir_translation.py b/openerp/addons/base/ir/ir_translation.py index 67e48ec8801..26dcd40f406 100644 --- a/openerp/addons/base/ir/ir_translation.py +++ b/openerp/addons/base/ir/ir_translation.py @@ -562,6 +562,9 @@ class IrTranslation(models.Model): # (trans.value -> trans.src) gives the original value back value0 = field.translate(lambda term: None, record[fname]) value1 = field.translate({trans.src: trans.value}.get, value0) + # don't check the reverse if no translation happened + if value0 == value1: + continue value2 = field.translate({trans.value: trans.src}.get, value1) if value2 != value0: raise ValidationError(_("Translation is not valid:\n%s") % trans.value) diff --git a/openerp/models.py b/openerp/models.py index 10e95b0642d..14cabe2ca00 100644 --- a/openerp/models.py +++ b/openerp/models.py @@ -5185,7 +5185,7 @@ class BaseModel(object): # duplicated record is not linked to any module del record['module'] record.update({'res_id': target_id}) - if user_lang and user_lang == record['lang']: + if user_lang and user_lang == record['lang'] and field.translate is True: # 'source' to force the call to _set_src # 'value' needed if value is changed in copy(), want to see the new_value record['source'] = old_record[field_name]