[MERGE] forward port branch 9.0 up to 838beb12de
This commit is contained in:
@@ -51,6 +51,7 @@
|
||||
<field name="prefix">A</field>
|
||||
<field eval="1" name="number_next"/>
|
||||
<field eval="1" name="number_increment"/>
|
||||
<field eval="False" name="company_id"/>
|
||||
</record>
|
||||
<!--
|
||||
Invoice requests (deprecated)
|
||||
|
||||
@@ -722,6 +722,7 @@ class AccountInvoice(models.Model):
|
||||
or not."""
|
||||
return "%s-%s-%s-%s-%s-%s" % (
|
||||
invoice_line['account_id'],
|
||||
invoice_line.get('tax_ids', 'False'),
|
||||
invoice_line.get('tax_line_id', 'False'),
|
||||
invoice_line.get('product_id', 'False'),
|
||||
invoice_line.get('analytic_account_id', 'False'),
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
<group>
|
||||
<group>
|
||||
<field name="product_id"
|
||||
context="{'partner_id': parent.partner_id}"/>
|
||||
context="parent and {'partner_id': parent.partner_id}"/>
|
||||
<label for="quantity"/>
|
||||
<div>
|
||||
<field name="quantity" class="oe_inline"/>
|
||||
|
||||
@@ -203,6 +203,10 @@ class Employee(models.Model):
|
||||
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
if 'address_home_id' in vals:
|
||||
account_id = vals.get('bank_account_id') or self.bank_account_id.id
|
||||
if account_id:
|
||||
self.env['res.partner.bank'].browse(account_id).partner_id = vals['address_home_id']
|
||||
tools.image_resize_images(vals)
|
||||
return super(Employee, self).write(vals)
|
||||
|
||||
|
||||
@@ -14,8 +14,9 @@ class Partner(models.Model):
|
||||
|
||||
try:
|
||||
employee_group = self.env.ref('base.group_user')
|
||||
for user in employee_group.users:
|
||||
suggestions.append((user.partner_id.id, user.name, user.email))
|
||||
hr_suggestions = [{'id': user.partner_id.id, 'name': user.name, 'email': user.email}
|
||||
for user in employee_group.users]
|
||||
suggestions.append(hr_suggestions)
|
||||
return suggestions
|
||||
except AccessError:
|
||||
return suggestions
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
<field name="country_id" options='{"no_open": True, "no_create": True}'/>
|
||||
<field name="identification_id" groups="base.group_hr_user"/>
|
||||
<field name="passport_id" groups="base.group_hr_user"/>
|
||||
<field name="bank_account_id"/>
|
||||
<field name="bank_account_id" context="{'default_partner_id': address_home_id}"/>
|
||||
</group>
|
||||
<group string="Contact Information">
|
||||
<field name="address_home_id"
|
||||
|
||||
@@ -82,7 +82,7 @@ class Usb(Escpos):
|
||||
|
||||
def _raw(self, msg):
|
||||
""" Print any command sent in raw format """
|
||||
if len(msg) != self.device.write(self.out_ep, msg, self.interface):
|
||||
if len(msg) != self.device.write(self.out_ep, msg, self.interface, timeout=5000):
|
||||
self.device.write(self.out_ep, self.errorText, self.interface)
|
||||
raise TicketNotPrinted()
|
||||
|
||||
|
||||
@@ -24,8 +24,9 @@ class account_invoice(osv.osv):
|
||||
"""Add BBA Structured Communication Type and change labels from 'reference' into 'communication' """
|
||||
res = super(account_invoice, self)._get_reference_type(cursor, user,
|
||||
context=context)
|
||||
res[[i for i,x in enumerate(res) if x[0] == 'none'][0]] = ('none', 'Free Communication')
|
||||
res.append(('bba', 'BBA Structured Communication'))
|
||||
res[[i for i,x in enumerate(res) if x[0] == 'none'][0]] = \
|
||||
('none', _('Free Communication'))
|
||||
res.append(('bba', _('BBA Structured Communication')))
|
||||
#l_logger.warning('reference_type = %s' %res )
|
||||
return res
|
||||
|
||||
|
||||
@@ -11,7 +11,8 @@ class TestMassMailing(osv.TransientModel):
|
||||
_columns = {
|
||||
'email_to': fields.char('Recipients', required=True,
|
||||
help='Comma-separated list of email addresses.'),
|
||||
'mass_mailing_id': fields.many2one('mail.mass_mailing', 'Mailing', required=True),
|
||||
'mass_mailing_id': fields.many2one(
|
||||
'mail.mass_mailing', 'Mailing', required=True, ondelete='cascade'),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
|
||||
@@ -40,15 +40,15 @@
|
||||
<table class="o_group o_inner_group o_label_nowrap">
|
||||
<tr>
|
||||
<td class="o_td_label"><label for="old_pwd" class="o_form_label">Old Password</label></td>
|
||||
<td width="100%"><input type="password" class="o_form_field o_form_input" name="old_pwd" minlength="1" autofocus="autofocus"/></td>
|
||||
<td width="100%"><input type="password" class="o_form_field o_form_input" name="old_pwd" minlength="1" autofocus="autofocus" autocomplete="current-password"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="o_td_label"><label for="new_password" class="o_form_label">New Password</label></td>
|
||||
<td width="100%"><input type="password" class="o_form_field o_form_input" name="new_password" minlength="1"/></td>
|
||||
<td width="100%"><input type="password" class="o_form_field o_form_input" name="new_password" minlength="1" autocomplete="new-password"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="o_td_label"><label for="confirm_pwd" class="o_form_label">Confirm New Password</label></td>
|
||||
<td width="100%"><input type="password" class="o_form_field o_form_input" name="confirm_pwd" minlength="1"/></td>
|
||||
<td width="100%"><input type="password" class="o_form_field o_form_input" name="confirm_pwd" minlength="1" autocomplete="new-password"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@@ -647,6 +647,7 @@
|
||||
t-att-tabindex="widget.node.attrs.tabindex"
|
||||
t-att-autofocus="widget.node.attrs.autofocus"
|
||||
t-att-placeholder="widget.node.attrs.placeholder"
|
||||
t-att-autocomplete="widget.password ? 'new-password' : widget.node.attrs.autocomplete"
|
||||
t-att-maxlength="widget.field.size"/>
|
||||
</t>
|
||||
<t t-name="FormSelection">
|
||||
|
||||
@@ -246,7 +246,7 @@
|
||||
|
||||
<div class="form-group field-password">
|
||||
<label for="password" class="control-label">Password</label>
|
||||
<input type="password" name="password" id="password" class="form-control" required="required" t-att-autofocus="'autofocus' if login else None" maxlength="4096"/>
|
||||
<input type="password" name="password" id="password" class="form-control" required="required" autocomplete="current-password" t-att-autofocus="'autofocus' if login else None" maxlength="4096"/>
|
||||
</div>
|
||||
|
||||
<p class="alert alert-danger" t-if="error">
|
||||
|
||||
@@ -6,10 +6,6 @@ var website = require('website.website');
|
||||
var base = require('web_editor.base');
|
||||
require('website_sale.website_sale');
|
||||
|
||||
if(!$('.js_add_cart_variants[data-attribute_value_ids]').length) {
|
||||
return $.Deferred().reject("DOM doesn't contain '.js_add_cart_variants[data-attribute_value_ids]'");
|
||||
}
|
||||
|
||||
$('.oe_website_sale #add_to_cart, .oe_website_sale #products_grid .a-submit')
|
||||
.off('click')
|
||||
.removeClass('a-submit')
|
||||
@@ -28,9 +24,14 @@ $('.oe_website_sale #add_to_cart, .oe_website_sale #products_grid .a-submit')
|
||||
|
||||
$modal.find('img:first').attr("src", "/web/image/product.product/" + product_id + "/image_medium");
|
||||
|
||||
// disable opacity on the <form> if currently active (in case the product is
|
||||
// not published), as it interferes with bs modals
|
||||
$form.addClass('css_options');
|
||||
|
||||
$modal.appendTo($form)
|
||||
.modal()
|
||||
.on('hidden.bs.modal', function () {
|
||||
$form.removeClass('css_options'); // possibly reactivate opacity (see above)
|
||||
$(this).remove();
|
||||
});
|
||||
|
||||
|
||||
@@ -686,6 +686,15 @@ class module(osv.osv):
|
||||
if not self.pool['res.users'].has_group(cr, uid, 'base.group_system'):
|
||||
raise openerp.exceptions.AccessDenied()
|
||||
|
||||
# One-click install is opt-in - cfr Issue #15225
|
||||
ad_dir = openerp.tools.config.addons_data_dir
|
||||
if not os.access(ad_dir, os.W_OK):
|
||||
msg = (_("Automatic install of downloaded Apps is currently disabled.") + "\n\n" +
|
||||
_("To enable it, make sure this directory exists and is writable on the server:") +
|
||||
"\n%s" % ad_dir)
|
||||
_logger.warning(msg)
|
||||
raise openerp.exceptions.AccessError(msg)
|
||||
|
||||
apps_server = urlparse.urlparse(self.get_apps_server(cr, uid, context=context))
|
||||
|
||||
OPENERP = openerp.release.product_name.lower()
|
||||
|
||||
@@ -80,6 +80,12 @@ class test_inherits(common.TransactionCase):
|
||||
self.assertIn(daughter, partner_demo.daughter_ids)
|
||||
|
||||
# search the partner from the daughter record
|
||||
partners = self.env['res.partner'].search([('daughter_ids', 'like', 'not existing daugther')])
|
||||
self.assertFalse(partners)
|
||||
partners = self.env['res.partner'].search([('daughter_ids', 'not like', 'not existing daugther')])
|
||||
self.assertIn(partner_demo, partners)
|
||||
partners = self.env['res.partner'].search([('daughter_ids', '!=', False)])
|
||||
self.assertIn(partner_demo, partners)
|
||||
partners = self.env['res.partner'].search([('daughter_ids', 'in', daughter.ids)])
|
||||
self.assertIn(partner_demo, partners)
|
||||
|
||||
|
||||
@@ -130,7 +130,7 @@ def initialize_sys_path():
|
||||
global hooked
|
||||
|
||||
dd = tools.config.addons_data_dir
|
||||
if dd not in ad_paths:
|
||||
if os.access(dd, os.R_OK) and dd not in ad_paths:
|
||||
ad_paths.append(dd)
|
||||
|
||||
for ad in tools.config['addons_path'].split(','):
|
||||
|
||||
@@ -999,7 +999,14 @@ class expression(object):
|
||||
|
||||
if call_null:
|
||||
o2m_op = 'in' if operator in NEGATIVE_TERM_OPERATORS else 'not in'
|
||||
push(create_substitution_leaf(leaf, ('id', o2m_op, select_distinct_from_where_not_null(cr, column._fields_id, comodel._table)), model))
|
||||
# determine ids from column._fields_id
|
||||
if comodel._fields[column._fields_id].store:
|
||||
ids1 = select_distinct_from_where_not_null(cr, column._fields_id, comodel._table)
|
||||
else:
|
||||
ids2 = comodel.search(cr, uid, [(column._fields_id, '!=', False)], context=context)
|
||||
recs = comodel.browse(cr, SUPERUSER_ID, ids2, {'prefetch_fields': False})
|
||||
ids1 = recs.mapped(column._fields_id).ids
|
||||
push(create_substitution_leaf(leaf, ('id', o2m_op, ids1), model))
|
||||
|
||||
elif column._type == 'many2many':
|
||||
rel_table, rel_id1, rel_id2 = column._sql_names(model)
|
||||
|
||||
@@ -570,10 +570,11 @@ class configmanager(object):
|
||||
def addons_data_dir(self):
|
||||
d = os.path.join(self['data_dir'], 'addons', release.series)
|
||||
if not os.path.exists(d):
|
||||
os.makedirs(d, 0700)
|
||||
else:
|
||||
assert os.access(d, os.W_OK), \
|
||||
"%s: directory is not writable" % d
|
||||
try:
|
||||
# try to make +rx placeholder dir, will need manual +w to activate it
|
||||
os.makedirs(d, 0500)
|
||||
except OSError:
|
||||
logging.getLogger(__name__).debug('Failed to create addons data dir %s', d)
|
||||
return d
|
||||
|
||||
@property
|
||||
|
||||
Reference in New Issue
Block a user