[MERGE] forward port branch saas-15 up to 8962b8ecc2
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = {}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -75,6 +75,10 @@ in each method::
|
||||
|
||||
# other tests...
|
||||
|
||||
.. note::
|
||||
|
||||
Test methods must start with ``test_``
|
||||
|
||||
Running tests
|
||||
-------------
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user