[MERGE] forward port branch 10.0 up to 1279f82e12

This commit is contained in:
Christophe Simonis
2017-03-06 13:52:06 +01:00
22 changed files with 112 additions and 38 deletions
@@ -0,0 +1,5 @@
li.oe_share_gdoc > a:after {
content: url('/google_drive/static/src/img/drive_icon.png');
position: absolute;
right: 5px;
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

+1 -1
View File
@@ -41,7 +41,7 @@ Sidebar.include({
}
if (!already_there){
self.add_items('other', [{
label: res.name+ '<img style="position:absolute;right:5px;height:20px;width:20px;" title="Google Drive" src="google_drive/static/src/img/drive_icon.png"/>',
label: res.name,
config_id: res.id,
res_id: res_id,
res_model: view.dataset.model,
@@ -3,6 +3,7 @@
<template id="assets_backend" name="google_drive assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<link rel="stylesheet" href="/google_drive/static/src/css/google_drive.css" />
<script type="text/javascript" src="/google_drive/static/src/js/gdrive.js"></script>
</xpath>
</template>
+5 -1
View File
@@ -8,6 +8,7 @@ import urllib2
import werkzeug
from odoo import http
from odoo.addons.payment.models.payment_acquirer import ValidationError
from odoo.http import request
_logger = logging.getLogger(__name__)
@@ -86,7 +87,10 @@ class PaypalController(http.Controller):
def paypal_ipn(self, **post):
""" Paypal IPN. """
_logger.info('Beginning Paypal IPN form_feedback with post data %s', pprint.pformat(post)) # debug
self.paypal_validate_data(**post)
try:
self.paypal_validate_data(**post)
except ValidationError:
_logger.exception('Unable to validate the Paypal payment')
return ''
@http.route('/payment/paypal/dpn', type='http', auth="none", methods=['POST', 'GET'], csrf=False)
+1 -1
View File
@@ -24,4 +24,4 @@ class PosInvoiceReport(models.AbstractModel):
not_invoiced_orders_names = list(map(lambda a: a.name, not_invoiced_posorders))
raise UserError(_('No link to an invoice for %s.') % ', '.join(not_invoiced_orders_names))
return Report.sudo().render('account.report_invoice', {'docs': self.env['account.invoice'].browse(ids_to_print)})
return Report.sudo().render('account.report_invoice', {'docs': self.env['account.invoice'].sudo().browse(ids_to_print)})
@@ -9,7 +9,7 @@
<div class="text-center">
<h2>Sales Details</h2>
<strong><t t-esc="date_start"/> - <t t-esc="date_stop"/></strong>
<strong><t t-esc="date_start" t-options="{'widget': 'datetime'}"/> - <t t-esc="date_stop" t-options="{'widget': 'datetime'}"/></strong>
</div>
<!-- Orderlines -->
+1 -1
View File
@@ -96,7 +96,7 @@ class ProductPriceHistory(models.Model):
company_id = fields.Many2one('res.company', default=_get_default_company_id, required=True)
product_id = fields.Many2one('product.product', 'Product', ondelete='cascade', required=True)
datetime = fields.Datetime('Date', default=fields.Datetime.now())
datetime = fields.Datetime('Date', default=fields.Datetime.now)
cost = fields.Float('Cost', digits=dp.get_precision('Product Price'))
@@ -162,10 +162,16 @@ class AccountInvoice(models.Model):
if valuation_price_unit != i_line.price_unit and line['price_unit'] == i_line.price_unit and acc:
# price with discount and without tax included
price_unit = i_line.price_unit * (1 - (i_line.discount or 0.0) / 100.0)
tax_ids = []
if line['tax_ids']:
#line['tax_ids'] is like [(4, tax_id, None), (4, tax_id2, None)...]
taxes = self.env['account.tax'].browse([x[1] for x in line['tax_ids']])
price_unit = taxes.compute_all(price_unit, currency=inv.currency_id, quantity=1.0)['total_excluded']
for tax in taxes:
tax_ids.append((4, tax.id, None))
for child in tax.children_tax_ids:
if child.type_tax_use != 'none':
tax_ids.append((4, child.id, None))
price_before = line.get('price', 0.0)
line.update({'price': round(valuation_price_unit * line['quantity'], account_prec)})
diff_res.append({
@@ -178,6 +184,7 @@ class AccountInvoice(models.Model):
'product_id': line['product_id'],
'uom_id': line['uom_id'],
'account_analytic_id': line['account_analytic_id'],
'tax_ids': tax_ids,
})
return diff_res
return []
+8 -4
View File
@@ -915,6 +915,11 @@ class SaleOrderLine(models.Model):
product_currency = None
if rule_id:
pricelist_item = PricelistItem.browse(rule_id)
if pricelist_item.pricelist_id.discount_policy == 'without_discount':
while pricelist_item.base == 'pricelist' and pricelist_item.base_pricelist_id and pricelist_item.base_pricelist_id.discount_policy == 'without_discount':
price, rule_id = pricelist_item.base_pricelist_id.with_context(uom=uom.id).get_product_price_rule(product, qty, self.order_id.partner_id)
pricelist_item = PricelistItem.browse(rule_id)
if pricelist_item.base == 'standard_price':
field_name = 'standard_price'
if pricelist_item.base == 'pricelist' and pricelist_item.base_pricelist_id:
@@ -951,8 +956,8 @@ class SaleOrderLine(models.Model):
self.env.user.has_group('sale.group_discount_per_so_line')):
return
context_partner = dict(self.env.context, partner_id=self.order_id.partner_id.id)
pricelist_context = dict(context_partner, uom=self.product_uom.id, date=self.order_id.date_order)
context_partner = dict(self.env.context, partner_id=self.order_id.partner_id.id, date=self.order_id.date_order)
pricelist_context = dict(context_partner, uom=self.product_uom.id)
price, rule_id = self.order_id.pricelist_id.with_context(pricelist_context).get_product_price_rule(self.product_id, self.product_uom_qty or 1.0, self.order_id.partner_id)
new_list_price, currency_id = self.with_context(context_partner)._get_real_price_currency(self.product_id, rule_id, self.product_uom_qty, self.product_uom, self.order_id.pricelist_id.id)
@@ -961,8 +966,7 @@ class SaleOrderLine(models.Model):
if price != 0 and new_list_price != 0:
if self.product_id.company_id and self.order_id.pricelist_id.currency_id != self.product_id.company_id.currency_id:
# new_list_price is in company's currency while price in pricelist currency
ctx = dict(context_partner, date=self.order_id.date_order)
new_list_price = self.env['res.currency'].browse(currency_id).with_context(ctx).compute(new_list_price, self.order_id.pricelist_id.currency_id)
new_list_price = self.env['res.currency'].browse(currency_id).with_context(context_partner).compute(new_list_price, self.order_id.pricelist_id.currency_id)
discount = (new_list_price - price) / new_list_price * 100
if discount > 0:
self.discount = discount
+6 -1
View File
@@ -88,8 +88,13 @@ class Inventory(models.Model):
exhausted = fields.Boolean('Include Exhausted Products', readonly=True, states={'draft': [('readonly', False)]})
@api.one
@api.depends('product_id', 'line_ids.product_qty')
def _compute_total_qty(self):
self.total_qty = sum(self.mapped('line_ids').mapped('product_qty'))
""" For single product inventory, total quantity of the counted """
if self.product_id:
self.total_qty = sum(self.mapped('line_ids').mapped('product_qty'))
else:
self.total_qty = 0
@api.model
def _selection_filter(self):
@@ -641,7 +641,7 @@ ListView.include(/** @lends instance.web.ListView# */{
if (saveInfo.created) {
return self.start_edition();
}
var options = { wraparound: !self.is_action_enabled('create') };
options.wraparound = !self.is_action_enabled('create');
var record = self.records[next_record](saveInfo.record, options);
if (record === undefined) {
return self.start_edition();
+5 -3
View File
@@ -1,8 +1,8 @@
odoo.define_section('web.registry', ['web.Registry'], {
beforeEach: function () {
this.Foo = {};
this.Bar = {};
this.Foo2 = {};
this.Foo = {bar: 1};
this.Bar = {foo: 0};
this.Foo2 = {fred: -1};
},
}, function (test) {
@@ -14,6 +14,8 @@ odoo.define_section('web.registry', ['web.Registry'], {
.add('bar', this.Bar);
assert.strictEqual(registry.get('foo'), this.Foo);
// make sure we're comparing actual objects instead of just undefineds
assert.deepEqual(registry.get('foo'), {bar: 1});
});
test('extension', function (assert, Registry) {
+29 -14
View File
@@ -16,7 +16,7 @@ odoo.testing.start_services = function () {
};
odoo.testing.MockRPC = function (session) {
this.responses = {};
this.clear();
};
odoo.testing.MockRPC.prototype.clear = function () {
@@ -81,8 +81,33 @@ odoo.define_section = function (name, section_deps) {
section_body = arguments[3];
}
QUnit.module(name, options);
mock = new odoo.testing.MockRPC();
function dummyfunc () {};
function beforeEach(assert) {
var services = odoo.testing.start_services();
this.deps = services;
this.getServiceDeps = function getServiceDeps(dep_names) {
return _.map(dep_names, function (name) { return services[name]; })
}
services['web.core'].qweb.add_template(odoo.testing.templates);
this.mock = mock;
this.mock.interceptRPC(services['web.session']);
this.assert = assert;
(options.beforeEach || dummyfunc).apply(this, [assert].concat(this.getServiceDeps(section_deps)));
}
function afterEach(assert) {
(options.afterEach || dummyfunc).apply(this, [assert].concat(this.getServiceDeps(section_deps)));
this.mock.clear();
}
QUnit.module(name, {
before: options.before,
beforeEach: beforeEach,
afterEach: afterEach,
after: options.after
});
function test () {
var name = arguments[0],
@@ -90,21 +115,11 @@ odoo.define_section = function (name, section_deps) {
body = arguments[arguments.length - 1];
QUnit.test(name, function (assert) {
var services = odoo.testing.start_services();
var deps = _.map(section_deps.concat(dep_names), function (name) { return services[name]; });
services['web.core'].qweb.add_template(odoo.testing.templates);
mock.clear();
mock.interceptRPC(services['web.session']);
var info = {
assert: assert,
mock: mock,
deps: _.pick.apply(null, [services].concat(section_deps).concat(dep_names)),
}
return body.apply(info, [assert].concat(deps));
var deps = this.getServiceDeps(section_deps.concat(dep_names));
return body.apply(this, [assert].concat(deps));
});
}
var mock = new odoo.testing.MockRPC();
section_body(test, mock);
};
@@ -288,6 +288,7 @@ var FieldTextHtml = widget.extend({
return src;
},
initialize_content: function () {
var self = this;
this.$el.closest('.modal-body').css('max-height', 'none');
this.$iframe = this.$el.find('iframe');
this.document = null;
@@ -296,6 +297,14 @@ var FieldTextHtml = widget.extend({
this.editor = false;
window.odoo[this.callback+"_updown"] = null;
this.$iframe.attr("src", this.get_url());
this.view.on("load_record", this, function(r){
if (!self.$body.find('.o_dirty').length){
var url = self.get_url();
if(url !== self.$iframe.attr("src")){
self.$iframe.attr("src", url);
}
}
});
},
on_content_loaded: function () {
var self = this;
@@ -204,6 +204,19 @@ odoo.define('website_sale.website_sale', function (require) {
event.preventDefault();
$(this).closest('form').submit();
}
if ($(this).hasClass('a-submit-disable')){
$(this).addClass("disabled");
}
if ($(this).hasClass('a-submit-loading')){
var loading = '<span class="fa fa-cog fa-spin"/>';
var fa_span = $(this).find('span[class*="fa"]');
if (fa_span.length){
fa_span.replaceWith(loading);
}
else{
$(this).append(loading);
}
}
});
$('form.js_attributes input, form.js_attributes select', oe_website_sale).on('change', function (event) {
if (!event.isDefaultPrevented()) {
@@ -397,7 +410,7 @@ odoo.define('website_sale.website_sale', function (require) {
//$("input[name='phone']").attr('placeholder', data.phone_code !== 0 ? '+'+ data.phone_code : '');
// populate states and display
var selectStates = $("select[name='state_id']:visible");
var selectStates = $("select[name='state_id']");
// dont reload state at first loading (done in qweb)
if (selectStates.data('init')===0 || selectStates.find('option').length===1) {
if (data.states.length) {
+1 -1
View File
@@ -1276,7 +1276,7 @@
<a t-att-href="mode == ('new', 'billing') and '/shop/cart' or '/shop/checkout'" class="btn btn-default mb32">
<span class="fa fa-long-arrow-left" /> Back
</a>
<a class="btn btn-default btn-primary pull-right mb32 a-submit">
<a class="btn btn-default btn-primary pull-right mb32 a-submit a-submit-disable a-submit-loading">
<span>Next </span><span class="fa fa-long-arrow-right" />
</a>
</div>
@@ -1,6 +1,6 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_slide_slide_public,slide.slide.public,model_slide_slide,base.group_public,1,0,0,0
access_slide_slide_portal,slide.slide.portal,model_slide_slide,base.group_portal,1,1,1,0
access_slide_slide_portal,slide.slide.portal,model_slide_slide,base.group_portal,1,0,0,0
access_slide_slide_user,slide.slide.user,model_slide_slide,base.group_user,1,1,1,1
access_slide_tag_public,slide.tag.public,model_slide_tag,base.group_public,1,0,0,0
access_slide_tag_portal,slide.tag.portal,model_slide_tag,base.group_portal,1,0,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_slide_slide_public slide.slide.public model_slide_slide base.group_public 1 0 0 0
3 access_slide_slide_portal slide.slide.portal model_slide_slide base.group_portal 1 1 0 1 0 0
4 access_slide_slide_user slide.slide.user model_slide_slide base.group_user 1 1 1 1
5 access_slide_tag_public slide.tag.public model_slide_tag base.group_public 1 0 0 0
6 access_slide_tag_portal slide.tag.portal model_slide_tag base.group_portal 1 0 0 0
@@ -17,7 +17,7 @@
<record id="rule_slide_channel_public" model="ir.rule">
<field name="name">Channel: public: published only</field>
<field name="model_id" ref="model_slide_channel"/>
<field name="groups" eval="[(4, ref('base.group_public'))]"/>
<field name="groups" eval="[(4, ref('base.group_public')) ,(4, ref('base.group_portal'))]"/>
<field name="domain_force">[('website_published', '=', True)]</field>
</record>
@@ -36,7 +36,7 @@
<record id="rule_slide_slide_public" model="ir.rule">
<field name="name">Slide: public: published only</field>
<field name="model_id" ref="model_slide_slide"/>
<field name="groups" eval="[(4, ref('base.group_public'))]"/>
<field name="groups" eval="[(4, ref('base.group_public')), (4, ref('base.group_portal'))]"/>
<field name="domain_force">[('channel_id.website_published', '=', True), ('website_published', '=', True)]</field>
</record>
</data>
+11
View File
@@ -0,0 +1,11 @@
Bosnia and Herzegovina, 2017-03-02
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,
Boško Stojaković bluesoft83@gmail.com https://github.com/bluesoft83
+2 -4
View File
@@ -136,10 +136,8 @@ class IrModel(models.Model):
for model in self:
if model.state != 'manual':
raise UserError(_("Model '%s' contains module data and cannot be removed!") % model.name)
# prevent screwing up fields that depend on these models' fields
for model in self:
model.field_id._prepare_update()
# prevent screwing up fields that depend on these models' fields
model.field_id._prepare_update()
self._drop_table()
res = super(IrModel, self).unlink()
+1 -1
View File
@@ -183,7 +183,7 @@ class Users(models.Model):
def _default_groups(self):
default_user = self.env.ref('base.default_user', raise_if_not_found=False)
return (default_user or self.env['res.users']).groups_id
return (default_user or self.env['res.users']).sudo().groups_id
def _companies_count(self):
return self.env['res.company'].sudo().search_count([])