[MERGE] Forward-port 9.0 up to 75e03c0f76
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -27,5 +27,19 @@
|
||||
<field name="name">Newsletter</field>
|
||||
</record>
|
||||
|
||||
<!-- Cron that process the mass mailing queue -->
|
||||
<record id="ir_cron_mass_mailing_queue" model="ir.cron">
|
||||
<field name="name">Process Mass Mailing Queue</field>
|
||||
<field eval="True" name="active" />
|
||||
<field name="user_id" ref="base.user_root" />
|
||||
<field name="interval_number">60</field>
|
||||
<field name="interval_type">minutes</field>
|
||||
<field name="numbercall">-1</field>
|
||||
<field eval="False" name="doall" />
|
||||
<field name="model">mail.mass_mailing</field>
|
||||
<field name="function">_process_mass_mailing_queue</field>
|
||||
<field name="args">()</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -902,20 +902,6 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Cron that process the mass mailing queue -->
|
||||
<record id="ir_cron_mass_mailing_queue" model="ir.cron">
|
||||
<field name="name">Process Mass Mailing Queue</field>
|
||||
<field eval="True" name="active" />
|
||||
<field name="user_id" ref="base.user_root" />
|
||||
<field name="interval_number">60</field>
|
||||
<field name="interval_type">minutes</field>
|
||||
<field name="numbercall">-1</field>
|
||||
<field eval="False" name="doall" />
|
||||
<field name="model">mail.mass_mailing</field>
|
||||
<field name="function">_process_mass_mailing_queue</field>
|
||||
<field name="args">()</field>
|
||||
</record>
|
||||
|
||||
<menuitem name="Campaigns" id="menu_email_campaigns"
|
||||
parent="mass_mailing_menu_root" sequence="5"
|
||||
action="action_view_mass_mailing_campaigns"
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<field name="arch" type="xml">
|
||||
<form string="Pay Order">
|
||||
<group>
|
||||
<field name="journal_id" />
|
||||
<field name="journal_id" domain="[('journal_user', '=', True)]"/>
|
||||
<field name="amount" />
|
||||
<field name="payment_name"/>
|
||||
</group>
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -8,8 +8,7 @@
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Product Margins" type="bar">
|
||||
<field name="product_tmpl_id"/>
|
||||
<field name="turnover" operator="+"/>
|
||||
<field name="total_cost" operator="+"/>
|
||||
<field name="total_margin" type="measure" operator="+"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
@@ -74,7 +73,7 @@
|
||||
<field name="sales_gap" sum="Sales Gap"/>
|
||||
<field name="total_cost" sum="Total Cost"/>
|
||||
<field name="purchase_num_invoiced" string="#Purchased"/>
|
||||
<field name="total_margin"/>
|
||||
<field name="total_margin" sum="Total Margin"/>
|
||||
<field name="expected_margin"/>
|
||||
<field name="total_margin_rate" widget="progressbar"/>
|
||||
<field name="expected_margin_rate" widget="progressbar"/>
|
||||
|
||||
@@ -215,7 +215,7 @@
|
||||
<field name="res_model">project.project</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="domain">[]</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="search_view_id" ref="view_project_project_filter"/>
|
||||
<field name="context">{}</field>
|
||||
<field name="help" type="html">
|
||||
|
||||
@@ -322,7 +322,7 @@
|
||||
<separator/>
|
||||
<filter name="not_invoiced" string="Not Invoiced" domain="[('invoice_status','=', 'to invoice')]" help="Purchase orders that include lines not invoiced."/>
|
||||
<filter name="invoiced" string="Invoiced" domain="[('invoice_status','=', 'invoiced')]" help="Purchase orders that include lines not invoiced."/>
|
||||
<filter string="New Mail" name="message_unread" domain="[('message_unread','=',True)]"/>
|
||||
<filter string="Unread Messages" name="message_needaction" domain="[('message_needaction','=',True)]"/>
|
||||
<group expand="0" string="Group By">
|
||||
<filter string="Vendor" domain="[]" context="{'group_by':'partner_id'}"/>
|
||||
<filter string="Order Date" domain="[]" context="{'group_by':'date_order'}"/>
|
||||
|
||||
@@ -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"')
|
||||
|
||||
@@ -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 () {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
+1
-1
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user