[MERGE] forward port branch saas-15 up to 8962b8ecc2

This commit is contained in:
Christophe Simonis
2018-01-12 17:23:10 +01:00
19 changed files with 69 additions and 28 deletions
+9 -9
View File
@@ -44,8 +44,8 @@ class AccountFrFec(models.TransientModel):
'-' AS PieceRef,
%s AS PieceDate,
'/' AS EcritureLib,
replace(CASE WHEN COALESCE(sum(aml.balance), 0) <= 0 THEN '0,00' ELSE to_char(SUM(aml.balance), '999999999999999D99') END, '.', ',') AS Debit,
replace(CASE WHEN COALESCE(sum(aml.balance), 0) >= 0 THEN '0,00' ELSE to_char(-SUM(aml.balance), '999999999999999D99') END, '.', ',') AS Credit,
replace(CASE WHEN COALESCE(sum(aml.balance), 0) <= 0 THEN '0,00' ELSE to_char(SUM(aml.balance), '000000000000000D99') END, '.', ',') AS Debit,
replace(CASE WHEN COALESCE(sum(aml.balance), 0) >= 0 THEN '0,00' ELSE to_char(-SUM(aml.balance), '000000000000000D99') END, '.', ',') AS Credit,
'' AS EcritureLet,
'' AS DateLet,
%s AS ValidDate,
@@ -143,8 +143,8 @@ class AccountFrFec(models.TransientModel):
'-' AS PieceRef,
%s AS PieceDate,
'/' AS EcritureLib,
replace(CASE WHEN sum(aml.balance) <= 0 THEN '0,00' ELSE to_char(SUM(aml.balance), '999999999999999D99') END, '.', ',') AS Debit,
replace(CASE WHEN sum(aml.balance) >= 0 THEN '0,00' ELSE to_char(-SUM(aml.balance), '999999999999999D99') END, '.', ',') AS Credit,
replace(CASE WHEN sum(aml.balance) <= 0 THEN '0,00' ELSE to_char(SUM(aml.balance), '000000000000000D99') END, '.', ',') AS Debit,
replace(CASE WHEN sum(aml.balance) >= 0 THEN '0,00' ELSE to_char(-SUM(aml.balance), '000000000000000D99') END, '.', ',') AS Credit,
'' AS EcritureLet,
'' AS DateLet,
%s AS ValidDate,
@@ -228,8 +228,8 @@ class AccountFrFec(models.TransientModel):
'-' AS PieceRef,
%s AS PieceDate,
'/' AS EcritureLib,
replace(CASE WHEN sum(aml.balance) <= 0 THEN '0,00' ELSE to_char(SUM(aml.balance), '999999999999999D99') END, '.', ',') AS Debit,
replace(CASE WHEN sum(aml.balance) >= 0 THEN '0,00' ELSE to_char(-SUM(aml.balance), '999999999999999D99') END, '.', ',') AS Credit,
replace(CASE WHEN sum(aml.balance) <= 0 THEN '0,00' ELSE to_char(SUM(aml.balance), '000000000000000D99') END, '.', ',') AS Debit,
replace(CASE WHEN sum(aml.balance) >= 0 THEN '0,00' ELSE to_char(-SUM(aml.balance), '000000000000000D99') END, '.', ',') AS Credit,
'' AS EcritureLet,
'' AS DateLet,
%s AS ValidDate,
@@ -290,14 +290,14 @@ class AccountFrFec(models.TransientModel):
AS PieceRef,
TO_CHAR(am.date, 'YYYYMMDD') AS PieceDate,
CASE WHEN aml.name IS NULL THEN '/' ELSE replace(aml.name, '|', '/') END AS EcritureLib,
replace(CASE WHEN aml.debit = 0 THEN '0,00' ELSE to_char(aml.debit, '999999999999999D99') END, '.', ',') AS Debit,
replace(CASE WHEN aml.credit = 0 THEN '0,00' ELSE to_char(aml.credit, '999999999999999D99') END, '.', ',') AS Credit,
replace(CASE WHEN aml.debit = 0 THEN '0,00' ELSE to_char(aml.debit, '000000000000000D99') END, '.', ',') AS Debit,
replace(CASE WHEN aml.credit = 0 THEN '0,00' ELSE to_char(aml.credit, '000000000000000D99') END, '.', ',') AS Credit,
CASE WHEN rec.name IS NULL THEN '' ELSE rec.name END AS EcritureLet,
CASE WHEN aml.full_reconcile_id IS NULL THEN '' ELSE TO_CHAR(rec.create_date, 'YYYYMMDD') END AS DateLet,
TO_CHAR(am.date, 'YYYYMMDD') AS ValidDate,
CASE
WHEN aml.amount_currency IS NULL OR aml.amount_currency = 0 THEN ''
ELSE replace(to_char(aml.amount_currency, '999999999999999D99'), '.', ',')
ELSE replace(to_char(aml.amount_currency, '000000000000000D99'), '.', ',')
END AS Montantdevise,
CASE WHEN aml.currency_id IS NULL THEN '' ELSE rc.name END AS Idevise
FROM
@@ -50,6 +50,7 @@
// ===== Layout =====
.o_layout {
overflow: hidden;
box-sizing: content-box;
width: 94%;
min-height: 100%;
background-color: @o_mm_def_color_alpha;
+5 -3
View File
@@ -18,9 +18,11 @@ class StockMoveLots(models.Model):
'stock.production.lot', 'Lot',
domain="[('product_id', '=', product_id)]")
lot_produced_id = fields.Many2one('stock.production.lot', 'Finished Lot')
lot_produced_qty = fields.Float('Quantity Finished Product', help="Informative, not used in matching")
quantity = fields.Float('To Do', default=1.0)
quantity_done = fields.Float('Done')
lot_produced_qty = fields.Float(
'Quantity Finished Product', digits=dp.get_precision('Product Unit of Measure'),
help="Informative, not used in matching")
quantity = fields.Float('To Do', default=1.0, digits=dp.get_precision('Product Unit of Measure'))
quantity_done = fields.Float('Done', digits=dp.get_precision('Product Unit of Measure'))
product_id = fields.Many2one(
'product.product', 'Product',
readonly=True, related="move_id.product_id", store=True)
+7 -2
View File
@@ -17,6 +17,7 @@ import operator
import os
import re
import sys
import tempfile
import time
import werkzeug
import werkzeug.utils
@@ -38,6 +39,7 @@ from odoo.http import content_disposition, dispatch_rpc, request, \
serialize_exception as _serialize_exception
from odoo.exceptions import AccessError, UserError
from odoo.models import check_method_name
from odoo.service import db
_logger = logging.getLogger(__name__)
@@ -725,12 +727,15 @@ class Database(http.Controller):
@http.route('/web/database/restore', type='http', auth="none", methods=['POST'], csrf=False)
def restore(self, master_pwd, backup_file, name, copy=False):
try:
data = base64.b64encode(backup_file.read())
dispatch_rpc('db', 'restore', [master_pwd, name, data, str2bool(copy)])
with tempfile.NamedTemporaryFile(delete=False) as data_file:
backup_file.save(data_file)
db.restore_db(name, data_file.name, str2bool(copy))
return http.local_redirect('/web/database/manager')
except Exception as e:
error = "Database restore error: %s" % (str(e) or repr(e))
return self._render_template(error=error)
finally:
os.unlink(data_file.name)
@http.route('/web/database/change_password', type='http', auth="none", methods=['POST'], csrf=False)
def change_password(self, master_pwd, master_pwd_new):
+1 -1
View File
@@ -116,7 +116,7 @@ var utils = {
size /= 1024;
++i;
}
return size.toFixed(2) + ' ' + units[i];
return size.toFixed(2) + ' ' + units[i].trim();
},
/**
* Insert "thousands" separators in the provided number (which is actually
@@ -398,7 +398,9 @@ eventHandler.modules.imageDialog.showImageDialog = function ($editable) {
if (r.sc.tagName && r.sc.childNodes.length) {
r.sc = r.sc.childNodes[r.so];
}
new widgets.MediaDialog(null, {}, $editable, dom.isImg(r.sc) ? r.sc : null).open();
new widgets.MediaDialog(null, {}, $editable, $(r.sc).parents().addBack().filter(function (i, el) {
return dom.isImg(el);
})[0]).open();
return new $.Deferred().reject();
};
$.summernote.pluginEvents.alt = function (event, editor, layoutInfo, sorted) {
+1 -1
View File
@@ -61,7 +61,7 @@ class Http(models.AbstractModel):
if not request.session.uid:
env = api.Environment(request.cr, SUPERUSER_ID, request.context)
website = env['website'].get_current_website()
if website:
if website and website.user_id:
request.uid = website.user_id.id
else:
request.uid = env.ref('base.public_user').id
+1 -1
View File
@@ -177,7 +177,7 @@ class Website(models.Model):
google_management_client_id = fields.Char('Google Client ID')
google_management_client_secret = fields.Char('Google Client Secret')
user_id = fields.Many2one('res.users', string='Public User', default=lambda self: self.env.ref('base.public_user').id)
user_id = fields.Many2one('res.users', string='Public User', required=True, default=lambda self: self.env.ref('base.public_user').id)
cdn_activated = fields.Boolean('Activate CDN for assets')
cdn_url = fields.Char('CDN Base URL', default='')
cdn_filters = fields.Text('CDN Filters', default=lambda s: '\n'.join(DEFAULT_CDN_FILTERS), help="URL matching those filters will be rewritten using the CDN Base URL")
+3 -1
View File
@@ -173,7 +173,9 @@ class WebsiteBlog(http.Controller):
v = {}
v['blog'] = blog
v['base_url'] = request.env['ir.config_parameter'].sudo().get_param('web.base.url')
v['posts'] = request.env['blog.post'].search([('blog_id','=', blog.id)], limit=min(int(limit), 50))
v['posts'] = request.env['blog.post'].search([('blog_id','=', blog.id)],
limit=min(int(limit), 50),
order="post_date DESC")
v['html2plaintext'] = html2plaintext
r = request.render("website_blog.blog_feed", v, headers=[('Content-Type', 'application/atom+xml')])
return r
+1 -1
View File
@@ -154,7 +154,7 @@ class BlogPost(models.Model):
write_date = fields.Datetime('Last Modified on', index=True, readonly=True)
write_uid = fields.Many2one('res.users', 'Last Contributor', index=True, readonly=True)
author_avatar = fields.Binary(related='author_id.image_small', string="Avatar")
visits = fields.Integer('No of Views')
visits = fields.Integer('No of Views', copy=False)
ranking = fields.Float(compute='_compute_ranking', string='Ranking')
@api.multi
@@ -552,14 +552,14 @@
<title t-esc="blog.name"/>
<link t-att-href="'%s/blog/%s' % (base_url ,blog.id)"/>
<id t-esc="'%s/blog/%s' % (base_url, blog.id)"/>
<updated t-esc="(posts[0] if posts else blog).write_date.replace(' ', 'T') + 'Z'"/>
<updated t-esc="(posts[0] if posts else blog).post_date.replace(' ', 'T') + 'Z'"/>
<entry t-foreach="posts" t-as="post">
<title t-esc="post.name"/>
<link t-att-href="'%s%s' % (base_url, post.website_url)"/>
<id t-esc="'%s%s' % (base_url, post.website_url)"/>
<author><name t-esc="post.sudo().author_id.name"/></author>
<summary t-esc="html2plaintext(post.teaser)"/>
<updated t-esc="post.write_date.replace(' ', 'T') + 'Z'"/>
<updated t-esc="post.post_date.replace(' ', 'T') + 'Z'"/>
</entry>
</feed>
</template>
@@ -67,11 +67,13 @@ class WebsiteEventTrackController(http.Controller):
@http.route(['''/event/<model("event.event", "[('website_track','=',1)]"):event>/agenda'''], type='http', auth="public", website=True)
def event_agenda(self, event, tag=None, **post):
local_tz = pytz.timezone(event.date_tz or 'UTC')
days_tracks = collections.defaultdict(lambda: [])
for track in event.track_ids.sorted(lambda track: (track.date, bool(track.location_id))):
if not track.date:
continue
days_tracks[track.date[:10]].append(track)
date = fields.Datetime.from_string(track.date).replace(tzinfo=pytz.utc).astimezone(local_tz)
days_tracks[str(date)[:10]].append(track)
days = {}
tracks_by_days = {}
+1 -1
View File
@@ -12,4 +12,4 @@ Robin Lucbenet robin@meta-it.fr https://github.com/n1b0r
List of contributors:
Guillaume Masson guillaume.masson@meta-it.fr
Guillaume Masson guillaume.masson@meta-it.fr https://github.com/metaminux
+11
View File
@@ -0,0 +1,11 @@
Costa Rica, 2018-01-11
I hereby agree to the terms of the Odoo Individual Contributor License
Agreement v1.0.
I declare that I am authorized and able to make this agreement and sign this
declaration.
Signed,
Randall Castro randall_castro@me.com https://github.com/rcastro-tyc
+4
View File
@@ -75,6 +75,10 @@ in each method::
# other tests...
.. note::
Test methods must start with ``test_``
Running tests
-------------
+9 -1
View File
@@ -576,7 +576,13 @@ class IrActionsServer(models.Model):
for exp in action.fields_lines:
res[exp.col1.name] = exp.eval_value(eval_context=eval_context)[exp.id]
self.env[action.model_id.model].browse(self._context.get('active_id')).write(res)
if self._context.get('onchange_self'):
record_cached = self._context['onchange_self']
for field, new_value in res.iteritems():
record_cached[field] = new_value
else:
self.env[action.model_id.model].browse(self._context.get('active_id')).write(res)
@api.model
def run_action_object_create(self, action, eval_context=None):
@@ -671,6 +677,8 @@ class IrActionsServer(models.Model):
elif hasattr(self, 'run_action_%s' % action.state):
active_id = self._context.get('active_id')
if not active_id and self._context.get('onchange_self'):
active_id = self._context['onchange_self']._origin.id
active_ids = self._context.get('active_ids', [active_id] if active_id else [])
for active_id in active_ids:
# run context dedicated to a particular active_id
+1 -1
View File
@@ -214,7 +214,7 @@ class ir_cron(models.Model):
_logger.debug("Job `%s` already executed by another process/thread. skipping it", job['cron_name'])
continue
# Got the lock on the job row, run its code
_logger.debug('Starting job `%s`.', job['cron_name'])
_logger.info('Starting job `%s`.', job['cron_name'])
job_cr = db.cursor()
try:
registry = odoo.registry(db_name)
+1 -1
View File
@@ -227,7 +227,7 @@ actual arch.
if fullpath:
arch_fs = get_view_arch_from_file(fullpath, view.xml_id)
# replace %(xml_id)s, %(xml_id)d, %%(xml_id)s, %%(xml_id)d by the res_id
arch_fs = arch_fs and resolve_external_ids(arch_fs, view.xml_id)
arch_fs = arch_fs and resolve_external_ids(arch_fs, view.xml_id).replace('%%', '%')
else:
_logger.warning("View %s: Full path [%s] cannot be found.", view.xml_id, view.arch_fs)
arch_fs = False
+5 -1
View File
@@ -213,9 +213,13 @@ def dump_db(db_name, stream, backup_format='zip'):
return stdout
def exp_restore(db_name, data, copy=False):
def chunks(d, n=8192):
for i in range(0, len(d), n):
yield d[i:i+n]
data_file = tempfile.NamedTemporaryFile(delete=False)
try:
data_file.write(data.decode('base64'))
for chunk in chunks(data):
data_file.write(chunk.decode('base64'))
data_file.close()
restore_db(db_name, data_file.name, copy=copy)
finally: