[MERGE] forward port branch saas-14 up to a4d5e64a4c

This commit is contained in:
Christophe Simonis
2017-03-06 15:46:24 +01:00
32 changed files with 194 additions and 105 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>
@@ -108,7 +108,7 @@ msgstr ""
#. module: hr_timesheet_attendance
#: code:addons/hr_timesheet_attendance/models/hr_timesheet_sheet.py:85
#, python-format
msgid "The timesheet cannot be validated as it contains an attendance record with no Check Out)."
msgid "The timesheet cannot be validated as it contains an attendance record with no Check Out."
msgstr ""
#. module: hr_timesheet_attendance
@@ -82,7 +82,7 @@ class HrTimesheetSheet(models.Model):
"""
self.ensure_one()
if any(self.attendances_ids.filtered(lambda r: not r.check_out)):
raise UserError(_("The timesheet cannot be validated as it contains an attendance record with no Check Out)."))
raise UserError(_("The timesheet cannot be validated as it contains an attendance record with no Check Out."))
return True
+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 []
+1 -1
View File
@@ -21,7 +21,7 @@ class BaseConfigSettings(models.TransientModel):
}
def edit_external_header(self):
return self._prepare_report_view_action('report.layout_'+self.external_report_layout)
return self._prepare_report_view_action('report.external_layout_' + self.external_report_layout)
def change_report_template(self):
self.ensure_one()
+8 -4
View File
@@ -919,6 +919,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:
@@ -955,8 +960,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)
@@ -965,8 +970,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
+2 -2
View File
@@ -51,8 +51,8 @@ class SaleConfiguration(models.TransientModel):
group_proforma_sales = fields.Boolean(string="Pro-Forma", implied_group='sale.group_proforma_sales',
help="Allows you to send pro-forma.")
sale_show_tax = fields.Selection([
('subtotal', 'Tax-Included Prices'),
('total', 'Tax-Excluded Prices')], "Tax Display",
('subtotal', 'Tax-Excluded Prices'),
('total', 'Tax-Included Prices')], "Tax Display",
default='subtotal',
required=True)
default_invoice_policy = fields.Selection([
+6 -1
View File
@@ -89,8 +89,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):
@@ -707,11 +707,14 @@ var FieldBooleanButton = common.AbstractField.extend({
this.hover_false = _t("Open");
break;
default:
var terms = typeof this.options["terminology"] === 'string' ? {} : this.options["terminology"];
this.string_true = _t(terms.string_true || "On");
this.hover_true = _t(terms.hover_true || terms.string_false || "Switch Off");
this.string_false = _t(terms.string_false || "Off");
this.hover_false = _t(terms.hover_false || terms.string_true || "Switch On");
var opt_terms = this.options["terminology"] || {};
if (typeof opt_terms === 'string') {
opt_terms = {}; //unsupported terminology
}
this.string_true = _t(opt_terms.string_true) || _t("On");
this.hover_true = _t(opt_terms.hover_true) || _t("Switch Off");
this.string_false = _t(opt_terms.string_false) || _t("Off");
this.hover_false = _t(opt_terms.hover_false) || _t("Switch On");
}
},
render_value: function() {
@@ -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;
+4 -6
View File
@@ -328,12 +328,13 @@ class WebsiteSale(http.Controller):
@http.route(['/shop/pricelist'], type='http', auth="public", website=True)
def pricelist(self, promo, **post):
redirect = post.get('r', '/shop/cart')
pricelist = request.env['product.pricelist'].sudo().search([('code', '=', promo)], limit=1)
if pricelist and not request.website.is_pricelist_available(pricelist.id):
return request.redirect("/shop/cart?code_not_available=1")
if not pricelist or (pricelist and not request.website.is_pricelist_available(pricelist.id)):
return request.redirect("%s?code_not_available=1" % redirect)
request.website.sale_get_order(code=promo)
return request.redirect("/shop/cart")
return request.redirect(redirect)
@http.route(['/shop/cart'], type='http', auth="public", website=True)
def cart(self, **post):
@@ -359,9 +360,6 @@ class WebsiteSale(http.Controller):
if post.get('type') == 'popover':
return request.render("website_sale.cart_popover", values)
if post.get('code_not_available'):
values['code_not_available'] = post.get('code_not_available')
return request.render("website_sale.cart", values)
@http.route(['/shop/cart/update'], type='http', auth="public", methods=['POST'], website=True, csrf=False)
@@ -650,3 +650,12 @@ a.no-decoration {
.o_shadow_animation {
box-shadow: 0 0 5px 10px rgba(240, 8, 0, 0.4) !important;
}
#coupon_box form {
max-width: 300px;
}
.font-weight-normal {
font-weight: normal;
}
@@ -554,6 +554,12 @@ a.no-decoration
.break-word
word-wrap: break-word
#coupon_box form
max-width: 300px
.font-weight-normal
font-weight: normal
.o_website_sale_animate
opacity: 0.7
position: absolute
@@ -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) {
+40 -49
View File
@@ -1031,24 +1031,31 @@
</xpath>
</template>
<template id="reduction_code" inherit_id="website_sale.cart" active="True" customize_show="True" name="Coupon Code">
<template id='coupon_form' name='Coupon form'>
<t t-if="request.params.get('code_not_available')" name="code_not_available">
<p class="bg-warning">This promo code is not available</p>
</t>
<form t-if="website_sale_order and website_sale_order.website_order_line" t-att-action="'/shop/pricelist%s' % (redirect and '?r=' + redirect or '')"
method="post" class="mb32" name="coupon_code">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()" />
<div class="input-group">
<input name="promo" class="form-control" type="text" placeholder="code..." t-att-value="website_sale_order.pricelist_id.code or None" />
<div class="input-group-btn">
<a class="btn btn-default a-submit">Apply</a>
</div>
</div>
</form>
</template>
<template id="reduction_code" inherit_id="website_sale.cart" active="False" customize_show="True" name="Coupon Code">
<xpath expr="//div[@id='right_column']" position="inside">
<h4>Coupon Code</h4>
<p>
Have a coupon code? Fill in this field and apply.
</p>
<t t-if="code_not_available" name="code_not_available">
<p class="bg-warning">This promo code is not available</p>
<t t-call='website_sale.coupon_form'>
<t t-set='redirect'>/shop/cart</t>
</t>
<form t-if="website_sale_order and website_sale_order.website_order_line" action="/shop/pricelist" method="post" class="mb32" name="coupon_code">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()" />
<div class="input-group">
<input name="promo" class="form-control" type="text" placeholder="code..." t-att-value="website_sale_order.pricelist_id.code or None" />
<div class="input-group-btn">
<a class="btn btn-default a-submit">Apply</a>
</div>
</div>
</form>
</xpath>
</template>
@@ -1157,26 +1164,26 @@
<t t-call="website.layout">
<div id="wrap">
<div class="container oe_website_sale">
<div class="row">
<div class="col-md-8 col-md-offset-2 oe_cart">
<div class='row'>
<t t-call="website_sale.wizard_checkout">
<t t-set="step" t-value="20" />
</t>
</div>
<div class="row">
<div class="col-md-9 oe_cart">
<div class="row">
<t t-if="mode == ('new', 'billing')">
<h2 class="page-header mt16 ml16">Your Address
<h3 class="page-header mt32 ml16">Your Address
<small> or </small>
<t t-set='connect' t-value="request.env['ir.config_parameter'].sudo().get_param('auth_signup.allow_uninvited') == 'True' and ('signup', 'Sign Up') or ('login', 'Log In')"/>
<a t-attf-href='/web/{{connect[0]}}?redirect=/shop/checkout' class='btn btn-primary' style="margin-top: -11px"><t t-esc='connect[1]'/></a>
</h2>
</h3>
</t>
<t t-if="mode == ('edit', 'billing')">
<h2 class="page-header mt16 ml16">Your Address</h2>
<h3 class="page-header mt32 ml16">Your Address</h3>
</t>
<t t-if="mode[1] == 'shipping'">
<h2 class="page-header mt16 ml16">Shipping Address </h2>
<h3 class="page-header mt32 ml16">Shipping Address </h3>
</t>
<t t-if="error" t-foreach="error.get('error_message', [])" t-as="err">
<h4 class="text-danger" t-esc="err" />
@@ -1200,11 +1207,11 @@
<div class="clearfix" />
<t t-if="mode == ('new', 'billing')">
<div t-attf-class="form-group #{error.get('company_name') and 'has-error' or ''} col-md-6">
<label class="control-label" for="company_name">Company Name</label>
<label class="control-label font-weight-normal" for="company_name">Company Name</label>
<input type="text" name="company_name" class="form-control" t-att-value="'company_name' in checkout and checkout['company_name']" />
</div>
<div t-attf-class="form-group #{error.get('vat') and 'has-error' or ''} col-md-6 div_vat">
<label class="control-label" for="vat">TIN / VAT </label>
<label class="control-label font-weight-normal" for="vat">TIN / VAT </label>
<input type="text" name="vat" class="form-control" t-att-value="'vat' in checkout and checkout['vat']" />
</div>
</t>
@@ -1271,18 +1278,13 @@
<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>
</form>
</div>
</div>
<div class="col-md-3 text-muted hidden-sm hidden-xs">
<h2 class="page-header mt16 text-center">Your Order</h2>
<t t-set="website_sale_order" t-value="website.sale_get_order()" />
<t t-call="website_sale.total" />
</div>
</div>
</div>
</div>
@@ -1352,15 +1354,24 @@
</tbody>
</table>
</div>
<div class="row">
<div class="col-lg-5 col-sm-4 col-md-4 text-muted" id="coupon_box"/>
<div class="col-md-12">
<div class="col-lg-5 col-sm-6 col-xs-12 text-muted" id="coupon_box">
<t t-if="request.env.ref('website_sale.reduction_code').active">
<p>
Have a coupon code? Fill in this field and apply.
</p>
<t t-call='website_sale.coupon_form'>
<t t-set='redirect'>/shop/payment</t>
</t>
</t>
</div>
<t t-call="website_sale.total">
<t t-set='extra_class' t-value='"col-md-5 col-md-offset-7 col-xs-8 col-xs-offset-4"'/>
</t>
</div>
<div class="clearfix" />
<div class="oe_structure" />
<div class="js_payment mb64 row" t-if="acquirers and website_sale_order.amount_total" id="payment_method">
<div class="js_payment mb64 col-md-12 row" t-if="acquirers and website_sale_order.amount_total" id="payment_method">
<div class="col-lg-5 col-sm-6">
<h4>Payment Method:</h4>
<ul class="list-unstyled">
@@ -1441,26 +1452,6 @@
</t>
</template>
<template id="reduction_code_payment" inherit_id="website_sale.payment" active="True" customize_show="True" name="Coupon Code">
<xpath expr="//div[@id='coupon_box']" position="inside">
<p>
Have a coupon code? Fill in this field and apply.
</p>
<t t-if="code_not_available" name="code_not_available">
<p class="bg-warning">This promo code is not available</p>
</t>
<form t-if="website_sale_order and website_sale_order.website_order_line" action="/shop/pricelist_payment" method="post" class="mb32" name="coupon_code">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()" />
<div class="input-group">
<input name="promo" class="form-control" type="text" placeholder="code..." t-att-value="website_sale_order.pricelist_id.code or None" />
<div class="input-group-btn">
<a class="btn btn-default a-submit">Apply</a>
</div>
</div>
</form>
</xpath>
</template>
<template id="payment_sale_note" inherit_id="payment" name="Accept Terms &amp; Conditions" customize_show="True" active="False">
<xpath expr="//t[@id='acquirers_list']" position="before">
<div class="oe_accept_cgv_button">
@@ -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
+4 -3
View File
@@ -617,12 +617,13 @@ class IrActionsServer(models.Model):
""", (self.env.uid, 'server', self._cr.dbname, __name__, level, message, "action", action.id, action.name))
eval_context = super(IrActionsServer, self)._get_eval_context(action=action)
model = self.env[action.model_id.model]
model_name = action.model_id.sudo().model
model = self.env[model_name]
record = None
records = None
if self._context.get('active_model') == action.model_id.model and self._context.get('active_id'):
if self._context.get('active_model') == model_name and self._context.get('active_id'):
record = model.browse(self._context['active_id'])
if self._context.get('active_model') == action.model_id.model and self._context.get('active_ids'):
if self._context.get('active_model') == model_name and self._context.get('active_ids'):
records = model.browse(self._context['active_ids'])
if self._context.get('onchange_self'):
record = self._context['onchange_self']
+7
View File
@@ -7,6 +7,13 @@
<field name="mode">primary</field>
<field name="inherit_id" ref="base.view_server_action_form"/>
<field name="arch" type="xml">
<div class="oe_title" position="before">
<div class="oe_button_box" name="button_box">
<button name="toggle_active" type="object" class="oe_stat_button" icon="fa-archive">
<field name="active" widget="boolean_button"/>
</button>
</div>
</div>
<xpath expr="//button[@name='create_action']" position="replace">
<button name="method_direct_trigger" type="object" string="Run Manually" class="oe_highlight"/>
</xpath>
+2 -4
View File
@@ -164,10 +164,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([])