[MERGE] forward port of branch saas-3 up to 8c4a7cb
This commit is contained in:
commit
f7723037d6
|
@ -15,6 +15,9 @@ _build/
|
||||||
status
|
status
|
||||||
# odoo filestore
|
# odoo filestore
|
||||||
openerp/filestore
|
openerp/filestore
|
||||||
|
# maintenance migration scripts
|
||||||
|
openerp/addons/base/maintenance
|
||||||
|
|
||||||
# generated for windows installer?
|
# generated for windows installer?
|
||||||
install/win32/*.bat
|
install/win32/*.bat
|
||||||
install/win32/meta.py
|
install/win32/meta.py
|
||||||
|
|
|
@ -720,7 +720,7 @@ class account_invoice(models.Model):
|
||||||
for tax in self.tax_line:
|
for tax in self.tax_line:
|
||||||
if tax.manual:
|
if tax.manual:
|
||||||
continue
|
continue
|
||||||
key = (tax.tax_code_id.id, tax.base_code_id.id, tax.account_id.id, tax.account_analytic_id.id)
|
key = (tax.tax_code_id.id, tax.base_code_id.id, tax.account_id.id)
|
||||||
tax_key.append(key)
|
tax_key.append(key)
|
||||||
if key not in compute_taxes:
|
if key not in compute_taxes:
|
||||||
raise except_orm(_('Warning!'), _('Global taxes defined, but they are not in invoice lines !'))
|
raise except_orm(_('Warning!'), _('Global taxes defined, but they are not in invoice lines !'))
|
||||||
|
@ -1560,7 +1560,15 @@ class account_invoice_tax(models.Model):
|
||||||
val['account_id'] = tax['account_paid_id'] or line.account_id.id
|
val['account_id'] = tax['account_paid_id'] or line.account_id.id
|
||||||
val['account_analytic_id'] = tax['account_analytic_paid_id']
|
val['account_analytic_id'] = tax['account_analytic_paid_id']
|
||||||
|
|
||||||
key = (val['tax_code_id'], val['base_code_id'], val['account_id'], val['account_analytic_id'])
|
# If the taxes generate moves on the same financial account as the invoice line
|
||||||
|
# and no default analytic account is defined at the tax level, propagate the
|
||||||
|
# analytic account from the invoice line to the tax line. This is necessary
|
||||||
|
# in situations were (part of) the taxes cannot be reclaimed,
|
||||||
|
# to ensure the tax move is allocated to the proper analytic account.
|
||||||
|
if not val.get('account_analytic_id') and line.account_analytic_id and val['account_id'] == line.account_id.id:
|
||||||
|
val['account_analytic_id'] = line.account_analytic_id.id
|
||||||
|
|
||||||
|
key = (val['tax_code_id'], val['base_code_id'], val['account_id'])
|
||||||
if not key in tax_grouped:
|
if not key in tax_grouped:
|
||||||
tax_grouped[key] = val
|
tax_grouped[key] = val
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -230,8 +230,8 @@ class base_action_rule(osv.osv):
|
||||||
ids = self.search(cr, SUPERUSER_ID, [])
|
ids = self.search(cr, SUPERUSER_ID, [])
|
||||||
for action_rule in self.browse(cr, SUPERUSER_ID, ids):
|
for action_rule in self.browse(cr, SUPERUSER_ID, ids):
|
||||||
model = action_rule.model_id.model
|
model = action_rule.model_id.model
|
||||||
model_obj = self.pool[model]
|
model_obj = self.pool.get(model)
|
||||||
if not hasattr(model_obj, 'base_action_ruled'):
|
if model_obj and not hasattr(model_obj, 'base_action_ruled'):
|
||||||
# monkey-patch methods create and write
|
# monkey-patch methods create and write
|
||||||
model_obj._patch_method('create', make_create())
|
model_obj._patch_method('create', make_create())
|
||||||
model_obj._patch_method('write', make_write())
|
model_obj._patch_method('write', make_write())
|
||||||
|
|
|
@ -36,7 +36,6 @@ class grant_badge_wizard(osv.TransientModel):
|
||||||
def action_grant_badge(self, cr, uid, ids, context=None):
|
def action_grant_badge(self, cr, uid, ids, context=None):
|
||||||
"""Wizard action for sending a badge to a chosen user"""
|
"""Wizard action for sending a badge to a chosen user"""
|
||||||
|
|
||||||
badge_obj = self.pool.get('gamification.badge')
|
|
||||||
badge_user_obj = self.pool.get('gamification.badge.user')
|
badge_user_obj = self.pool.get('gamification.badge.user')
|
||||||
|
|
||||||
for wiz in self.browse(cr, uid, ids, context=context):
|
for wiz in self.browse(cr, uid, ids, context=context):
|
||||||
|
@ -51,6 +50,6 @@ class grant_badge_wizard(osv.TransientModel):
|
||||||
'comment': wiz.comment,
|
'comment': wiz.comment,
|
||||||
}
|
}
|
||||||
badge_user = badge_user_obj.create(cr, uid, values, context=context)
|
badge_user = badge_user_obj.create(cr, uid, values, context=context)
|
||||||
result = badge_obj._send_badge(cr, uid, badge_user, context=context)
|
result = badge_user_obj._send_badge(cr, uid, badge_user, context=context)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
|
@ -315,14 +315,14 @@
|
||||||
<separator string="Previous Activities"/>
|
<separator string="Previous Activities"/>
|
||||||
<field name="from_ids" mode="tree" context="{'default_activity_to_id': active_id}">
|
<field name="from_ids" mode="tree" context="{'default_activity_to_id': active_id}">
|
||||||
<tree string="Incoming Transitions" editable="bottom">
|
<tree string="Incoming Transitions" editable="bottom">
|
||||||
<field name="activity_from_id" domain="[('campaign_id', '=', parent.campaign_id)]"/>
|
<field name="activity_from_id" domain="[('campaign_id', '=', parent.campaign_id)]" options="{'no_create': True}" />
|
||||||
<field name='trigger'/>
|
<field name='trigger'/>
|
||||||
<field name="interval_nbr"/>
|
<field name="interval_nbr"/>
|
||||||
<field name="interval_type"/>
|
<field name="interval_type"/>
|
||||||
</tree>
|
</tree>
|
||||||
<form string="Incoming Transitions">
|
<form string="Incoming Transitions">
|
||||||
<group col="4">
|
<group col="4">
|
||||||
<field name="activity_from_id" domain="[('campaign_id', '=', parent.campaign_id)]"/>
|
<field name="activity_from_id" domain="[('campaign_id', '=', parent.campaign_id)]" options="{'no_create': True}" />
|
||||||
<field name='trigger'/>
|
<field name='trigger'/>
|
||||||
<field name="interval_nbr"/>
|
<field name="interval_nbr"/>
|
||||||
<field name="interval_type"/>
|
<field name="interval_type"/>
|
||||||
|
@ -332,14 +332,14 @@
|
||||||
<separator string="Next Activities"/>
|
<separator string="Next Activities"/>
|
||||||
<field name="to_ids" mode="tree" context="{'default_activity_from_id': active_id}">
|
<field name="to_ids" mode="tree" context="{'default_activity_from_id': active_id}">
|
||||||
<tree string="Outgoing Transitions" editable="bottom">
|
<tree string="Outgoing Transitions" editable="bottom">
|
||||||
<field name="activity_to_id" domain="[('campaign_id', '=', parent.campaign_id)]"/>
|
<field name="activity_to_id" domain="[('campaign_id', '=', parent.campaign_id)]" options="{'no_create': True}" />
|
||||||
<field name='trigger'/>
|
<field name='trigger'/>
|
||||||
<field name="interval_nbr"/>
|
<field name="interval_nbr"/>
|
||||||
<field name="interval_type"/>
|
<field name="interval_type"/>
|
||||||
</tree>
|
</tree>
|
||||||
<form string="Outgoing Transitions">
|
<form string="Outgoing Transitions">
|
||||||
<group col="4">
|
<group col="4">
|
||||||
<field name="activity_to_id" domain="[('campaign_id', '=', parent.campaign_id)]"/>
|
<field name="activity_to_id" domain="[('campaign_id', '=', parent.campaign_id)]" options="{'no_create': True}" />
|
||||||
<field name='trigger'/>
|
<field name='trigger'/>
|
||||||
<field name="interval_nbr"/>
|
<field name="interval_nbr"/>
|
||||||
<field name="interval_type"/>
|
<field name="interval_type"/>
|
||||||
|
|
|
@ -113,7 +113,7 @@ class AcquirerPaypal(osv.Model):
|
||||||
paypal_tx_values.update({
|
paypal_tx_values.update({
|
||||||
'cmd': '_xclick',
|
'cmd': '_xclick',
|
||||||
'business': acquirer.paypal_email_account,
|
'business': acquirer.paypal_email_account,
|
||||||
'item_name': tx_values['reference'],
|
'item_name': '%s: %s' % (acquirer.company_id.name, tx_values['reference']),
|
||||||
'item_number': tx_values['reference'],
|
'item_number': tx_values['reference'],
|
||||||
'amount': tx_values['amount'],
|
'amount': tx_values['amount'],
|
||||||
'currency_code': tx_values['currency'] and tx_values['currency'].name or '',
|
'currency_code': tx_values['currency'] and tx_values['currency'].name or '',
|
||||||
|
|
|
@ -590,7 +590,9 @@ class product_template(osv.osv):
|
||||||
if ptype != 'standard_price':
|
if ptype != 'standard_price':
|
||||||
res[product.id] = product[ptype] or 0.0
|
res[product.id] = product[ptype] or 0.0
|
||||||
else:
|
else:
|
||||||
res[product.id] = product.sudo()[ptype]
|
company_id = self.pool['res.users'].read(cr, uid, uid, ['company_id'], context=context)[0]
|
||||||
|
product = product.with_context(force_company=company_id)
|
||||||
|
res[product.id] = res[product.id] = product.sudo()[ptype]
|
||||||
if ptype == 'list_price':
|
if ptype == 'list_price':
|
||||||
res[product.id] += product._name == "product.product" and product.price_extra or 0.0
|
res[product.id] += product._name == "product.product" and product.price_extra or 0.0
|
||||||
if 'uom' in context:
|
if 'uom' in context:
|
||||||
|
|
|
@ -272,7 +272,7 @@ class project_issue(osv.Model):
|
||||||
'progress': fields.function(_hours_get, string='Progress (%)', multi='hours', group_operator="avg", help="Computed as: Time Spent / Total Time.",
|
'progress': fields.function(_hours_get, string='Progress (%)', multi='hours', group_operator="avg", help="Computed as: Time Spent / Total Time.",
|
||||||
store = {
|
store = {
|
||||||
'project.issue': (lambda self, cr, uid, ids, c={}: ids, ['task_id'], 10),
|
'project.issue': (lambda self, cr, uid, ids, c={}: ids, ['task_id'], 10),
|
||||||
'project.task': (_get_issue_task, ['progress'], 10),
|
'project.task': (_get_issue_task, ['work_ids', 'remaining_hours', 'planned_hours', 'state', 'stage_id'], 10),
|
||||||
'project.task.work': (_get_issue_work, ['hours'], 10),
|
'project.task.work': (_get_issue_work, ['hours'], 10),
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
@ -535,7 +535,7 @@ class project_project(osv.Model):
|
||||||
if use_tasks and not use_issues:
|
if use_tasks and not use_issues:
|
||||||
values['alias_model'] = 'project.task'
|
values['alias_model'] = 'project.task'
|
||||||
elif not use_tasks and use_issues:
|
elif not use_tasks and use_issues:
|
||||||
values['alias_model'] = 'project.issues'
|
values['alias_model'] = 'project.issue'
|
||||||
return {'value': values}
|
return {'value': values}
|
||||||
|
|
||||||
def create(self, cr, uid, vals, context=None):
|
def create(self, cr, uid, vals, context=None):
|
||||||
|
|
|
@ -4389,28 +4389,23 @@ instance.web.form.One2ManyListView = instance.web.ListView.extend({
|
||||||
this.o2m.trigger_on_change();
|
this.o2m.trigger_on_change();
|
||||||
},
|
},
|
||||||
is_valid: function () {
|
is_valid: function () {
|
||||||
var editor = this.editor;
|
var self = this;
|
||||||
var form = editor.form;
|
if (!this.editable()){
|
||||||
// If no edition is pending, the listview can not be invalid (?)
|
|
||||||
if (!editor.record) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// If the form has not been modified, the view can only be valid
|
|
||||||
// NB: is_dirty will also be set on defaults/onchanges/whatever?
|
|
||||||
// oe_form_dirty seems to only be set on actual user actions
|
|
||||||
if (!form.$el.is('.oe_form_dirty')) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
this.o2m._dirty_flag = true;
|
this.o2m._dirty_flag = true;
|
||||||
|
var r;
|
||||||
// Otherwise validate internal form
|
return _.every(this.records.records, function(record){
|
||||||
return _(form.fields).chain()
|
r = record;
|
||||||
.invoke(function () {
|
_.each(self.editor.form.fields, function(field){
|
||||||
this._check_css_flags();
|
field.set_value(r.attributes[field.name]);
|
||||||
return this.is_valid();
|
});
|
||||||
})
|
return _.every(self.editor.form.fields, function(field){
|
||||||
.all(_.identity)
|
field.process_modifiers();
|
||||||
.value();
|
field._check_css_flags();
|
||||||
|
return field.is_valid();
|
||||||
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
do_add_record: function () {
|
do_add_record: function () {
|
||||||
if (this.editable()) {
|
if (this.editable()) {
|
||||||
|
|
Loading…
Reference in New Issue