[MERGE] forward port branch 10.0 up to 1279f82e12
This commit is contained in:
@@ -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 |
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 -->
|
||||
|
||||
@@ -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 []
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
|
@@ -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>
|
||||
|
||||
@@ -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
|
||||
@@ -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()
|
||||
|
||||
@@ -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([])
|
||||
|
||||
Reference in New Issue
Block a user