diff --git a/MANIFEST.in b/MANIFEST.in index 4f470c58aad..df402ab6558 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -32,6 +32,7 @@ recursive-include odoo *.ttf recursive-include odoo *.woff recursive-include odoo *.woff2 recursive-include odoo *.wsdl +recursive-include odoo *.xls recursive-include odoo *.xsd recursive-include odoo *.xsl recursive-include odoo *.xml diff --git a/addons/account/static/src/js/account_reconciliation_widgets.js b/addons/account/static/src/js/account_reconciliation_widgets.js index da7e4ef1934..aa58012dd8a 100644 --- a/addons/account/static/src/js/account_reconciliation_widgets.js +++ b/addons/account/static/src/js/account_reconciliation_widgets.js @@ -1065,7 +1065,7 @@ var abstractReconciliationLine = Widget.extend({ var amount = line.tax_id ? line.amount_before_tax: line.amount; dict['credit'] = (amount > 0 ? amount : 0); dict['debit'] = (amount < 0 ? -1 * amount : 0); - if (line.tax_id) dict['tax_ids'] = [line.tax_id]; + if (line.tax_id) dict['tax_ids'] = [[4, line.tax_id, null]]; if (line.analytic_account_id) dict['analytic_account_id'] = line.analytic_account_id; return dict; }); diff --git a/addons/account_asset/models/account_asset.py b/addons/account_asset/models/account_asset.py index 144f0cc518e..c5ed568671d 100644 --- a/addons/account_asset/models/account_asset.py +++ b/addons/account_asset/models/account_asset.py @@ -204,7 +204,12 @@ class AccountAssetAsset(models.Model): if self.value_residual != 0.0: amount_to_depr = residual_amount = self.value_residual if self.prorata: - depreciation_date = datetime.strptime(self._get_last_depreciation_date()[self.id], DF).date() + # if we already have some previous validated entries, starting date is last entry + method perio + if posted_depreciation_line_ids and posted_depreciation_line_ids[-1].depreciation_date: + last_depreciation_date = datetime.strptime(posted_depreciation_line_ids[-1].depreciation_date, DF).date() + depreciation_date = last_depreciation_date + relativedelta(months=+self.method_period) + else: + depreciation_date = datetime.strptime(self._get_last_depreciation_date()[self.id], DF).date() else: # depreciation_date = 1st of January of purchase year if annual valuation, 1st of # purchase month in other cases diff --git a/addons/mail/static/src/js/chat_manager.js b/addons/mail/static/src/js/chat_manager.js index 2f63dd61b5a..d2bfade1d38 100644 --- a/addons/mail/static/src/js/chat_manager.js +++ b/addons/mail/static/src/js/chat_manager.js @@ -18,10 +18,10 @@ var LIMIT = 25; var preview_msg_max_size = 350; // optimal for native english speakers var ODOOBOT_ID = "ODOOBOT"; -var MessageModel = new Model('mail.message', session.context); -var ChannelModel = new Model('mail.channel', session.context); -var UserModel = new Model('res.users', session.context); -var PartnerModel = new Model('res.partner', session.context); +var MessageModel = new Model('mail.message', session.user_context); +var ChannelModel = new Model('mail.channel', session.user_context); +var UserModel = new Model('res.users', session.user_context); +var PartnerModel = new Model('res.partner', session.user_context); // Private model //---------------------------------------------------------------------------------- @@ -383,7 +383,7 @@ function fetch_from_channel (channel, options) { domain = new data.CompoundDomain([['id', '<', min_message_id]], domain); } - return MessageModel.call('message_fetch', [domain], {limit: LIMIT}).then(function (msgs) { + return MessageModel.call('message_fetch', [domain], {limit: LIMIT, context: session.user_context}).then(function (msgs) { if (!cache.all_history_loaded) { cache.all_history_loaded = msgs.length < LIMIT; } @@ -408,7 +408,7 @@ function fetch_document_messages (ids, options) { if (options.force_fetch || _.difference(ids.slice(0, LIMIT), loaded_msg_ids).length) { var ids_to_load = _.difference(ids, loaded_msg_ids).slice(0, LIMIT); - return MessageModel.call('message_format', [ids_to_load]).then(function (msgs) { + return MessageModel.call('message_format', [ids_to_load], {context: session.user_context}).then(function (msgs) { var processed_msgs = []; _.each(msgs, function (msg) { processed_msgs.push(add_message(msg, {silent: true})); @@ -952,7 +952,7 @@ var chat_manager = { } }); } else { - new Model(res_model).call('get_formview_id', [[res_id], session.context]).then(function (view_id) { + new Model(res_model).call('get_formview_id', [[res_id], session.user_context]).then(function (view_id) { redirect_to_document(res_model, res_id, view_id); }); } diff --git a/addons/point_of_sale/static/src/js/devices.js b/addons/point_of_sale/static/src/js/devices.js index 3a5e0ba45a0..5d272bbfda8 100644 --- a/addons/point_of_sale/static/src/js/devices.js +++ b/addons/point_of_sale/static/src/js/devices.js @@ -423,7 +423,7 @@ var ProxyDevice = core.Class.extend(core.mixins.PropertiesMixin,{ send_printing_job(); },function(error){ if (error) { - self.pos.chrome.screen_selector.show_popup('error-traceback',{ + self.pos.gui.show_popup('error-traceback',{ 'title': _t('Printing Error: ') + error.data.message, 'body': error.data.debug, }); diff --git a/addons/point_of_sale/static/src/js/screens.js b/addons/point_of_sale/static/src/js/screens.js index 1fba372a1de..bb30e7b7943 100644 --- a/addons/point_of_sale/static/src/js/screens.js +++ b/addons/point_of_sale/static/src/js/screens.js @@ -1865,7 +1865,7 @@ var PaymentScreenWidget = ScreenWidget.extend({ var plines = order.get_paymentlines(); for (var i = 0; i < plines.length; i++) { if (plines[i].get_type() === 'bank' && plines[i].get_amount() < 0) { - this.pos_widget.screen_selector.show_popup('error',{ + this.gui.show_popup('error',{ 'message': _t('Negative Bank Payment'), 'comment': _t('You cannot have a negative amount in a Bank payment. Use a cash payment method to return money to the customer.'), }); diff --git a/addons/website/controllers/main.py b/addons/website/controllers/main.py index 3a64816a248..fa7b1b12b1f 100644 --- a/addons/website/controllers/main.py +++ b/addons/website/controllers/main.py @@ -137,6 +137,7 @@ class Website(Home): @http.route('/sitemap.xml', type='http', auth="public", website=True) def sitemap_xml_index(self): + current_website = request.website Attachment = request.env['ir.attachment'].sudo() View = request.env['ir.ui.view'].sudo() mimetype = 'application/xml;charset=utf-8' @@ -150,8 +151,8 @@ class Website(Home): 'name': url, 'url': url, }) - - sitemap = Attachment.search([('url', '=', '/sitemap.xml'), ('type', '=', 'binary')], limit=1) + dom = [('url', '=' , '/sitemap-%d.xml' % current_website.id), ('type', '=', 'binary')] + sitemap = Attachment.search(dom, limit=1) if sitemap: # Check if stored version is still valid create_date = fields.Datetime.from_string(sitemap.create_date) @@ -161,7 +162,9 @@ class Website(Home): if not content: # Remove all sitemaps in ir.attachments as we're going to regenerated them - sitemaps = Attachment.search([('url', '=like', '/sitemap%.xml'), ('type', '=', 'binary')]) + dom = [('type', '=', 'binary'), '|', ('url', '=like' , '/sitemap-%d-%%.xml' % current_website.id), + ('url', '=' , '/sitemap-%d.xml' % current_website.id)] + sitemaps = Attachment.search(dom) sitemaps.unlink() pages = 0 @@ -175,16 +178,17 @@ class Website(Home): if urls.strip(): content = View.render_template('website.sitemap_xml', {'content': urls}) pages += 1 - last_sitemap = create_sitemap('/sitemap-%d.xml' % pages, content) + last_sitemap = create_sitemap('/sitemap-%d-%d.xml' % (current_website.id, pages), content) else: break if not pages: return request.not_found() elif pages == 1: + # rename the -id-page.xml => -id.xml last_sitemap.write({ - 'url': "/sitemap.xml", - 'name': "/sitemap.xml" + 'url': "/sitemap-%d.xml" % current_website.id, + 'name': "/sitemap-%d.xml" % current_website.id, }) else: # Sitemaps must be split in several smaller files with a sitemap index @@ -192,7 +196,7 @@ class Website(Home): 'pages': range(1, pages + 1), 'url_root': request.httprequest.url_root, }) - create_sitemap('/sitemap.xml', content) + create_sitemap('/sitemap-%d.xml' % current_website.id, content) return request.make_response(content, [('Content-Type', mimetype)]) diff --git a/addons/website/models/ir_http.py b/addons/website/models/ir_http.py index 3edf0313e3f..ccee9a43721 100644 --- a/addons/website/models/ir_http.py +++ b/addons/website/models/ir_http.py @@ -371,6 +371,7 @@ class PageConverter(werkzeug.routing.PathConverter): query = query and query.startswith('website.') and query[8:] or query if query: domain += [('key', 'like', query)] + domain += ['|', ('website_id', '=', request.website.id), ('website_id', '=', False)] views = View.search_read(domain, fields=['key', 'priority', 'write_date'], order='name') for view in views: diff --git a/doc/cla/individual/hurrinico.md b/doc/cla/individual/hurrinico.md new file mode 100644 index 00000000000..67c5c355700 --- /dev/null +++ b/doc/cla/individual/hurrinico.md @@ -0,0 +1,11 @@ +Italy, 2016-11-25 + +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, + +Nicola Malcontenti nicola.malcontenti@agilebg.com https://github.com/hurrinico diff --git a/doc/cla/individual/kurkop.md b/doc/cla/individual/kurkop.md new file mode 100644 index 00000000000..ead18fbc4cb --- /dev/null +++ b/doc/cla/individual/kurkop.md @@ -0,0 +1,11 @@ +Colombia, 2015-12-23 + +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, + +Juan Pablo Arias jpa@devco.co https://github.com/kurkop diff --git a/doc/cla/individual/msmart.md b/doc/cla/individual/msmart.md new file mode 100644 index 00000000000..c834f591f21 --- /dev/null +++ b/doc/cla/individual/msmart.md @@ -0,0 +1,11 @@ +Germany, 2016-09-20 + +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, + +Michael Martinides michael@martinides.de https://github.com/msmart diff --git a/odoo/addons/base/ir/ir_qweb/fields.py b/odoo/addons/base/ir/ir_qweb/fields.py index 677763359c7..c7dadb1ce8f 100644 --- a/odoo/addons/base/ir/ir_qweb/fields.py +++ b/odoo/addons/base/ir/ir_qweb/fields.py @@ -97,6 +97,8 @@ class FieldConverter(models.AbstractModel): Converts the specified field of the browse_record ``record`` to HTML :rtype: unicode """ + if not record: + return False value = record[field_name] return False if value is False else record.env[self._name].value_to_html(value, options=options) diff --git a/odoo/addons/base/res/res_country_data.xml b/odoo/addons/base/res/res_country_data.xml index bd642c7c5c4..39282bef53d 100644 --- a/odoo/addons/base/res/res_country_data.xml +++ b/odoo/addons/base/res/res_country_data.xml @@ -354,6 +354,7 @@ + Costa Rica diff --git a/odoo/addons/base/res/res_currency_data.xml b/odoo/addons/base/res/res_currency_data.xml index b67ab0fc41d..c89552c5783 100644 --- a/odoo/addons/base/res/res_currency_data.xml +++ b/odoo/addons/base/res/res_currency_data.xml @@ -50,6 +50,7 @@ $ 0.01 + before