[MERGE] forward port of branch saas-4 up to 5087612
This commit is contained in:
commit
adf07a9490
|
@ -295,7 +295,8 @@ class account_invoice(osv.osv):
|
||||||
},
|
},
|
||||||
multi='all'),
|
multi='all'),
|
||||||
'currency_id': fields.many2one('res.currency', 'Currency', required=True, readonly=True, states={'draft':[('readonly',False)]}, track_visibility='always'),
|
'currency_id': fields.many2one('res.currency', 'Currency', required=True, readonly=True, states={'draft':[('readonly',False)]}, track_visibility='always'),
|
||||||
'journal_id': fields.many2one('account.journal', 'Journal', required=True, readonly=True, states={'draft':[('readonly',False)]}),
|
'journal_id': fields.many2one('account.journal', 'Journal', required=True, readonly=True, states={'draft':[('readonly',False)]},
|
||||||
|
domain="[('type', 'in', {'out_invoice': ['sale'], 'out_refund': ['sale_refund'], 'in_refund': ['purchase_refund'], 'in_invoice': ['purchase']}.get(type, [])), ('company_id', '=', company_id)]"),
|
||||||
'company_id': fields.many2one('res.company', 'Company', required=True, change_default=True, readonly=True, states={'draft':[('readonly',False)]}),
|
'company_id': fields.many2one('res.company', 'Company', required=True, change_default=True, readonly=True, states={'draft':[('readonly',False)]}),
|
||||||
'check_total': fields.float('Verification Total', digits_compute=dp.get_precision('Account'), readonly=True, states={'draft':[('readonly',False)]}),
|
'check_total': fields.float('Verification Total', digits_compute=dp.get_precision('Account'), readonly=True, states={'draft':[('readonly',False)]}),
|
||||||
'reconciled': fields.function(_reconciled, string='Paid/Reconciled', type='boolean',
|
'reconciled': fields.function(_reconciled, string='Paid/Reconciled', type='boolean',
|
||||||
|
|
|
@ -99,7 +99,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr t-foreach="get_lines_with_out_partner(data['form'])" t-as="not_partner">
|
<tr t-foreach="get_lines_with_out_partner(data['form'])" t-as="not_partner">
|
||||||
<td>
|
<td>
|
||||||
<span t-esc="partner['name']"/>
|
<span t-esc="not_partner['name']"/>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-right">
|
<td class="text-right">
|
||||||
<span t-esc="formatLang(not_partner['direction'], currency_obj=res_company.currency_id)"/>
|
<span t-esc="formatLang(not_partner['direction'], currency_obj=res_company.currency_id)"/>
|
||||||
|
|
|
@ -22,7 +22,6 @@ from dateutil.relativedelta import relativedelta
|
||||||
import datetime
|
import datetime
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
import traceback
|
|
||||||
|
|
||||||
from openerp.osv import osv, fields
|
from openerp.osv import osv, fields
|
||||||
from openerp.osv.orm import intersect, except_orm
|
from openerp.osv.orm import intersect, except_orm
|
||||||
|
@ -73,6 +72,7 @@ class account_analytic_invoice_line(osv.osv):
|
||||||
|
|
||||||
result = {}
|
result = {}
|
||||||
res = self.pool.get('product.product').browse(cr, uid, product, context=local_context)
|
res = self.pool.get('product.product').browse(cr, uid, product, context=local_context)
|
||||||
|
price = False
|
||||||
if price_unit is not False:
|
if price_unit is not False:
|
||||||
price = price_unit
|
price = price_unit
|
||||||
elif pricelist_id:
|
elif pricelist_id:
|
||||||
|
@ -746,29 +746,32 @@ class account_analytic_account(osv.osv):
|
||||||
contract_ids = ids
|
contract_ids = ids
|
||||||
else:
|
else:
|
||||||
contract_ids = self.search(cr, uid, [('recurring_next_date','<=', current_date), ('state','=', 'open'), ('recurring_invoices','=', True), ('type', '=', 'contract')])
|
contract_ids = self.search(cr, uid, [('recurring_next_date','<=', current_date), ('state','=', 'open'), ('recurring_invoices','=', True), ('type', '=', 'contract')])
|
||||||
for contract in self.browse(cr, uid, contract_ids, context=context):
|
if contract_ids:
|
||||||
try:
|
cr.execute('SELECT company_id, array_agg(id) as ids FROM account_analytic_account WHERE id IN %s GROUP BY company_id', (tuple(contract_ids),))
|
||||||
invoice_values = self._prepare_invoice(cr, uid, contract, context=context)
|
for company_id, ids in cr.fetchall():
|
||||||
invoice_ids.append(self.pool['account.invoice'].create(cr, uid, invoice_values, context=context))
|
for contract in self.browse(cr, uid, ids, context=dict(context, company_id=company_id, force_company=company_id)):
|
||||||
next_date = datetime.datetime.strptime(contract.recurring_next_date or current_date, "%Y-%m-%d")
|
try:
|
||||||
interval = contract.recurring_interval
|
invoice_values = self._prepare_invoice(cr, uid, contract, context=context)
|
||||||
if contract.recurring_rule_type == 'daily':
|
invoice_ids.append(self.pool['account.invoice'].create(cr, uid, invoice_values, context=context))
|
||||||
new_date = next_date+relativedelta(days=+interval)
|
next_date = datetime.datetime.strptime(contract.recurring_next_date or current_date, "%Y-%m-%d")
|
||||||
elif contract.recurring_rule_type == 'weekly':
|
interval = contract.recurring_interval
|
||||||
new_date = next_date+relativedelta(weeks=+interval)
|
if contract.recurring_rule_type == 'daily':
|
||||||
elif contract.recurring_rule_type == 'monthly':
|
new_date = next_date+relativedelta(days=+interval)
|
||||||
new_date = next_date+relativedelta(months=+interval)
|
elif contract.recurring_rule_type == 'weekly':
|
||||||
else:
|
new_date = next_date+relativedelta(weeks=+interval)
|
||||||
new_date = next_date+relativedelta(years=+interval)
|
elif contract.recurring_rule_type == 'monthly':
|
||||||
self.write(cr, uid, [contract.id], {'recurring_next_date': new_date.strftime('%Y-%m-%d')}, context=context)
|
new_date = next_date+relativedelta(months=+interval)
|
||||||
if automatic:
|
else:
|
||||||
cr.commit()
|
new_date = next_date+relativedelta(years=+interval)
|
||||||
except Exception:
|
self.write(cr, uid, [contract.id], {'recurring_next_date': new_date.strftime('%Y-%m-%d')}, context=context)
|
||||||
if automatic:
|
if automatic:
|
||||||
cr.rollback()
|
cr.commit()
|
||||||
_logger.error(traceback.format_exc())
|
except Exception:
|
||||||
else:
|
if automatic:
|
||||||
raise
|
cr.rollback()
|
||||||
|
_logger.exception('Fail to create recurring invoice for contract %s', contract.code)
|
||||||
|
else:
|
||||||
|
raise
|
||||||
return invoice_ids
|
return invoice_ids
|
||||||
|
|
||||||
class account_analytic_account_summary_user(osv.osv):
|
class account_analytic_account_summary_user(osv.osv):
|
||||||
|
|
|
@ -248,7 +248,7 @@
|
||||||
<page string="Bill Information">
|
<page string="Bill Information">
|
||||||
<field name="line_dr_ids" on_change="onchange_price(line_dr_ids, tax_id, partner_id)" context="{'journal_id':journal_id,'partner_id':partner_id}">
|
<field name="line_dr_ids" on_change="onchange_price(line_dr_ids, tax_id, partner_id)" context="{'journal_id':journal_id,'partner_id':partner_id}">
|
||||||
<tree string="Expense Lines" editable="bottom">
|
<tree string="Expense Lines" editable="bottom">
|
||||||
<field name="account_id" widget="selection" domain="[('user_type.report_type','=','expense'), ('type','!=','view')]"/>
|
<field name="account_id" domain="[('user_type.report_type','=','expense'), ('type','!=','view')]"/>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="amount"/>
|
<field name="amount"/>
|
||||||
<field name="account_analytic_id" groups="analytic.group_analytic_accounting"/>
|
<field name="account_analytic_id" groups="analytic.group_analytic_accounting"/>
|
||||||
|
|
|
@ -117,10 +117,22 @@ def sh256crypt(cls, password, salt, magic=magic_sha256):
|
||||||
class res_users(osv.osv):
|
class res_users(osv.osv):
|
||||||
_inherit = "res.users"
|
_inherit = "res.users"
|
||||||
|
|
||||||
|
def init(self, cr):
|
||||||
|
"""Encrypt all passwords at module installation"""
|
||||||
|
cr.execute("SELECT id, password FROM res_users WHERE password IS NOT NULL and password != ''")
|
||||||
|
for user in cr.fetchall():
|
||||||
|
self._set_encrypted_password(cr, user[0], user[1])
|
||||||
|
|
||||||
|
def _set_encrypted_password(self, cr, uid, plain_password):
|
||||||
|
"""Set an encrypted password for a given user"""
|
||||||
|
salt = gen_salt()
|
||||||
|
stored_password_crypt = md5crypt(plain_password, salt)
|
||||||
|
cr.execute("UPDATE res_users SET password = '', password_crypt = %s WHERE id = %s",
|
||||||
|
(stored_password_crypt, uid))
|
||||||
|
|
||||||
def set_pw(self, cr, uid, id, name, value, args, context):
|
def set_pw(self, cr, uid, id, name, value, args, context):
|
||||||
if value:
|
if value:
|
||||||
encrypted = md5crypt(value, gen_salt())
|
self._set_encrypted_password(cr, id, value)
|
||||||
cr.execute("update res_users set password='', password_crypt=%s where id=%s", (encrypted, id))
|
|
||||||
del value
|
del value
|
||||||
|
|
||||||
def get_pw( self, cr, uid, ids, name, args, context ):
|
def get_pw( self, cr, uid, ids, name, args, context ):
|
||||||
|
@ -144,9 +156,7 @@ class res_users(osv.osv):
|
||||||
if cr.rowcount:
|
if cr.rowcount:
|
||||||
stored_password, stored_password_crypt = cr.fetchone()
|
stored_password, stored_password_crypt = cr.fetchone()
|
||||||
if stored_password and not stored_password_crypt:
|
if stored_password and not stored_password_crypt:
|
||||||
salt = gen_salt()
|
self._set_encrypted_password(cr, uid, stored_password)
|
||||||
stored_password_crypt = md5crypt(stored_password, salt)
|
|
||||||
cr.execute("UPDATE res_users SET password='', password_crypt=%s WHERE id=%s", (stored_password_crypt, uid))
|
|
||||||
try:
|
try:
|
||||||
return super(res_users, self).check_credentials(cr, uid, password)
|
return super(res_users, self).check_credentials(cr, uid, password)
|
||||||
except openerp.exceptions.AccessDenied:
|
except openerp.exceptions.AccessDenied:
|
||||||
|
|
|
@ -74,7 +74,7 @@ class OAuthLogin(Home):
|
||||||
state = dict(
|
state = dict(
|
||||||
d=request.session.db,
|
d=request.session.db,
|
||||||
p=provider['id'],
|
p=provider['id'],
|
||||||
r=redirect,
|
r=werkzeug.url_quote_plus(redirect),
|
||||||
)
|
)
|
||||||
token = request.params.get('token')
|
token = request.params.get('token')
|
||||||
if token:
|
if token:
|
||||||
|
@ -143,7 +143,7 @@ class OAuthController(http.Controller):
|
||||||
cr.commit()
|
cr.commit()
|
||||||
action = state.get('a')
|
action = state.get('a')
|
||||||
menu = state.get('m')
|
menu = state.get('m')
|
||||||
redirect = state.get('r')
|
redirect = werkzeug.url_unquote_plus(state['r']) if state.get('r') else False
|
||||||
url = '/web'
|
url = '/web'
|
||||||
if redirect:
|
if redirect:
|
||||||
url = redirect
|
url = redirect
|
||||||
|
|
|
@ -102,7 +102,7 @@ openerp.calendar = function(instance) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var action_url = '';
|
var action_url = '';
|
||||||
|
|
||||||
action_url = _.str.sprintf('/?db=%s#id=%s&view_type=form&model=calendar.event', db, meeting_id);
|
action_url = _.str.sprintf('/web?db=%s#id=%s&view_type=form&model=calendar.event', db, meeting_id);
|
||||||
|
|
||||||
var reload_page = function(){
|
var reload_page = function(){
|
||||||
return location.replace(action_url);
|
return location.replace(action_url);
|
||||||
|
|
|
@ -32,7 +32,7 @@ class report_event_registration(osv.osv):
|
||||||
'draft_state': fields.integer(' # No of Draft Registrations', size=20),
|
'draft_state': fields.integer(' # No of Draft Registrations', size=20),
|
||||||
'confirm_state': fields.integer(' # No of Confirmed Registrations', size=20),
|
'confirm_state': fields.integer(' # No of Confirmed Registrations', size=20),
|
||||||
'seats_max': fields.integer('Max Seats'),
|
'seats_max': fields.integer('Max Seats'),
|
||||||
'nbevent': fields.integer('Number Of Events'),
|
'nbevent': fields.integer('Number of Registrations'),
|
||||||
'event_type': fields.many2one('event.type', 'Event Type'),
|
'event_type': fields.many2one('event.type', 'Event Type'),
|
||||||
'registration_state': fields.selection([('draft', 'Draft'), ('confirm', 'Confirmed'), ('done', 'Attended'), ('cancel', 'Cancelled')], 'Registration State', readonly=True, required=True),
|
'registration_state': fields.selection([('draft', 'Draft'), ('confirm', 'Confirmed'), ('done', 'Attended'), ('cancel', 'Cancelled')], 'Registration State', readonly=True, required=True),
|
||||||
'event_state': fields.selection([('draft', 'Draft'), ('confirm', 'Confirmed'), ('done', 'Done'), ('cancel', 'Cancelled')], 'Event State', readonly=True, required=True),
|
'event_state': fields.selection([('draft', 'Draft'), ('confirm', 'Confirmed'), ('done', 'Done'), ('cancel', 'Cancelled')], 'Event State', readonly=True, required=True),
|
||||||
|
@ -59,7 +59,7 @@ class report_event_registration(osv.osv):
|
||||||
r.name AS name_registration,
|
r.name AS name_registration,
|
||||||
e.company_id AS company_id,
|
e.company_id AS company_id,
|
||||||
e.date_begin AS event_date,
|
e.date_begin AS event_date,
|
||||||
count(e.id) AS nbevent,
|
count(r.id) AS nbevent,
|
||||||
CASE WHEN r.state IN ('draft') THEN r.nb_register ELSE 0 END AS draft_state,
|
CASE WHEN r.state IN ('draft') THEN r.nb_register ELSE 0 END AS draft_state,
|
||||||
CASE WHEN r.state IN ('open','done') THEN r.nb_register ELSE 0 END AS confirm_state,
|
CASE WHEN r.state IN ('open','done') THEN r.nb_register ELSE 0 END AS confirm_state,
|
||||||
e.type AS event_type,
|
e.type AS event_type,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
.oe_event_date{
|
.oe_event_date{
|
||||||
border-top-left-radius:3px;
|
border-top-left-radius:3px;
|
||||||
border-top-right-radius:3px;
|
border-top-right-radius:3px;
|
||||||
font-size: 48px;
|
font-size: 36px;
|
||||||
height: auto;
|
height: auto;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
|
@ -58,7 +58,7 @@ def start_end_date_for_period(period, default_start_date=False, default_end_date
|
||||||
end_date = default_end_date
|
end_date = default_end_date
|
||||||
|
|
||||||
if start_date and end_date:
|
if start_date and end_date:
|
||||||
return (start_date.strftime(DF), end_date.strftime(DF))
|
return (datetime.strftime(start_date, DF), datetime.strftime(end_date, DF))
|
||||||
else:
|
else:
|
||||||
return (start_date, end_date)
|
return (start_date, end_date)
|
||||||
|
|
||||||
|
|
|
@ -699,7 +699,7 @@ class google_calendar(osv.AbstractModel):
|
||||||
for att in att_obj.browse(cr, uid, my_att_ids, context=context):
|
for att in att_obj.browse(cr, uid, my_att_ids, context=context):
|
||||||
event = att.event_id
|
event = att.event_id
|
||||||
|
|
||||||
base_event_id = att.google_internal_event_id.split('_')[0]
|
base_event_id = att.google_internal_event_id.rsplit('_', 1)[0]
|
||||||
|
|
||||||
if base_event_id not in event_to_synchronize:
|
if base_event_id not in event_to_synchronize:
|
||||||
event_to_synchronize[base_event_id] = {}
|
event_to_synchronize[base_event_id] = {}
|
||||||
|
@ -721,7 +721,7 @@ class google_calendar(osv.AbstractModel):
|
||||||
|
|
||||||
for event in all_event_from_google.values():
|
for event in all_event_from_google.values():
|
||||||
event_id = event.get('id')
|
event_id = event.get('id')
|
||||||
base_event_id = event_id.split('_')[0]
|
base_event_id = event_id.rsplit('_', 1)[0]
|
||||||
|
|
||||||
if base_event_id not in event_to_synchronize:
|
if base_event_id not in event_to_synchronize:
|
||||||
event_to_synchronize[base_event_id] = {}
|
event_to_synchronize[base_event_id] = {}
|
||||||
|
@ -786,7 +786,7 @@ class google_calendar(osv.AbstractModel):
|
||||||
if actSrc == 'OE':
|
if actSrc == 'OE':
|
||||||
self.delete_an_event(cr, uid, current_event[0], context=context)
|
self.delete_an_event(cr, uid, current_event[0], context=context)
|
||||||
elif actSrc == 'GG':
|
elif actSrc == 'GG':
|
||||||
new_google_event_id = event.GG.event['id'].split('_')[1]
|
new_google_event_id = event.GG.event['id'].rsplit('_', 1)[1]
|
||||||
if 'T' in new_google_event_id:
|
if 'T' in new_google_event_id:
|
||||||
new_google_event_id = new_google_event_id.replace('T', '')[:-1]
|
new_google_event_id = new_google_event_id.replace('T', '')[:-1]
|
||||||
else:
|
else:
|
||||||
|
@ -795,7 +795,8 @@ class google_calendar(osv.AbstractModel):
|
||||||
if event.GG.status:
|
if event.GG.status:
|
||||||
parent_event = {}
|
parent_event = {}
|
||||||
if not event_to_synchronize[base_event][0][1].OE.event_id:
|
if not event_to_synchronize[base_event][0][1].OE.event_id:
|
||||||
event_to_synchronize[base_event][0][1].OE.event_id = att_obj.search_read(cr, uid, [('google_internal_event_id', '=', event.GG.event['id'].split('_')[0])], ['event_id'], context=context_novirtual)[0].get('event_id')[0]
|
main_ev = att_obj.search_read(cr, uid, [('google_internal_event_id', '=', event.GG.event['id'].rsplit('_', 1)[0])], fields=['event_id'], context=context_novirtual)
|
||||||
|
event_to_synchronize[base_event][0][1].OE.event_id = main_ev[0].get('event_id')[0]
|
||||||
|
|
||||||
parent_event['id'] = "%s-%s" % (event_to_synchronize[base_event][0][1].OE.event_id, new_google_event_id)
|
parent_event['id'] = "%s-%s" % (event_to_synchronize[base_event][0][1].OE.event_id, new_google_event_id)
|
||||||
res = self.update_from_google(cr, uid, parent_event, event.GG.event, "copy", context)
|
res = self.update_from_google(cr, uid, parent_event, event.GG.event, "copy", context)
|
||||||
|
|
|
@ -225,7 +225,7 @@ class hr_employee(osv.osv):
|
||||||
"resized as a 128x128px image, with aspect ratio preserved. "\
|
"resized as a 128x128px image, with aspect ratio preserved. "\
|
||||||
"Use this field in form views or some kanban views."),
|
"Use this field in form views or some kanban views."),
|
||||||
'image_small': fields.function(_get_image, fnct_inv=_set_image,
|
'image_small': fields.function(_get_image, fnct_inv=_set_image,
|
||||||
string="Smal-sized photo", type="binary", multi="_get_image",
|
string="Small-sized photo", type="binary", multi="_get_image",
|
||||||
store = {
|
store = {
|
||||||
'hr.employee': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
|
'hr.employee': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
|
||||||
},
|
},
|
||||||
|
|
|
@ -40,7 +40,9 @@
|
||||||
<page string="Public Information">
|
<page string="Public Information">
|
||||||
<group>
|
<group>
|
||||||
<group string="Contact Information">
|
<group string="Contact Information">
|
||||||
<field name="address_id" on_change="onchange_address_id(address_id)" context="{'show_address': 1}" options='{"always_reload": True, "highlight_first_line": True}'/>
|
<field name="address_id" on_change="onchange_address_id(address_id)"
|
||||||
|
context="{'show_address': 1, 'default_customer': False}"
|
||||||
|
options='{"always_reload": True, "highlight_first_line": True}'/>
|
||||||
<field name="mobile_phone"/>
|
<field name="mobile_phone"/>
|
||||||
<field name="work_location"/>
|
<field name="work_location"/>
|
||||||
</group>
|
</group>
|
||||||
|
@ -68,7 +70,9 @@
|
||||||
<field name="otherid" groups="base.group_hr_user"/>
|
<field name="otherid" groups="base.group_hr_user"/>
|
||||||
</group>
|
</group>
|
||||||
<group string="Contact Information">
|
<group string="Contact Information">
|
||||||
<field name="address_home_id" context="{'show_address': 1}" options='{"always_reload": True, "highlight_first_line": True}'/>
|
<field name="address_home_id"
|
||||||
|
context="{'show_address': 1, 'default_customer': False}"
|
||||||
|
options='{"always_reload": True, "highlight_first_line": True}'/>
|
||||||
</group>
|
</group>
|
||||||
<group string="Status">
|
<group string="Status">
|
||||||
<field name="gender"/>
|
<field name="gender"/>
|
||||||
|
|
|
@ -99,7 +99,7 @@ class hr_holidays_status(osv.osv):
|
||||||
for record in self.browse(cr, uid, ids, context=context):
|
for record in self.browse(cr, uid, ids, context=context):
|
||||||
name = record.name
|
name = record.name
|
||||||
if not record.limit:
|
if not record.limit:
|
||||||
name = name + (' (%d/%d)' % (record.leaves_taken or 0.0, record.max_leaves or 0.0))
|
name = name + (' (%g/%g)' % (record.leaves_taken or 0.0, record.max_leaves or 0.0))
|
||||||
res.append((record.id, name))
|
res.append((record.id, name))
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
|
@ -141,7 +141,7 @@ class account_invoice(osv.osv):
|
||||||
elif algorithm == 'random':
|
elif algorithm == 'random':
|
||||||
if not self.check_bbacomm(reference):
|
if not self.check_bbacomm(reference):
|
||||||
base = random.randint(1, 9999999999)
|
base = random.randint(1, 9999999999)
|
||||||
bbacomm = str(base).rjust(7, '0')
|
bbacomm = str(base).rjust(10, '0')
|
||||||
base = int(bbacomm)
|
base = int(bbacomm)
|
||||||
mod = base % 97 or 97
|
mod = base % 97 or 97
|
||||||
mod = str(mod).rjust(2, '0')
|
mod = str(mod).rjust(2, '0')
|
||||||
|
|
|
@ -34,6 +34,7 @@ import pytz
|
||||||
import socket
|
import socket
|
||||||
import time
|
import time
|
||||||
import xmlrpclib
|
import xmlrpclib
|
||||||
|
import re
|
||||||
from email.message import Message
|
from email.message import Message
|
||||||
from urllib import urlencode
|
from urllib import urlencode
|
||||||
|
|
||||||
|
@ -48,6 +49,8 @@ from openerp.tools.translate import _
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
mail_header_msgid_re = re.compile('<[^<>]+>')
|
||||||
|
|
||||||
def decode_header(message, header, separator=' '):
|
def decode_header(message, header, separator=' '):
|
||||||
return separator.join(map(decode, filter(None, message.get_all(header, []))))
|
return separator.join(map(decode, filter(None, message.get_all(header, []))))
|
||||||
|
|
||||||
|
@ -1311,13 +1314,13 @@ class mail_thread(osv.AbstractModel):
|
||||||
msg_dict['date'] = stored_date.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT)
|
msg_dict['date'] = stored_date.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT)
|
||||||
|
|
||||||
if message.get('In-Reply-To'):
|
if message.get('In-Reply-To'):
|
||||||
parent_ids = self.pool.get('mail.message').search(cr, uid, [('message_id', '=', decode(message['In-Reply-To']))])
|
parent_ids = self.pool.get('mail.message').search(cr, uid, [('message_id', '=', decode(message['In-Reply-To'].strip()))])
|
||||||
if parent_ids:
|
if parent_ids:
|
||||||
msg_dict['parent_id'] = parent_ids[0]
|
msg_dict['parent_id'] = parent_ids[0]
|
||||||
|
|
||||||
if message.get('References') and 'parent_id' not in msg_dict:
|
if message.get('References') and 'parent_id' not in msg_dict:
|
||||||
parent_ids = self.pool.get('mail.message').search(cr, uid, [('message_id', 'in',
|
msg_list = mail_header_msgid_re.findall(decode(message['References']))
|
||||||
[x.strip() for x in decode(message['References']).split()])])
|
parent_ids = self.pool.get('mail.message').search(cr, uid, [('message_id', 'in', [x.strip() for x in msg_list])])
|
||||||
if parent_ids:
|
if parent_ids:
|
||||||
msg_dict['parent_id'] = parent_ids[0]
|
msg_dict['parent_id'] = parent_ids[0]
|
||||||
|
|
||||||
|
|
|
@ -1071,8 +1071,8 @@ class mrp_production(osv.osv):
|
||||||
return False
|
return False
|
||||||
# Take routing location as a Source Location.
|
# Take routing location as a Source Location.
|
||||||
source_location_id = production.location_src_id.id
|
source_location_id = production.location_src_id.id
|
||||||
if production.bom_id.routing_id and production.bom_id.routing_id.location_id:
|
if production.routing_id and production.routing_id.location_id:
|
||||||
source_location_id = production.bom_id.routing_id.location_id.id
|
source_location_id = production.routing_id.location_id.id
|
||||||
|
|
||||||
destination_location_id = production.product_id.property_stock_production.id
|
destination_location_id = production.product_id.property_stock_production.id
|
||||||
if not source_location_id:
|
if not source_location_id:
|
||||||
|
|
|
@ -50,8 +50,8 @@
|
||||||
<field name="user_id" ref="base.user_demo"/>
|
<field name="user_id" ref="base.user_demo"/>
|
||||||
<field name="alias_model">project.task</field>
|
<field name="alias_model">project.task</field>
|
||||||
<field name="message_follower_ids" eval="[(6, 0, [
|
<field name="message_follower_ids" eval="[(6, 0, [
|
||||||
ref('base.user_root'),
|
ref('base.partner_root'),
|
||||||
ref('base.user_demo')])]"/>
|
ref('base.partner_demo')])]"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<!-- We assign after so that default values applies -->
|
<!-- We assign after so that default values applies -->
|
||||||
|
|
|
@ -2350,7 +2350,7 @@
|
||||||
}
|
}
|
||||||
.openerp .oe_fileupload .oe_add button.oe_attach .oe_e {
|
.openerp .oe_fileupload .oe_add button.oe_attach .oe_e {
|
||||||
position: relative;
|
position: relative;
|
||||||
top: -1px;
|
top: -10px;
|
||||||
left: -9px;
|
left: -9px;
|
||||||
}
|
}
|
||||||
.openerp .oe_fileupload .oe_add input.oe_form_binary_file {
|
.openerp .oe_fileupload .oe_add input.oe_form_binary_file {
|
||||||
|
@ -3301,6 +3301,9 @@ body.oe_single_form .oe_single_form_container {
|
||||||
.openerp_ie ul.oe_form_status li.oe_active > .arrow span, .openerp_ie ul.oe_form_status_clickable li.oe_active > .arrow span {
|
.openerp_ie ul.oe_form_status li.oe_active > .arrow span, .openerp_ie ul.oe_form_status_clickable li.oe_active > .arrow span {
|
||||||
background-color: #729fcf !important;
|
background-color: #729fcf !important;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
.openerp_ie .oe_webclient {
|
||||||
|
height: auto !important;
|
||||||
|
|
||||||
@media print {
|
@media print {
|
||||||
.openerp {
|
.openerp {
|
||||||
|
|
|
@ -1918,7 +1918,7 @@ $sheet-padding: 16px
|
||||||
text-shadow: none
|
text-shadow: none
|
||||||
.oe_e
|
.oe_e
|
||||||
position: relative
|
position: relative
|
||||||
top: -1px
|
top: -10px
|
||||||
left: -9px
|
left: -9px
|
||||||
input.oe_form_binary_file
|
input.oe_form_binary_file
|
||||||
display: inline-block
|
display: inline-block
|
||||||
|
@ -2670,6 +2670,8 @@ body.oe_single_form
|
||||||
> .arrow span
|
> .arrow span
|
||||||
background-color: #729fcf !important
|
background-color: #729fcf !important
|
||||||
|
|
||||||
|
.oe_webclient
|
||||||
|
height: auto !important
|
||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
// @media print {{{
|
// @media print {{{
|
||||||
|
|
|
@ -233,7 +233,8 @@ instance.web.parse_value = function (value, descriptor, value_if_empty) {
|
||||||
value = value.replace(instance.web._t.database.parameters.thousands_sep, "");
|
value = value.replace(instance.web._t.database.parameters.thousands_sep, "");
|
||||||
} while(tmp !== value);
|
} while(tmp !== value);
|
||||||
tmp = Number(value);
|
tmp = Number(value);
|
||||||
if (isNaN(tmp))
|
// do not accept not numbers or float values
|
||||||
|
if (isNaN(tmp) || tmp % 1)
|
||||||
throw new Error(_.str.sprintf(_t("'%s' is not a correct integer"), value));
|
throw new Error(_.str.sprintf(_t("'%s' is not a correct integer"), value));
|
||||||
return tmp;
|
return tmp;
|
||||||
case 'float':
|
case 'float':
|
||||||
|
@ -268,6 +269,11 @@ instance.web.parse_value = function (value, descriptor, value_if_empty) {
|
||||||
case 'datetime':
|
case 'datetime':
|
||||||
var datetime = Date.parseExact(
|
var datetime = Date.parseExact(
|
||||||
value, (date_pattern + ' ' + time_pattern));
|
value, (date_pattern + ' ' + time_pattern));
|
||||||
|
if (datetime !== null)
|
||||||
|
return instance.web.datetime_to_str(datetime);
|
||||||
|
datetime = Date.parseExact(value.replace(/\d+/g, function(m){
|
||||||
|
return m.length === 1 ? "0" + m : m ;
|
||||||
|
}), (date_pattern + ' ' + time_pattern));
|
||||||
if (datetime !== null)
|
if (datetime !== null)
|
||||||
return instance.web.datetime_to_str(datetime);
|
return instance.web.datetime_to_str(datetime);
|
||||||
datetime = Date.parse(value);
|
datetime = Date.parse(value);
|
||||||
|
@ -276,6 +282,11 @@ instance.web.parse_value = function (value, descriptor, value_if_empty) {
|
||||||
throw new Error(_.str.sprintf(_t("'%s' is not a correct datetime"), value));
|
throw new Error(_.str.sprintf(_t("'%s' is not a correct datetime"), value));
|
||||||
case 'date':
|
case 'date':
|
||||||
var date = Date.parseExact(value, date_pattern);
|
var date = Date.parseExact(value, date_pattern);
|
||||||
|
if (date !== null)
|
||||||
|
return instance.web.date_to_str(date);
|
||||||
|
date = Date.parseExact(value.replace(/\d+/g, function(m){
|
||||||
|
return m.length === 1 ? "0" + m : m ;
|
||||||
|
}), date_pattern);
|
||||||
if (date !== null)
|
if (date !== null)
|
||||||
return instance.web.date_to_str(date);
|
return instance.web.date_to_str(date);
|
||||||
date = Date.parse(value);
|
date = Date.parse(value);
|
||||||
|
|
|
@ -345,11 +345,11 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea
|
||||||
'keydown .oe_searchview_input, .oe_searchview_facet': function (e) {
|
'keydown .oe_searchview_input, .oe_searchview_facet': function (e) {
|
||||||
switch(e.which) {
|
switch(e.which) {
|
||||||
case $.ui.keyCode.LEFT:
|
case $.ui.keyCode.LEFT:
|
||||||
this.focusPreceding(this);
|
this.focusPreceding(e.target);
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
break;
|
break;
|
||||||
case $.ui.keyCode.RIGHT:
|
case $.ui.keyCode.RIGHT:
|
||||||
this.focusFollowing(this);
|
this.focusFollowing(e.target);
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2632,6 +2632,7 @@ instance.web.DateTimeWidget = instance.web.Widget.extend({
|
||||||
type_of_date: "datetime",
|
type_of_date: "datetime",
|
||||||
events: {
|
events: {
|
||||||
'change .oe_datepicker_master': 'change_datetime',
|
'change .oe_datepicker_master': 'change_datetime',
|
||||||
|
'keypress .oe_datepicker_master': 'change_datetime',
|
||||||
},
|
},
|
||||||
init: function(parent) {
|
init: function(parent) {
|
||||||
this._super(parent);
|
this._super(parent);
|
||||||
|
@ -2750,8 +2751,8 @@ instance.web.DateTimeWidget = instance.web.Widget.extend({
|
||||||
format_client: function(v) {
|
format_client: function(v) {
|
||||||
return instance.web.format_value(v, {"widget": this.type_of_date});
|
return instance.web.format_value(v, {"widget": this.type_of_date});
|
||||||
},
|
},
|
||||||
change_datetime: function() {
|
change_datetime: function(e) {
|
||||||
if (this.is_valid_()) {
|
if ((e.type !== "keypress" || e.which === 13) && this.is_valid_()) {
|
||||||
this.set_value_from_ui_();
|
this.set_value_from_ui_();
|
||||||
this.trigger("datetime_changed");
|
this.trigger("datetime_changed");
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,15 +130,7 @@
|
||||||
if (this.editable()) {
|
if (this.editable()) {
|
||||||
this.$el.find('table:first').show();
|
this.$el.find('table:first').show();
|
||||||
this.$el.find('.oe_view_nocontent').remove();
|
this.$el.find('.oe_view_nocontent').remove();
|
||||||
this.start_edition().then(function(){
|
this.start_edition();
|
||||||
var fields = self.editor.form.fields;
|
|
||||||
self.editor.form.fields_order.some(function(field){
|
|
||||||
if (fields[field].$el.is(':visible')){
|
|
||||||
fields[field].$el.find("input").select();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
this._super();
|
this._super();
|
||||||
}
|
}
|
||||||
|
@ -243,6 +235,7 @@
|
||||||
return this.ensure_saved().then(function () {
|
return this.ensure_saved().then(function () {
|
||||||
var $recordRow = self.groups.get_row_for(record);
|
var $recordRow = self.groups.get_row_for(record);
|
||||||
var cells = self.get_cells_for($recordRow);
|
var cells = self.get_cells_for($recordRow);
|
||||||
|
var fields = {};
|
||||||
self.fields_for_resize.splice(0, self.fields_for_resize.length);
|
self.fields_for_resize.splice(0, self.fields_for_resize.length);
|
||||||
return self.with_event('edit', {
|
return self.with_event('edit', {
|
||||||
record: record.attributes,
|
record: record.attributes,
|
||||||
|
@ -256,10 +249,16 @@
|
||||||
|
|
||||||
// FIXME: need better way to get the field back from bubbling (delegated) DOM events somehow
|
// FIXME: need better way to get the field back from bubbling (delegated) DOM events somehow
|
||||||
field.$el.attr('data-fieldname', field_name);
|
field.$el.attr('data-fieldname', field_name);
|
||||||
|
fields[field_name] = field;
|
||||||
self.fields_for_resize.push({field: field, cell: cell});
|
self.fields_for_resize.push({field: field, cell: cell});
|
||||||
}, options).then(function () {
|
}, options).then(function () {
|
||||||
$recordRow.addClass('oe_edition');
|
$recordRow.addClass('oe_edition');
|
||||||
self.resize_fields();
|
self.resize_fields();
|
||||||
|
var focus_field = options && options.focus_field ? options.focus_field : undefined;
|
||||||
|
if (!focus_field){
|
||||||
|
focus_field = _.find(self.editor.form.fields_order, function(field){ return fields[field] && fields[field].$el.is(':visible:has(input)'); });
|
||||||
|
}
|
||||||
|
if (focus_field) fields[focus_field].$el.find('input').select();
|
||||||
return record.attributes;
|
return record.attributes;
|
||||||
});
|
});
|
||||||
}).fail(function () {
|
}).fail(function () {
|
||||||
|
@ -749,31 +748,6 @@
|
||||||
throw new Error("is_editing's state filter must be either `new` or" +
|
throw new Error("is_editing's state filter must be either `new` or" +
|
||||||
" `edit` if provided");
|
" `edit` if provided");
|
||||||
},
|
},
|
||||||
_focus_setup: function (focus_field) {
|
|
||||||
var form = this.form;
|
|
||||||
|
|
||||||
var field;
|
|
||||||
// If a field to focus was specified
|
|
||||||
if (focus_field
|
|
||||||
// Is actually in the form
|
|
||||||
&& (field = form.fields[focus_field])
|
|
||||||
// And is visible
|
|
||||||
&& field.$el.is(':visible')) {
|
|
||||||
// focus it
|
|
||||||
field.focus();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_(form.fields_order).detect(function (name) {
|
|
||||||
// look for first visible field in fields_order, focus it
|
|
||||||
var field = form.fields[name];
|
|
||||||
if (!field.$el.is(':visible')) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Stop as soon as a field got focused
|
|
||||||
return field.focus() !== false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
edit: function (record, configureField, options) {
|
edit: function (record, configureField, options) {
|
||||||
// TODO: specify sequence of edit calls
|
// TODO: specify sequence of edit calls
|
||||||
var self = this;
|
var self = this;
|
||||||
|
@ -788,7 +762,6 @@
|
||||||
_(form.fields).each(function (field, name) {
|
_(form.fields).each(function (field, name) {
|
||||||
configureField(name, field);
|
configureField(name, field);
|
||||||
});
|
});
|
||||||
self._focus_setup(options && options.focus_field);
|
|
||||||
return form;
|
return form;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -218,7 +218,12 @@ openerp.web_calendar = function(instance) {
|
||||||
this.info_fields.push(fv.arch.children[fld].attrs.name);
|
this.info_fields.push(fv.arch.children[fld].attrs.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (new instance.web.Model(this.dataset.model))
|
var edit_check = new instance.web.Model(this.dataset.model)
|
||||||
|
.call("check_access_rights", ["write", false])
|
||||||
|
.then(function (write_right) {
|
||||||
|
self.write_right = write_right;
|
||||||
|
});
|
||||||
|
var init = new instance.web.Model(this.dataset.model)
|
||||||
.call("check_access_rights", ["create", false])
|
.call("check_access_rights", ["create", false])
|
||||||
.then(function (create_right) {
|
.then(function (create_right) {
|
||||||
self.create_right = create_right;
|
self.create_right = create_right;
|
||||||
|
@ -228,6 +233,7 @@ openerp.web_calendar = function(instance) {
|
||||||
self.ready.resolve();
|
self.ready.resolve();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
return $.when(edit_check, init);
|
||||||
},
|
},
|
||||||
|
|
||||||
get_fc_init_options: function () {
|
get_fc_init_options: function () {
|
||||||
|
@ -841,7 +847,11 @@ openerp.web_calendar = function(instance) {
|
||||||
if (! this.open_popup_action) {
|
if (! this.open_popup_action) {
|
||||||
var index = this.dataset.get_id_index(id);
|
var index = this.dataset.get_id_index(id);
|
||||||
this.dataset.index = index;
|
this.dataset.index = index;
|
||||||
this.do_switch_view('form', null, { mode: "edit" });
|
if (this.write_right) {
|
||||||
|
this.do_switch_view('form', null, { mode: "edit" });
|
||||||
|
} else {
|
||||||
|
this.do_switch_view('form', null, { mode: "view" });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var pop = new instance.web.form.FormOpenPopup(this);
|
var pop = new instance.web.form.FormOpenPopup(this);
|
||||||
|
|
|
@ -468,7 +468,7 @@
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
menu.on('click', 'a[data-action!=ace]', function (event) {
|
menu.on('click', 'a[data-view-id]', function (event) {
|
||||||
var view_id = $(event.currentTarget).data('view-id');
|
var view_id = $(event.currentTarget).data('view-id');
|
||||||
return openerp.jsonRpc('/web/dataset/call_kw', 'call', {
|
return openerp.jsonRpc('/web/dataset/call_kw', 'call', {
|
||||||
model: 'ir.ui.view',
|
model: 'ir.ui.view',
|
||||||
|
|
|
@ -120,7 +120,7 @@ class WebsiteForum(http.Controller):
|
||||||
|
|
||||||
question_count = Post.search(cr, uid, domain, count=True, context=context)
|
question_count = Post.search(cr, uid, domain, count=True, context=context)
|
||||||
if tag:
|
if tag:
|
||||||
url = "/forum/%s/%s/questions" % (slug(forum), slug(tag))
|
url = "/forum/%s/tag/%s/questions" % (slug(forum), slug(tag))
|
||||||
else:
|
else:
|
||||||
url = "/forum/%s" % slug(forum)
|
url = "/forum/%s" % slug(forum)
|
||||||
|
|
||||||
|
|
|
@ -148,7 +148,7 @@ function IsKarmaValid(eventNumber,minKarma){
|
||||||
CKEDITOR.tools.callFunction(eventNumber,this);
|
CKEDITOR.tools.callFunction(eventNumber,this);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
alert("Sorry you need more than 30 Karma.");
|
alert("Sorry you need more than " + minKarma + " Karma.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -92,9 +92,8 @@ class WebsiteMail(http.Controller):
|
||||||
values['is_follower'] = len(
|
values['is_follower'] = len(
|
||||||
request.registry['mail.followers'].search(
|
request.registry['mail.followers'].search(
|
||||||
cr, SUPERUSER_ID, [
|
cr, SUPERUSER_ID, [
|
||||||
('res_model', '=', 'mail.group'),
|
('res_model', '=', model),
|
||||||
('res_id', '=', obj_ids[0]),
|
('res_id', '=', obj_ids[0]),
|
||||||
('partner_id', '=', partner_id.id)
|
('partner_id', '=', partner_id.id)
|
||||||
], context=context)) == 1
|
], context=context)) == 1
|
||||||
|
|
||||||
return values
|
return values
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
(function () {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var website = openerp.website;
|
||||||
|
|
||||||
|
website.snippet.animationRegistry.follow = website.snippet.Animation.extend({
|
||||||
|
selector: ".js_follow",
|
||||||
|
start: function (editable_mode) {
|
||||||
|
var self = this;
|
||||||
|
this.is_user = false;
|
||||||
|
|
||||||
|
openerp.jsonRpc('/website_mail/is_follower', 'call', {
|
||||||
|
model: this.$target.data('object'),
|
||||||
|
id: this.$target.data('id'),
|
||||||
|
}).always(function (data) {
|
||||||
|
self.is_user = data.is_user;
|
||||||
|
self.email = data.email;
|
||||||
|
self.toggle_subscription(data.is_follower, data.email);
|
||||||
|
self.$target.removeClass("hidden");
|
||||||
|
});
|
||||||
|
|
||||||
|
// not if editable mode to allow designer to edit alert field
|
||||||
|
if (!editable_mode) {
|
||||||
|
$('.js_follow > .alert').addClass("hidden");
|
||||||
|
$('.js_follow > .input-group-btn.hidden').removeClass("hidden");
|
||||||
|
this.$target.find('.js_follow_btn, .js_unfollow_btn').on('click', function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
self.on_click();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
on_click: function () {
|
||||||
|
var self = this;
|
||||||
|
var $email = this.$target.find(".js_follow_email");
|
||||||
|
|
||||||
|
if ($email.length && !$email.val().match(/.+@.+/)) {
|
||||||
|
this.$target.addClass('has-error');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.$target.removeClass('has-error');
|
||||||
|
|
||||||
|
openerp.jsonRpc('/website_mail/follow', 'call', {
|
||||||
|
'id': +this.$target.data('id'),
|
||||||
|
'object': this.$target.data('object'),
|
||||||
|
'message_is_follower': this.$target.attr("data-follow") || "off",
|
||||||
|
'email': $email.length ? $email.val() : false,
|
||||||
|
}).then(function (follow) {
|
||||||
|
self.toggle_subscription(follow, self.email);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
toggle_subscription: function(follow, email) {
|
||||||
|
console.log(follow, email);
|
||||||
|
if (follow) {
|
||||||
|
this.$target.find(".js_follow_btn").addClass("hidden");
|
||||||
|
this.$target.find(".js_unfollow_btn").removeClass("hidden");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.$target.find(".js_follow_btn").removeClass("hidden");
|
||||||
|
this.$target.find(".js_unfollow_btn").addClass("hidden");
|
||||||
|
}
|
||||||
|
this.$target.find('input.js_follow_email')
|
||||||
|
.val(email ? email : "")
|
||||||
|
.attr("disabled", follow || (email.length && this.is_user) ? "disabled" : false);
|
||||||
|
this.$target.attr("data-follow", follow ? 'on' : 'off');
|
||||||
|
},
|
||||||
|
});
|
||||||
|
})();
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
<template id="head" inherit_id="website.assets_frontend" name="Mail customization">
|
<template id="head" inherit_id="website.assets_frontend" name="Mail customization">
|
||||||
<xpath expr="/t" position="inside">
|
<xpath expr="/t" position="inside">
|
||||||
|
<script type="text/javascript" src="/website_mail/static/src/js/follow.js"></script>
|
||||||
<link rel='stylesheet' href='/website_mail/static/src/css/website_mail.css'/>
|
<link rel='stylesheet' href='/website_mail/static/src/css/website_mail.css'/>
|
||||||
</xpath>
|
</xpath>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
|
|
||||||
var website = openerp.website;
|
var website = openerp.website;
|
||||||
|
|
||||||
website.snippet.animationRegistry.follow = website.snippet.Animation.extend({
|
website.snippet.animationRegistry.follow_alias = website.snippet.Animation.extend({
|
||||||
selector: ".js_follow",
|
selector: ".js_follow_alias",
|
||||||
start: function (editable_mode) {
|
start: function (editable_mode) {
|
||||||
var self = this;
|
var self = this;
|
||||||
this.is_user = false;
|
this.is_user = false;
|
||||||
|
@ -23,8 +23,8 @@
|
||||||
|
|
||||||
// not if editable mode to allow designer to edit alert field
|
// not if editable mode to allow designer to edit alert field
|
||||||
if (!editable_mode) {
|
if (!editable_mode) {
|
||||||
$('.js_follow > .alert').addClass("hidden");
|
$('.js_follow_alias > .alert').addClass("hidden");
|
||||||
$('.js_follow > .input-group-btn.hidden').removeClass("hidden");
|
$('.js_follow_alias > .input-group-btn.hidden').removeClass("hidden");
|
||||||
this.$target.find('.js_follow_btn, .js_unfollow_btn').on('click', function (event) {
|
this.$target.find('.js_follow_btn, .js_unfollow_btn').on('click', function (event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
self.on_click();
|
self.on_click();
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<span class="oe_snippet_thumbnail_title">Discussion Group</span>
|
<span class="oe_snippet_thumbnail_title">Discussion Group</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="oe_snippet_body js_follow"
|
<div class="oe_snippet_body js_follow_alias"
|
||||||
data-id="0"
|
data-id="0"
|
||||||
data-object="mail.group"
|
data-object="mail.group"
|
||||||
data-follow="off">
|
data-follow="off">
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
|
|
||||||
<xpath expr="//div[@id='snippet_options']" position="inside">
|
<xpath expr="//div[@id='snippet_options']" position="inside">
|
||||||
<div data-snippet-option-id='subscribe'
|
<div data-snippet-option-id='subscribe'
|
||||||
data-selector=".js_follow"
|
data-selector=".js_follow_alias"
|
||||||
data-selector-siblings="p, h1, h2, h3, blockquote, .well, .panel"
|
data-selector-siblings="p, h1, h2, h3, blockquote, .well, .panel"
|
||||||
>
|
>
|
||||||
<li>
|
<li>
|
||||||
|
|
|
@ -55,7 +55,7 @@ class table_compute(object):
|
||||||
self.table[(pos/PPR)+y2][(pos%PPR)+x2] = False
|
self.table[(pos/PPR)+y2][(pos%PPR)+x2] = False
|
||||||
self.table[pos/PPR][pos%PPR] = {
|
self.table[pos/PPR][pos%PPR] = {
|
||||||
'product': p, 'x':x, 'y': y,
|
'product': p, 'x':x, 'y': y,
|
||||||
'class': " ".join(map(lambda x: x.html_class, p.website_style_ids))
|
'class': " ".join(map(lambda x: x.html_class or '', p.website_style_ids))
|
||||||
}
|
}
|
||||||
if index<=PPG:
|
if index<=PPG:
|
||||||
maxy=max(maxy,y+(pos/PPR))
|
maxy=max(maxy,y+(pos/PPR))
|
||||||
|
|
|
@ -482,6 +482,8 @@ class ir_actions_server(osv.osv):
|
||||||
"based on the sequence. Low number means high priority."),
|
"based on the sequence. Low number means high priority."),
|
||||||
'model_id': fields.many2one('ir.model', 'Base Model', required=True, ondelete='cascade',
|
'model_id': fields.many2one('ir.model', 'Base Model', required=True, ondelete='cascade',
|
||||||
help="Base model on which the server action runs."),
|
help="Base model on which the server action runs."),
|
||||||
|
'model_name': fields.related('model_id', 'model', type='char',
|
||||||
|
string='Model Name', readonly=True),
|
||||||
'menu_ir_values_id': fields.many2one('ir.values', 'More Menu entry', readonly=True,
|
'menu_ir_values_id': fields.many2one('ir.values', 'More Menu entry', readonly=True,
|
||||||
help='More menu entry.'),
|
help='More menu entry.'),
|
||||||
# Client Action
|
# Client Action
|
||||||
|
@ -641,6 +643,10 @@ class ir_actions_server(osv.osv):
|
||||||
'wkf_field_id': False,
|
'wkf_field_id': False,
|
||||||
'crud_model_id': model_id,
|
'crud_model_id': model_id,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if model_id:
|
||||||
|
values['model_name'] = self.pool.get('ir.model').browse(cr, uid, model_id, context).model
|
||||||
|
|
||||||
return {'value': values}
|
return {'value': values}
|
||||||
|
|
||||||
def on_change_wkf_wonfig(self, cr, uid, ids, use_relational_model, wkf_field_id, wkf_model_id, model_id, context=None):
|
def on_change_wkf_wonfig(self, cr, uid, ids, use_relational_model, wkf_field_id, wkf_model_id, model_id, context=None):
|
||||||
|
@ -744,6 +750,7 @@ class ir_actions_server(osv.osv):
|
||||||
crud_model_name = False
|
crud_model_name = False
|
||||||
if crud_model_id:
|
if crud_model_id:
|
||||||
crud_model_name = self.pool.get('ir.model').browse(cr, uid, crud_model_id, context).model
|
crud_model_name = self.pool.get('ir.model').browse(cr, uid, crud_model_id, context).model
|
||||||
|
|
||||||
values = {'link_field_id': False, 'crud_model_name': crud_model_name}
|
values = {'link_field_id': False, 'crud_model_name': crud_model_name}
|
||||||
return {'value': values}
|
return {'value': values}
|
||||||
|
|
||||||
|
|
|
@ -349,8 +349,9 @@
|
||||||
Check to attach the newly created record to the record on which the server action runs.
|
Check to attach the newly created record to the record on which the server action runs.
|
||||||
</p>
|
</p>
|
||||||
<group>
|
<group>
|
||||||
|
<field name="model_name" invisible="1"/>
|
||||||
<field name="link_field_id"
|
<field name="link_field_id"
|
||||||
domain="[('model_id', '=', model_id), ('relation', '=', crud_model_name), ('ttype', 'in', ['many2one'])]"
|
domain="[('model_id', '=', crud_model_id), ('relation', '=', model_name), ('ttype', 'in', ['many2one'])]"
|
||||||
attrs="{'required': [('state', '=', 'object_create'), ('link_new_record', '=', True)],
|
attrs="{'required': [('state', '=', 'object_create'), ('link_new_record', '=', True)],
|
||||||
'invisible': ['|', ('state', '!=', 'object_create'), ('link_new_record', '=', False)]}"/>
|
'invisible': ['|', ('state', '!=', 'object_create'), ('link_new_record', '=', False)]}"/>
|
||||||
</group>
|
</group>
|
||||||
|
|
|
@ -561,7 +561,7 @@ class many2one(_column):
|
||||||
# we use uid=1 because the visibility of a many2one field value (just id and name)
|
# we use uid=1 because the visibility of a many2one field value (just id and name)
|
||||||
# must be the access right of the parent form and not the linked object itself.
|
# must be the access right of the parent form and not the linked object itself.
|
||||||
records = dict(obj.name_get(cr, SUPERUSER_ID,
|
records = dict(obj.name_get(cr, SUPERUSER_ID,
|
||||||
list(set([x for x in res.values() if isinstance(x, (int,long))])),
|
list(set([x for x in res.values() if x and isinstance(x, (int,long))])),
|
||||||
context=context))
|
context=context))
|
||||||
for id in res:
|
for id in res:
|
||||||
if res[id] in records:
|
if res[id] in records:
|
||||||
|
|
|
@ -3347,6 +3347,8 @@ class BaseModel(object):
|
||||||
return []
|
return []
|
||||||
if fields_to_read is None:
|
if fields_to_read is None:
|
||||||
fields_to_read = self._columns.keys()
|
fields_to_read = self._columns.keys()
|
||||||
|
else:
|
||||||
|
fields_to_read = list(set(fields_to_read))
|
||||||
|
|
||||||
# all inherited fields + all non inherited fields for which the attribute whose name is in load is True
|
# all inherited fields + all non inherited fields for which the attribute whose name is in load is True
|
||||||
fields_pre = [f for f in fields_to_read if
|
fields_pre = [f for f in fields_to_read if
|
||||||
|
|
Loading…
Reference in New Issue