[MERGE] forward port of branch saas-5 up to 9e8e365

This commit is contained in:
Christophe Simonis 2014-06-25 12:44:13 +02:00
commit 1eaa69d342
34 changed files with 287 additions and 117 deletions

View File

@ -139,6 +139,13 @@
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
</record>
<record id="account_subscription_line_comp_rule" model="ir.rule">
<field name="name">Account subscription line company rule</field>
<field name="model_id" ref="model_account_subscription_line"/>
<field name="global" eval="True"/>
<field name="domain_force">['|',('subscription_id.model_id.company_id','=',False),('subscription_id.model_id.company_id','child_of',[user.company_id.id])]</field>
</record>
<record model="ir.rule" id="account_invoice_line_comp_rule">
<field name="name">Invoice Line company rule</field>
<field name="model_id" ref="model_account_invoice_line"/>

View File

@ -36,11 +36,11 @@ class account_subscription_generate(osv.osv_memory):
def action_generate(self, cr, uid, ids, context=None):
mod_obj = self.pool.get('ir.model.data')
act_obj = self.pool.get('ir.actions.act_window')
sub_line_obj = self.pool.get('account.subscription.line')
moves_created=[]
for data in self.read(cr, uid, ids, context=context):
cr.execute('select id from account_subscription_line where date<%s and move_id is null', (data['date'],))
line_ids = map(lambda x: x[0], cr.fetchall())
moves = self.pool.get('account.subscription.line').move_create(cr, uid, line_ids, context=context)
line_ids = sub_line_obj.search(cr, uid, [('date', '<', data['date']), ('move_id', '=', False)], context=context)
moves = sub_line_obj.move_create(cr, uid, line_ids, context=context)
moves_created.extend(moves)
result = mod_obj.get_object_reference(cr, uid, 'account', 'action_move_line_form')
id = result and result[1] or False

View File

@ -1,22 +1,53 @@
# -*- coding: utf-8 -*-
import openerp
from openerp import SUPERUSER_ID
from openerp.addons.web import http
from openerp.addons.web.http import request
from werkzeug.wrappers import BaseResponse as Response
import json
class website_gengo(http.Controller):
def get_gengo_key(self, cr):
icp = request.registry['ir.config_parameter']
return icp.get_param(cr, SUPERUSER_ID, request.registry['base.gengo.translations'].GENGO_KEY, default="")
@http.route('/website/gengo_callback', type='http', auth='none')
def gengo_callback(self,**post):
def gengo_callback(self, **post):
cr, uid, context = request.cr, openerp.SUPERUSER_ID, request.context
translation_pool = request.registry['ir.translation']
if post and post.get('job'):
job = json.loads(post['job'])
if post and post.get('job') and post.get('pgk'):
if post.get('pgk') != self.get_gengo_key(cr):
return Response("Bad authentication - 403/412", status=412)
job = json.loads(post['job'], 'utf-8')
tid = job.get('custom_data', False)
if (job.get('status') == 'approved') and tid:
term = translation_pool.browse(cr, uid, int(tid), context=context)
if term.job_id <> job.get('job_id'):
raise 'Error'
vals = {'state': 'translated', 'value': job.get('body_tgt')}
translation_pool.write(cr, uid, [int(tid)], vals, context=context)
if term.src != job.get('body_src'):
return Response("Text Altered - Not saved", status=100)
domain = [
'|',
('id', "=", int(tid)),
'&', '&', '&', '&', '&',
('state', '=', term.state),
('gengo_translation', '=', term.gengo_translation),
('src', "=", term.src),
('type', "=", term.type),
('name', "=", term.name),
('lang', "=", term.lang),
#('order_id', "=", term.order_id),
]
all_ir_tanslations = translation_pool.search(cr, uid, domain, context=context or {})
if all_ir_tanslations:
vals = {'state': 'translated', 'value': job.get('body_tgt')}
translation_pool.write(cr, uid, all_ir_tanslations, vals, context=context)
return Response("OK", status=200)
else:
return Response("No terms found", status=104)
return Response("Not saved", status=100)

View File

@ -8,6 +8,7 @@
<field name="interval_number">6</field>
<field name="interval_type">hours</field>
<field name="numbercall">-1</field>
<field name="doall">0</field>
<field eval="'base.gengo.translations'" name="model"></field>
<field eval="'_sync_response'" name="function"/>
<field eval="'(20,)'" name="args"/>
@ -20,6 +21,7 @@
<field name="interval_number">6</field>
<field name="interval_type">hours</field>
<field name="numbercall">-1</field>
<field name="doall">0</field>
<field eval="'base.gengo.translations'" name="model"></field>
<field eval="'_sync_request'" name="function"/>
<field eval="'(20,)'" name="args"/>

View File

@ -56,16 +56,18 @@ LANG_CODE_MAPPING = {
'fi_FI': ('fi', 'Finnish')
}
class ir_translation(osv.Model):
_name = "ir.translation"
_inherit = "ir.translation"
_columns = {
'gengo_comment': fields.text("Comments & Activity Linked to Gengo"),
'job_id': fields.char('Gengo Job ID', size=32),
'order_id': fields.char('Gengo Order ID', size=32),
"gengo_translation": fields.selection([('machine', 'Translation By Machine'),
('standard', 'Standard'),
('pro', 'Pro'),
('ultra', 'Ultra')], "Gengo Translation Service Level", help='You can select here the service level you want for an automatic translation using Gengo.'),
('standard', 'Standard'),
('pro', 'Pro'),
('ultra', 'Ultra')], "Gengo Translation Service Level", help='You can select here the service level you want for an automatic translation using Gengo.'),
}
def _get_all_supported_languages(self, cr, uid, context=None):
@ -83,3 +85,19 @@ class ir_translation(osv.Model):
def _get_gengo_corresponding_language(cr, lang):
return lang in LANG_CODE_MAPPING and LANG_CODE_MAPPING[lang][0] or lang
def _get_source_query(self, cr, uid, name, types, lang, source, res_id):
query, params = super(ir_translation, self)._get_source_query(cr, uid, name, types, lang, source, res_id)
query += """
ORDER BY
CASE
WHEN gengo_translation=%s then 10
WHEN gengo_translation=%s then 20
WHEN gengo_translation=%s then 30
WHEN gengo_translation=%s then 40
ELSE 0
END DESC
"""
params += ('machine', 'standard', 'ultra', 'pro',)
return (query, params)

View File

@ -19,12 +19,13 @@
#
##############################################################################
import uuid
import logging
import re
import time
from openerp.osv import osv, fields
from openerp import tools
from openerp import tools, SUPERUSER_ID
from openerp.tools.translate import _
_logger = logging.getLogger(__name__)
@ -36,7 +37,9 @@ except ImportError:
GENGO_DEFAULT_LIMIT = 20
class base_gengo_translations(osv.osv_memory):
GENGO_KEY = "Gengo.UUID"
_name = 'base.gengo.translations'
_columns = {
@ -46,9 +49,20 @@ class base_gengo_translations(osv.osv_memory):
'lang_id': fields.many2one('res.lang', 'Language', required=True),
'sync_limit': fields.integer("No. of terms to sync"),
}
_defaults = {'sync_type' : 'both',
'sync_limit' : 20
}
_defaults = {
'sync_type': 'both',
'sync_limit': 20
}
def init(self, cr):
icp = self.pool['ir.config_parameter']
if not icp.get_param(cr, SUPERUSER_ID, self.GENGO_KEY, default=None):
icp.set_param(cr, SUPERUSER_ID, self.GENGO_KEY, str(uuid.uuid4()))
def get_gengo_key(self, cr):
icp = self.pool['ir.config_parameter']
return icp.get_param(cr, SUPERUSER_ID, self.GENGO_KEY, default="Undefined")
def gengo_authentication(self, cr, uid, context=None):
'''
This method tries to open a connection with Gengo. For that, it uses the Public and Private
@ -113,48 +127,68 @@ class base_gengo_translations(osv.osv_memory):
_logger.warning("%s", gengo)
else:
offset = 0
all_translation_ids = translation_pool.search(cr, uid, [('state', '=', 'inprogress'), ('gengo_translation', 'in', ('machine', 'standard', 'pro', 'ultra')), ('job_id', "!=", False)], context=context)
all_translation_ids = translation_pool.search(cr, uid, [('state', '=', 'inprogress'), ('gengo_translation', 'in', ('machine', 'standard', 'pro', 'ultra')), ('order_id', "!=", False)], context=context)
while True:
translation_ids = all_translation_ids[offset:offset + limit]
offset += limit
if not translation_ids:
break
terms_progress = {
'gengo_order_ids': set(),
'ir_translation_ids': set(),
}
translation_terms = translation_pool.browse(cr, uid, translation_ids, context=context)
gengo_job_id = [term.job_id for term in translation_terms]
if gengo_job_id:
gengo_ids = ','.join(gengo_job_id)
for term in translation_terms:
terms_progress['gengo_order_ids'].add(term.order_id)
terms_progress['ir_translation_ids'].add(tools.ustr(term.id))
for order_id in terms_progress['gengo_order_ids']:
order_response = gengo.getTranslationOrderJobs(id=order_id)
jobs_approved = order_response.get('response', []).get('order', []).get('jobs_approved', [])
gengo_ids = ','.join(jobs_approved)
if gengo_ids: # Need to check, because getTranslationJobBatch don't catch this case and so call the getTranslationJobs because no ids in url
try:
job_response = gengo.getTranslationJobBatch(id=gengo_ids)
except:
continue
if job_response['opstat'] == 'ok':
for job in job_response['response'].get('jobs', []):
self._update_terms_job(cr, uid, job, context=context)
if job.get('custom_data') in terms_progress['ir_translation_ids']:
self._update_terms_job(cr, uid, job, context=context)
return True
def _update_terms_job(self, cr, uid, job, context=None):
translation_pool = self.pool.get('ir.translation')
tid = int(job['custom_data'])
vals = {}
if job.get('job_id', False):
vals['job_id'] = job['job_id']
if job.get('status', False) in ('queued', 'available', 'pending', 'reviewable'):
vals['state'] = 'inprogress'
if job.get('status', False) in ('queued','available','pending','reviewable'):
vals['state'] = 'inprogress'
if job.get('body_tgt', False) and job.get('status', False)=='approved':
if job.get('body_tgt', False) and job.get('status', False) == 'approved':
vals['value'] = job['body_tgt']
if job.get('status', False) in ('approved', 'canceled'):
vals['state'] = 'translated'
if vals:
translation_pool.write(cr, uid, [tid], vals, context=context)
def _update_terms(self, cr, uid, response, context=None):
def _update_terms(self, cr, uid, response, term_ids, context=None):
"""
Update the terms after their translation were requested to Gengo
"""
for jobs in response.get('jobs', []):
translation_pool = self.pool.get('ir.translation')
vals = {
'order_id': response.get('order_id', ''),
'state': 'inprogress'
}
translation_pool.write(cr, uid, term_ids, vals, context=context)
jobs = response.get('jobs', [])
if jobs:
for t_id, res in jobs.items():
self._update_terms_job(cr, uid, res, context=context)
return
def pack_jobs_request(self, cr, uid, term_ids, context=None):
@ -164,7 +198,7 @@ class base_gengo_translations(osv.osv_memory):
'term2.id': {...}
}
}'''
base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url')
translation_pool = self.pool.get('ir.translation')
jobs = {}
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
@ -173,7 +207,7 @@ class base_gengo_translations(osv.osv_memory):
if re.search(r"\w", term.src or ""):
comment = user.company_id.gengo_comment or ''
if term.gengo_comment:
comment+='\n' + term.gengo_comment
comment += '\n' + term.gengo_comment
jobs[time.strftime('%Y%m%d%H%M%S') + '-' + str(term.id)] = {
'type': 'text',
'slug': 'Single :: English to ' + term.lang,
@ -184,10 +218,9 @@ class base_gengo_translations(osv.osv_memory):
'lc_tgt': translation_pool._get_gengo_corresponding_language(term.lang),
'auto_approve': auto_approve,
'comment': comment,
'callback_url': self.pool.get('ir.config_parameter').get_param(cr, uid,'web.base.url') + '/website/gengo_callback'
'callback_url': "%s/website/gengo_callback?pgk=%s&db=%s" % (base_url, self.get_gengo_key(cr), cr.dbname)
}
return {'jobs': jobs, 'as_group': 1}
return {'jobs': jobs, 'as_group': 0}
def _send_translation_terms(self, cr, uid, term_ids, context=None):
"""
@ -200,7 +233,7 @@ class base_gengo_translations(osv.osv_memory):
if request['jobs']:
result = gengo.postTranslationJobs(jobs=request)
if result['opstat'] == 'ok':
self._update_terms(cr, uid, result['response'], context=context)
self._update_terms(cr, uid, result['response'], term_ids, context=context)
else:
_logger.error(gengo)
return True
@ -218,10 +251,10 @@ class base_gengo_translations(osv.osv_memory):
context = {}
language_pool = self.pool.get('res.lang')
translation_pool = self.pool.get('ir.translation')
domain = [('state', '=', 'to_translate'), ('gengo_translation', 'in', ('machine', 'standard', 'pro', 'ultra')), ('job_id', "=", False)]
domain = [('state', '=', 'to_translate'), ('gengo_translation', 'in', ('machine', 'standard', 'pro', 'ultra')), ('order_id', "=", False)]
if context.get('gengo_language', False):
lc = language_pool.browse(cr, uid, context['gengo_language'], context=context).code
domain.append( ('lang', '=', lc) )
domain.append(('lang', '=', lc))
all_term_ids = translation_pool.search(cr, uid, domain, context=context)
try:

View File

@ -161,6 +161,13 @@ class crm_claim(osv.osv):
# context: no_log, because subtype already handle this
return super(crm_claim, self).create(cr, uid, vals, context=context)
def copy(self, cr, uid, id, default=None, context=None):
claim = self.browse(cr, uid, id, context=context)
default = dict(default or {},
stage_id = self._get_default_stage_id(cr, uid, context=context),
name = _('%s (copy)') % claim.name)
return super(crm_claim, self).copy(cr, uid, id, default, context=context)
# -------------------------------------------------------
# Mail gateway
# -------------------------------------------------------

View File

@ -225,7 +225,7 @@ class partner_vat_intra(osv.osv_memory):
data_head = """<?xml version="1.0" encoding="ISO-8859-1"?>
<ns2:IntraConsignment xmlns="http://www.minfin.fgov.be/InputCommon" xmlns:ns2="http://www.minfin.fgov.be/IntraConsignment" IntraListingsNbr="1">
<ns2:Representative>
<RepresentativeID identificationType="NVAT" issuedBy="%(issued_by)s">%(company_vat)s</RepresentativeID>
<RepresentativeID identificationType="NVAT" issuedBy="%(issued_by)s">%(vatnum)s</RepresentativeID>
<Name>%(company_name)s</Name>
<Street>%(street)s</Street>
<PostCode>%(post_code)s</PostCode>

View File

@ -91,6 +91,8 @@ class purchase_requisition(osv.osv):
for purchase_order in tender.purchase_ids:
purchase_order_obj.action_cancel(cr, uid, [purchase_order.id], context=context)
purchase_order_obj.message_post(cr, uid, [purchase_order.id], body=_('Cancelled by the tender associated to this quotation.'), context=context)
procurement_ids = self.pool['procurement.order'].search(cr, uid, [('requisition_id', 'in', ids)], context=context)
self.pool['procurement.order'].action_done(cr, uid, procurement_ids)
return self.write(cr, uid, ids, {'state': 'cancel'})
def tender_in_progress(self, cr, uid, ids, context=None):
@ -108,6 +110,8 @@ class purchase_requisition(osv.osv):
return True
def tender_done(self, cr, uid, ids, context=None):
procurement_ids = self.pool['procurement.order'].search(cr, uid, [('requisition_id', 'in', ids)], context=context)
self.pool['procurement.order'].action_done(cr, uid, procurement_ids)
return self.write(cr, uid, ids, {'state': 'done'}, context=context)
def open_product_line(self, cr, uid, ids, context=None):
@ -352,6 +356,10 @@ class purchase_order(osv.osv):
proc_obj.write(cr, uid, proc_ids, {'purchase_id': po.id})
self.signal_purchase_cancel(cr, uid, [order.id])
po.requisition_id.tender_done(context=context)
if po.requisition_id and all(purchase_id.state in ['draft', 'cancel'] for purchase_id in po.requisition_id.purchase_ids if purchase_id.id != po.id):
procurement_ids = self.pool['procurement.order'].search(cr, uid, [('requisition_id', '=', po.requisition_id.id)], context=context)
for procurement in proc_obj.browse(cr, uid, procurement_ids, context=context):
procurement.move_id.write({'location_id': procurement.move_id.location_dest_id.id})
return res
def copy(self, cr, uid, id, default=None, context=None):

View File

@ -56,7 +56,7 @@
<tr t-foreach="o.invoice_line" t-as="l">
<td><span t-field="l.name"/></td>
<td class="text-right"><span t-esc="', '.join(map(lambda x: x.name, l.invoice_line_tax_id))"/></td>
<td class="text-right"><span t-esc="l.product_id.intrastat_id"/></td>
<td class="text-right"><span t-esc="l.product_id.intrastat_id.name"/></td>
<td class="text-right"><span t-esc="l.product_id.weight"/></td>
<td class="text-right"><span t-field="l.quantity"/></td>
<td groups="product.group_uom"><span t-field="l.uos_id"/></td>

View File

@ -493,7 +493,7 @@ instance.web.DatabaseManager = instance.web.Widget.extend({
size: 'medium',
title: error.title,
buttons: [
{text: _t("Ok"), click: function() { this.$el.parents('.modal').modal('hide'); }}
{text: _t("Ok"), click: function() { this.parents('.modal').modal('hide'); }}
]
}, $('<div>').html(error.error)).open();
},
@ -706,7 +706,7 @@ instance.web.ChangePassword = instance.web.Widget.extend({
var $button = self.$el.find('.oe_form_button');
$button.appendTo(this.getParent().$buttons);
$button.eq(2).click(function(){
self.getParent().close();
self.$el.parents('.modal').modal('hide');
});
$button.eq(0).click(function(){
self.rpc("/web/session/change_password",{
@ -726,7 +726,7 @@ instance.web.ChangePassword = instance.web.Widget.extend({
size: 'medium',
title: error.title,
buttons: [
{text: _t("Ok"), click: function() { this.$el.parents('.modal').modal('hide'); }}
{text: _t("Ok"), click: function() { this.parents('.modal').modal('hide'); }}
]
}, $('<div>').html(error.error)).open();
},

View File

@ -271,7 +271,7 @@ instance.web.parse_value = function (value, descriptor, value_if_empty) {
value, (date_pattern + ' ' + time_pattern));
if (datetime !== null)
return instance.web.datetime_to_str(datetime);
datetime = Date.parseExact(value.replace(/\d+/g, function(m){
datetime = Date.parseExact(value.toString().replace(/\d+/g, function(m){
return m.length === 1 ? "0" + m : m ;
}), (date_pattern + ' ' + time_pattern));
if (datetime !== null)
@ -284,7 +284,7 @@ instance.web.parse_value = function (value, descriptor, value_if_empty) {
var date = Date.parseExact(value, date_pattern);
if (date !== null)
return instance.web.date_to_str(date);
date = Date.parseExact(value.replace(/\d+/g, function(m){
date = Date.parseExact(value.toString().replace(/\d+/g, function(m){
return m.length === 1 ? "0" + m : m ;
}), date_pattern);
if (date !== null)

View File

@ -1114,7 +1114,7 @@ instance.web.ListView.List = instance.web.Class.extend( /** @lends instance.web.
ids = value;
}
new instance.web.Model(column.relation)
.call('name_get', [ids]).done(function (names) {
.call('name_get', [ids, this.dataset.context]).done(function (names) {
// FIXME: nth horrible hack in this poor listview
record.set(column.id + '__display',
_(names).pluck(1).join(', '));

View File

@ -610,17 +610,13 @@ openerp.web_calendar = function(instance) {
date_start_day = new Date(event.start.getFullYear(),event.start.getMonth(),event.start.getDate(),7);
date_stop_day = new Date(event_end.getFullYear(),event_end.getMonth(),event_end.getDate(),19);
}
data[this.date_start] = instance.web.parse_value(date_start_day, this.fields[this.date_start]);
if (this.date_stop) {
data[this.date_stop] = instance.web.parse_value(date_stop_day, this.fields[this.date_stop]);
}
diff_seconds = Math.round((date_stop_day.getTime() - date_start_day.getTime()) / 1000);
}
else {
data[this.date_start] = instance.web.parse_value(event.start, this.fields[this.date_start]);
data[this.date_start] = event.start;
if (this.date_stop) {
data[this.date_stop] = instance.web.parse_value(event_end, this.fields[this.date_stop]);
data[this.date_stop] = event_end;
}
diff_seconds = Math.round((event_end.getTime() - event.start.getTime()) / 1000);
}

View File

@ -413,7 +413,7 @@ class Website(openerp.addons.web.controllers.main.Home):
action = ServerActions.browse(cr, uid, action_id, context=context)
if action.state == 'code' and action.website_published:
action_res = ServerActions.run(cr, uid, [action_id], context=context)
if isinstance(action_res, Response):
if isinstance(action_res, werkzeug.wrappers.Response):
res = action_res
if res:
return res

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -11,6 +11,7 @@
var nodialog = 'website_translator_nodialog';
website.EditorBar.include({
do_not_translate : ['-','*','!'],
events: _.extend({}, website.EditorBar.prototype.events, {
'click a[data-action=edit_master]': 'edit_master',
}),
@ -134,7 +135,7 @@
node.className += ' oe_translatable_inprogress';
}
} else {
node.className += ' oe_translatable_todo';
node.className += this.do_not_translate.indexOf(node.textContent.trim()) ? ' oe_translatable_todo' : '';
}
node.contentEditable = true;
var nid = _.uniqueId();

View File

@ -288,6 +288,31 @@ class ir_translation(osv.osv):
})
return len(ids)
def _get_source_query(self, cr, uid, name, types, lang, source, res_id):
if source:
query = """SELECT value
FROM ir_translation
WHERE lang=%s
AND type in %s
AND src=%s"""
params = (lang or '', types, tools.ustr(source))
if res_id:
query += "AND res_id=%s"
params += (res_id,)
if name:
query += " AND name=%s"
params += (tools.ustr(name),)
else:
query = """SELECT value
FROM ir_translation
WHERE lang=%s
AND type in %s
AND name=%s"""
params = (lang or '', types, tools.ustr(name))
return (query, params)
@tools.ormcache(skiparg=3)
def _get_source(self, cr, uid, name, types, lang, source=None, res_id=None):
"""
@ -310,27 +335,10 @@ class ir_translation(osv.osv):
return tools.ustr(source or '')
if isinstance(types, basestring):
types = (types,)
if source:
query = """SELECT value
FROM ir_translation
WHERE lang=%s
AND type in %s
AND src=%s"""
params = (lang or '', types, tools.ustr(source))
if res_id:
query += "AND res_id=%s"
params += (res_id,)
if name:
query += " AND name=%s"
params += (tools.ustr(name),)
cr.execute(query, params)
else:
cr.execute("""SELECT value
FROM ir_translation
WHERE lang=%s
AND type in %s
AND name=%s""",
(lang or '', types, tools.ustr(name)))
query, params = self._get_source_query(cr, uid, name, types, lang, source, res_id)
cr.execute(query, params)
res = cr.fetchone()
trad = res and res[0] or u''
if source and not trad:

View File

@ -475,7 +475,7 @@ class view(osv.osv):
node.getparent().remove(node)
elif pos == 'attributes':
for child in spec.getiterator('attribute'):
attribute = (child.get('name'), child.text and child.text.encode('utf8') or None)
attribute = (child.get('name'), child.text or None)
if attribute[1]:
node.set(attribute[0], attribute[1])
elif attribute[0] in node.attrib:

View File

@ -103,17 +103,7 @@ class base_module_upgrade(osv.osv_memory):
openerp.modules.registry.RegistryManager.new(cr.dbname, update_module=True)
ir_model_data = self.pool.get('ir.model.data')
__, res_id = ir_model_data.get_object_reference(cr, uid, 'base', 'view_base_module_upgrade_install')
return {
'view_type': 'form',
'view_mode': 'form',
'res_model': 'base.module.upgrade',
'views': [(res_id, 'form')],
'view_id': False,
'type': 'ir.actions.act_window',
'target': 'new',
}
return {'type': 'ir.actions.act_window_close'}
def config(self, cr, uid, ids, context=None):
return self.pool.get('res.config').next(cr, uid, [], context=context)

View File

@ -13,7 +13,7 @@
<separator string="Impacted Modules"/>
<field name="module_info"/>
<footer>
<button name="upgrade_module" string="Update" type="object" class="oe_highlight"/>
<button name="upgrade_module" string="Confirm" type="object" class="oe_highlight"/>
or
<button string="Cancel" class="oe_link" name="upgrade_module_cancel" type="object"/>
</footer>

View File

@ -1036,34 +1036,30 @@ class expression(object):
unaccent = self._unaccent if sql_operator.endswith('like') else lambda x: x
trans_left = unaccent('value')
quote_left = unaccent(_quote(left))
instr = unaccent('%s')
if sql_operator == 'in':
# params will be flatten by to_sql() => expand the placeholders
instr = '(%s)' % ', '.join(['%s'] * len(right))
subselect = """(SELECT res_id
FROM ir_translation
WHERE name = %s
AND lang = %s
AND type = %s
AND {trans_left} {operator} {right}
) UNION (
SELECT id
FROM "{table}"
WHERE {left} {operator} {right}
)
""".format(trans_left=trans_left, operator=sql_operator,
right=instr, table=working_model._table, left=quote_left)
subselect = """WITH temp_irt_current (id, name) as (
SELECT ct.id, coalesce(it.value,ct.{quote_left})
FROM {current_table} ct
LEFT JOIN ir_translation it ON (it.name = %s and
it.lang = %s and
it.type = %s and
it.res_id = ct.id and
it.value != '')
)
SELECT id FROM temp_irt_current WHERE {name} {operator} {right} order by name
""".format(current_table=working_model._table, quote_left=_quote(left), name=unaccent('name'),
operator=sql_operator, right=instr)
params = (
working_model._name + ',' + left,
context.get('lang') or 'en_US',
'model',
right,
right,
)
push(create_substitution_leaf(leaf, ('id', inselect_operator, (subselect, params)), working_model))

View File

@ -1556,7 +1556,8 @@ class property(function):
default_val = self._get_default(obj, cr, uid, prop_name, context)
property_create = False
if isinstance(default_val, openerp.osv.orm.browse_record):
if isinstance(default_val, (openerp.osv.orm.browse_record,
openerp.osv.orm.browse_null)):
if default_val.id != id_val:
property_create = True
elif default_val != id_val: