[MERGE] forward port of branch saas-3 up to revid 9409 dle@openerp.com-20140415101427-a6r7lgy50x9bdah3

bzr revid: chs@openerp.com-20140415142934-rlka4vkxd34fkil8
This commit is contained in:
Christophe Simonis 2014-04-15 16:29:34 +02:00
commit 61da3f4aba
14 changed files with 113 additions and 126 deletions

View File

@ -840,16 +840,11 @@ class account_journal(osv.osv):
def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=100): def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=100):
if not args: if not args:
args = [] args = []
if context is None: if operator in expression.NEGATIVE_TERM_OPERATORS:
context = {} domain = [('code', operator, name), ('name', operator, name)]
ids = [] else:
if context.get('journal_type', False): domain = ['|', ('code', operator, name), ('name', operator, name)]
args += [('type','=',context.get('journal_type'))] ids = self.search(cr, user, expression.AND([domain, args]), limit=limit, context=context)
if name:
ids = self.search(cr, user, [('code', 'ilike', name)]+ args, limit=limit, context=context)
if not ids:
ids = self.search(cr, user, [('name', 'ilike', name)]+ args, limit=limit, context=context)#fix it ilike should be replace with operator
return self.name_get(cr, user, ids, context=context) return self.name_get(cr, user, ids, context=context)
@ -938,13 +933,11 @@ class account_fiscalyear(osv.osv):
def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=80): def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=80):
if args is None: if args is None:
args = [] args = []
if context is None: if operator in expression.NEGATIVE_TERM_OPERATORS:
context = {} domain = [('code', operator, name), ('name', operator, name)]
ids = [] else:
if name: domain = ['|', ('code', operator, name), ('name', operator, name)]
ids = self.search(cr, user, [('code', 'ilike', name)]+ args, limit=limit) ids = self.search(cr, user, expression.AND([domain, args]), limit=limit, context=context)
if not ids:
ids = self.search(cr, user, [('name', operator, name)]+ args, limit=limit)
return self.name_get(cr, user, ids, context=context) return self.name_get(cr, user, ids, context=context)
@ -1040,19 +1033,11 @@ class account_period(osv.osv):
def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=100): def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=100):
if args is None: if args is None:
args = [] args = []
if context is None: if operator in expression.NEGATIVE_TERM_OPERATORS:
context = {} domain = [('code', operator, name), ('name', operator, name)]
ids = [] else:
if name: domain = ['|', ('code', operator, name), ('name', operator, name)]
ids = self.search(cr, user, ids = self.search(cr, user, expression.AND([domain, args]), limit=limit, context=context)
[('code', 'ilike', name)] + args,
limit=limit,
context=context)
if not ids:
ids = self.search(cr, user,
[('name', operator, name)] + args,
limit=limit,
context=context)
return self.name_get(cr, user, ids, context=context) return self.name_get(cr, user, ids, context=context)
def write(self, cr, uid, ids, vals, context=None): def write(self, cr, uid, ids, vals, context=None):
@ -1187,36 +1172,6 @@ class account_move(osv.osv):
'company_id': company_id, 'company_id': company_id,
} }
def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=80):
"""
Returns a list of tupples containing id, name, as internally it is called {def name_get}
result format: {[(id, name), (id, name), ...]}
@param cr: A database cursor
@param user: ID of the user currently logged in
@param name: name to search
@param args: other arguments
@param operator: default operator is 'ilike', it can be changed
@param context: context arguments, like lang, time zone
@param limit: Returns first 'n' ids of complete result, default is 80.
@return: Returns a list of tuples containing id and name
"""
if not args:
args = []
ids = []
if name:
ids += self.search(cr, user, [('name','ilike',name)]+args, limit=limit, context=context)
if not ids and name and type(name) == int:
ids += self.search(cr, user, [('id','=',name)]+args, limit=limit, context=context)
if not ids:
ids += self.search(cr, user, args, limit=limit, context=context)
return self.name_get(cr, user, ids, context=context)
def name_get(self, cursor, user, ids, context=None): def name_get(self, cursor, user, ids, context=None):
if isinstance(ids, (int, long)): if isinstance(ids, (int, long)):
ids = [ids] ids = [ids]
@ -1842,10 +1797,12 @@ class account_tax_code(osv.osv):
def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=80): def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=80):
if not args: if not args:
args = [] args = []
if context is None: if operator in expression.NEGATIVE_TERM_OPERATORS:
context = {} domain = [('code', operator, name), ('name', operator, name)]
ids = self.search(cr, user, ['|',('name',operator,name),('code',operator,name)] + args, limit=limit, context=context) else:
return self.name_get(cr, user, ids, context) domain = ['|', ('code', operator, name), ('name', operator, name)]
ids = self.search(cr, user, expression.AND([domain, args]), limit=limit, context=context)
return self.name_get(cr, user, ids, context=context)
def name_get(self, cr, uid, ids, context=None): def name_get(self, cr, uid, ids, context=None):
if isinstance(ids, (int, long)): if isinstance(ids, (int, long)):
@ -1974,15 +1931,11 @@ class account_tax(osv.osv):
""" """
if not args: if not args:
args = [] args = []
if context is None: if operator in expression.NEGATIVE_TERM_OPERATORS:
context = {} domain = [('description', operator, name), ('name', operator, name)]
ids = []
if name:
ids = self.search(cr, user, [('description', '=', name)] + args, limit=limit, context=context)
if not ids:
ids = self.search(cr, user, [('name', operator, name)] + args, limit=limit, context=context)
else: else:
ids = self.search(cr, user, args, limit=limit, context=context or {}) domain = ['|', ('description', operator, name), ('name', operator, name)]
ids = self.search(cr, user, expression.AND([domain, args]), limit=limit, context=context)
return self.name_get(cr, user, ids, context=context) return self.name_get(cr, user, ids, context=context)
def write(self, cr, uid, ids, vals, context=None): def write(self, cr, uid, ids, vals, context=None):

View File

@ -165,7 +165,7 @@ class account_invoice_refund(osv.osv_memory):
to_reconcile_ids = {} to_reconcile_ids = {}
for line in movelines: for line in movelines:
if line.account_id.id == inv.account_id.id: if line.account_id.id == inv.account_id.id:
to_reconcile_ids[line.account_id.id] = [line.id] to_reconcile_ids.setdefault(line.account_id.id, []).append(line.id)
if line.reconcile_id: if line.reconcile_id:
line.reconcile_id.unlink() line.reconcile_id.unlink()
inv_obj.signal_invoice_open(cr, uid, [refund.id]) inv_obj.signal_invoice_open(cr, uid, [refund.id])

View File

@ -162,7 +162,7 @@ class crossovered_budget_lines(osv.osv):
elapsed = strToDate(date_to) - strToDate(date_to) elapsed = strToDate(date_to) - strToDate(date_to)
if total.days: if total.days:
theo_amt = float(elapsed.days / float(total.days)) * line.planned_amount theo_amt = float((elapsed.days + 1) / float(total.days + 1)) * line.planned_amount
else: else:
theo_amt = line.planned_amount theo_amt = line.planned_amount

View File

@ -197,6 +197,10 @@ class calendar_attendee(osv.Model):
@param email_from: email address for user sending the mail @param email_from: email address for user sending the mail
""" """
res = False res = False
if self.pool['ir.config_parameter'].get_param(cr, uid, 'calendar.block_mail', default=False):
return res
mail_ids = [] mail_ids = []
data_pool = self.pool['ir.model.data'] data_pool = self.pool['ir.model.data']
mailmess_pool = self.pool['mail.message'] mailmess_pool = self.pool['mail.message']
@ -431,7 +435,7 @@ class calendar_alarm_manager(osv.AbstractModel):
if cron and len(cron) == 1: if cron and len(cron) == 1:
cron = self.pool.get('ir.cron').browse(cr, uid, cron[0], context=context) cron = self.pool.get('ir.cron').browse(cr, uid, cron[0], context=context)
else: else:
raise ("Cron for " + self._name + " not identified :( !") _logger.exception("Cron for " + self._name + " can not be identified !")
if cron.interval_type == "weeks": if cron.interval_type == "weeks":
cron_interval = cron.interval_number * 7 * 24 * 60 * 60 cron_interval = cron.interval_number * 7 * 24 * 60 * 60
@ -445,7 +449,7 @@ class calendar_alarm_manager(osv.AbstractModel):
cron_interval = cron.interval_number cron_interval = cron.interval_number
if not cron_interval: if not cron_interval:
raise ("Cron delay for " + self._name + " can not be calculated :( !") _logger.exception("Cron delay can not be computed !")
all_events = self.get_next_potential_limit_alarm(cr, uid, cron_interval, notif=False, context=context) all_events = self.get_next_potential_limit_alarm(cr, uid, cron_interval, notif=False, context=context)
@ -649,7 +653,7 @@ class calendar_event(osv.Model):
_inherit = ["mail.thread", "ir.needaction_mixin"] _inherit = ["mail.thread", "ir.needaction_mixin"]
def do_run_scheduler(self, cr, uid, id, context=None): def do_run_scheduler(self, cr, uid, id, context=None):
self.pool['calendar.alarm_manager'].do_run_scheduler(cr, uid, context=context) self.pool['calendar.alarm_manager'].get_next_mail(cr, uid, context=context)
def get_recurrent_date_by_event(self, cr, uid, event, context=None): def get_recurrent_date_by_event(self, cr, uid, event, context=None):
"""Get recurrent dates based on Rule string and all event where recurrent_id is child """Get recurrent dates based on Rule string and all event where recurrent_id is child

View File

@ -31,6 +31,7 @@ except ImportError:
from lxml import etree from lxml import etree
import logging import logging
import pytz import pytz
import socket
import time import time
import xmlrpclib import xmlrpclib
from email.message import Message from email.message import Message
@ -880,25 +881,30 @@ class mail_thread(osv.AbstractModel):
# 2. message is a reply to an existign thread (6.1 compatibility) # 2. message is a reply to an existign thread (6.1 compatibility)
ref_match = thread_references and tools.reference_re.search(thread_references) ref_match = thread_references and tools.reference_re.search(thread_references)
if ref_match: if ref_match:
thread_id = int(ref_match.group(1)) reply_thread_id = int(ref_match.group(1))
model = ref_match.group(2) or fallback_model reply_model = ref_match.group(2) or fallback_model
if thread_id and model in self.pool: reply_hostname = ref_match.group(3)
model_obj = self.pool[model] local_hostname = socket.gethostname()
compat_mail_msg_ids = mail_msg_obj.search( # do not match forwarded emails from another OpenERP system (thread_id collision!)
cr, uid, [ if local_hostname == reply_hostname:
('message_id', '=', False), thread_id, model = reply_thread_id, reply_model
('model', '=', model), if thread_id and model in self.pool:
('res_id', '=', thread_id), model_obj = self.pool[model]
], context=context) compat_mail_msg_ids = mail_msg_obj.search(
if compat_mail_msg_ids and model_obj.exists(cr, uid, thread_id) and hasattr(model_obj, 'message_update'): cr, uid, [
_logger.info( ('message_id', '=', False),
'Routing mail from %s to %s with Message-Id %s: direct thread reply (compat-mode) to model: %s, thread_id: %s, custom_values: %s, uid: %s', ('model', '=', model),
email_from, email_to, message_id, model, thread_id, custom_values, uid) ('res_id', '=', thread_id),
route = self.message_route_verify( ], context=context)
cr, uid, message, message_dict, if compat_mail_msg_ids and model_obj.exists(cr, uid, thread_id) and hasattr(model_obj, 'message_update'):
(model, thread_id, custom_values, uid, None), _logger.info(
update_author=True, assert_model=True, create_fallback=True, context=context) 'Routing mail from %s to %s with Message-Id %s: direct thread reply (compat-mode) to model: %s, thread_id: %s, custom_values: %s, uid: %s',
return route and [route] or [] email_from, email_to, message_id, model, thread_id, custom_values, uid)
route = self.message_route_verify(
cr, uid, message, message_dict,
(model, thread_id, custom_values, uid, None),
update_author=True, assert_model=True, create_fallback=True, context=context)
return route and [route] or []
# 2. Reply to a private message # 2. Reply to a private message
if in_reply_to: if in_reply_to:

View File

@ -21,6 +21,7 @@
from openerp.addons.mail.tests.common import TestMail from openerp.addons.mail.tests.common import TestMail
from openerp.tools import mute_logger from openerp.tools import mute_logger
import socket
MAIL_TEMPLATE = """Return-Path: <whatever-2a840@postmaster.twitter.com> MAIL_TEMPLATE = """Return-Path: <whatever-2a840@postmaster.twitter.com>
To: {to} To: {to}
@ -400,13 +401,15 @@ class TestMailgateway(TestMail):
to='noone@example.com', subject='spam', to='noone@example.com', subject='spam',
extra='In-Reply-To: <12321321-openerp-%d-mail.group@example.com>' % frog_group.id, extra='In-Reply-To: <12321321-openerp-%d-mail.group@example.com>' % frog_group.id,
msg_id='<1.1.JavaMail.new@agrolait.com>') msg_id='<1.1.JavaMail.new@agrolait.com>')
# There are 6.1 messages, activate compat mode
# When 6.1 messages are present, compat mode is available
# Create a fake 6.1 message
tmp_msg_id = self.mail_message.create(cr, uid, {'message_id': False, 'model': 'mail.group', 'res_id': frog_group.id}) tmp_msg_id = self.mail_message.create(cr, uid, {'message_id': False, 'model': 'mail.group', 'res_id': frog_group.id})
# Do: compat mode accepts partial-matching emails # Do: compat mode accepts partial-matching emails
frog_groups = format_and_process(MAIL_TEMPLATE, email_from='other5@gmail.com', frog_groups = format_and_process(MAIL_TEMPLATE, email_from='other5@gmail.com',
msg_id='<1.2.JavaMail.new@agrolait.com>', msg_id='<1.2.JavaMail.new@agrolait.com>',
to='noone@example.com>', subject='spam', to='noone@example.com>', subject='spam',
extra='In-Reply-To: <12321321-openerp-%d-mail.group@example.com>' % frog_group.id) extra='In-Reply-To: <12321321-openerp-%d-mail.group@%s>' % (frog_group.id, socket.gethostname()))
self.mail_message.unlink(cr, uid, [tmp_msg_id]) self.mail_message.unlink(cr, uid, [tmp_msg_id])
# Test: no group 'Re: news' created, still only 1 Frogs group # Test: no group 'Re: news' created, still only 1 Frogs group
self.assertEqual(len(frog_groups), 0, self.assertEqual(len(frog_groups), 0,
@ -418,6 +421,17 @@ class TestMailgateway(TestMail):
# Test: one new message # Test: one new message
self.assertEqual(len(frog_group.message_ids), 4, 'message_process: group should contain 4 messages after reply') self.assertEqual(len(frog_group.message_ids), 4, 'message_process: group should contain 4 messages after reply')
# 6.1 compat mode should not work if hostname does not match!
tmp_msg_id = self.mail_message.create(cr, uid, {'message_id': False, 'model': 'mail.group', 'res_id': frog_group.id})
self.assertRaises(ValueError,
format_and_process,
MAIL_TEMPLATE, email_from='other5@gmail.com',
msg_id='<1.3.JavaMail.new@agrolait.com>',
to='noone@example.com>', subject='spam',
extra='In-Reply-To: <12321321-openerp-%d-mail.group@neighbor.com>' % frog_group.id)
self.mail_message.unlink(cr, uid, [tmp_msg_id])
# Do: due to some issue, same email goes back into the mailgateway # Do: due to some issue, same email goes back into the mailgateway
frog_groups = format_and_process(MAIL_TEMPLATE, email_from='other4@gmail.com', frog_groups = format_and_process(MAIL_TEMPLATE, email_from='other4@gmail.com',
msg_id='<1198923581.41972151344608186760.JavaMail.diff1@agrolait.com>', msg_id='<1198923581.41972151344608186760.JavaMail.diff1@agrolait.com>',
@ -445,7 +459,7 @@ class TestMailgateway(TestMail):
# Do: post a new message, with a known partner -> duplicate emails -> partner # Do: post a new message, with a known partner -> duplicate emails -> partner
format_and_process(MAIL_TEMPLATE, email_from='Lombrik Lubrik <test_raoul@email.com>', format_and_process(MAIL_TEMPLATE, email_from='Lombrik Lubrik <test_raoul@email.com>',
to='erroneous@example.com>', subject='Re: news (2)', subject='Re: news (2)',
msg_id='<1198923581.41972151344608186760.JavaMail.new1@agrolait.com>', msg_id='<1198923581.41972151344608186760.JavaMail.new1@agrolait.com>',
extra='In-Reply-To: <1198923581.41972151344608186799.JavaMail.diff1@agrolait.com>') extra='In-Reply-To: <1198923581.41972151344608186799.JavaMail.diff1@agrolait.com>')
frog_groups = self.mail_group.search(cr, uid, [('name', '=', 'Frogs')]) frog_groups = self.mail_group.search(cr, uid, [('name', '=', 'Frogs')])
@ -456,10 +470,9 @@ class TestMailgateway(TestMail):
# Do: post a new message, with a known partner -> duplicate emails -> user # Do: post a new message, with a known partner -> duplicate emails -> user
frog_group.message_unsubscribe([extra_partner_id]) frog_group.message_unsubscribe([extra_partner_id])
raoul_email = self.user_raoul.email
self.res_users.write(cr, uid, self.user_raoul_id, {'email': 'test_raoul@email.com'}) self.res_users.write(cr, uid, self.user_raoul_id, {'email': 'test_raoul@email.com'})
format_and_process(MAIL_TEMPLATE, email_from='Lombrik Lubrik <test_raoul@email.com>', format_and_process(MAIL_TEMPLATE, email_from='Lombrik Lubrik <test_raoul@email.com>',
to='erroneous@example.com>', subject='Re: news (3)', to='groups@example.com', subject='Re: news (3)',
msg_id='<1198923581.41972151344608186760.JavaMail.new2@agrolait.com>', msg_id='<1198923581.41972151344608186760.JavaMail.new2@agrolait.com>',
extra='In-Reply-To: <1198923581.41972151344608186799.JavaMail.diff1@agrolait.com>') extra='In-Reply-To: <1198923581.41972151344608186799.JavaMail.diff1@agrolait.com>')
frog_groups = self.mail_group.search(cr, uid, [('name', '=', 'Frogs')]) frog_groups = self.mail_group.search(cr, uid, [('name', '=', 'Frogs')])
@ -474,7 +487,7 @@ class TestMailgateway(TestMail):
raoul_email = self.user_raoul.email raoul_email = self.user_raoul.email
self.res_users.write(cr, uid, self.user_raoul_id, {'email': 'test_raoul@email.com'}) self.res_users.write(cr, uid, self.user_raoul_id, {'email': 'test_raoul@email.com'})
format_and_process(MAIL_TEMPLATE, email_from='Lombrik Lubrik <test_raoul@email.com>', format_and_process(MAIL_TEMPLATE, email_from='Lombrik Lubrik <test_raoul@email.com>',
to='erroneous@example.com>', subject='Re: news (3)', to='groups@example.com', subject='Re: news (3)',
msg_id='<1198923581.41972151344608186760.JavaMail.new3@agrolait.com>', msg_id='<1198923581.41972151344608186760.JavaMail.new3@agrolait.com>',
extra='In-Reply-To: <1198923581.41972151344608186799.JavaMail.diff1@agrolait.com>') extra='In-Reply-To: <1198923581.41972151344608186799.JavaMail.diff1@agrolait.com>')
frog_groups = self.mail_group.search(cr, uid, [('name', '=', 'Frogs')]) frog_groups = self.mail_group.search(cr, uid, [('name', '=', 'Frogs')])

View File

@ -29,7 +29,7 @@ from openerp.osv import osv
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
class MailThread(osv.Model): class MailThread(osv.AbstractModel):
""" Update MailThread to add the feature of bounced emails and replied emails """ Update MailThread to add the feature of bounced emails and replied emails
in message_process. """ in message_process. """
_name = 'mail.thread' _name = 'mail.thread'

View File

@ -133,10 +133,7 @@ class purchase_order(osv.osv):
def _invoiced(self, cursor, user, ids, name, arg, context=None): def _invoiced(self, cursor, user, ids, name, arg, context=None):
res = {} res = {}
for purchase in self.browse(cursor, user, ids, context=context): for purchase in self.browse(cursor, user, ids, context=context):
invoiced = False res[purchase.id] = all(line.invoiced for line in purchase.order_line)
if purchase.invoiced_rate == 100.00:
invoiced = True
res[purchase.id] = invoiced
return res return res
def _get_journal(self, cr, uid, context=None): def _get_journal(self, cr, uid, context=None):
@ -542,7 +539,7 @@ class purchase_order(osv.osv):
inv_line_id = inv_line_obj.create(cr, uid, inv_line_data, context=context) inv_line_id = inv_line_obj.create(cr, uid, inv_line_data, context=context)
inv_lines.append(inv_line_id) inv_lines.append(inv_line_id)
po_line.write({'invoiced': True, 'invoice_lines': [(4, inv_line_id)]}, context=context) po_line.write({'invoice_lines': [(4, inv_line_id)]}, context=context)
# get invoice data and create invoice # get invoice data and create invoice
inv_data = { inv_data = {
@ -1290,9 +1287,15 @@ class account_invoice(osv.Model):
else: else:
user_id = uid user_id = uid
po_ids = purchase_order_obj.search(cr, user_id, [('invoice_ids', 'in', ids)], context=context) po_ids = purchase_order_obj.search(cr, user_id, [('invoice_ids', 'in', ids)], context=context)
for po_id in po_ids: for order in purchase_order_obj.browse(cr, uid, po_ids, context=context):
purchase_order_obj.message_post(cr, user_id, po_id, body=_("Invoice received"), context=context) purchase_order_obj.message_post(cr, user_id, order.id, body=_("Invoice received"), context=context)
workflow.trg_write(uid, 'purchase.order', po_id, cr) invoiced = []
for po_line in order.order_line:
if any(line.invoice_id.state not in ['draft', 'cancel'] for line in po_line.invoice_lines):
invoiced.append(po_line.id)
if invoiced:
self.pool['purchase.order.line'].write(cr, uid, invoiced, {'invoiced': True})
workflow.trg_write(uid, 'purchase.order', order.id, cr)
return res return res
def confirm_paid(self, cr, uid, ids, context=None): def confirm_paid(self, cr, uid, ids, context=None):

View File

@ -110,7 +110,6 @@ class stock_picking(osv.osv):
invoice_line_obj = self.pool.get('account.invoice.line') invoice_line_obj = self.pool.get('account.invoice.line')
purchase_line_obj = self.pool.get('purchase.order.line') purchase_line_obj = self.pool.get('purchase.order.line')
purchase_line_obj.write(cursor, user, [move_line.purchase_line_id.id], { purchase_line_obj.write(cursor, user, [move_line.purchase_line_id.id], {
'invoiced': True,
'invoice_lines': [(4, invoice_line_id)], 'invoice_lines': [(4, invoice_line_id)],
}) })
return super(stock_picking, self)._invoice_line_hook(cursor, user, move_line, invoice_line_id) return super(stock_picking, self)._invoice_line_hook(cursor, user, move_line, invoice_line_id)

View File

@ -906,6 +906,7 @@
var self = this; var self = this;
var bg = self.$target.css("background-image"); var bg = self.$target.css("background-image");
this.$el.find('li').removeClass("active"); this.$el.find('li').removeClass("active");
this.$el.find('li').removeClass("btn-primary");
var $active = this.$el.find('li[data-value]') var $active = this.$el.find('li[data-value]')
.filter(function () { .filter(function () {
var $li = $(this); var $li = $(this);
@ -918,8 +919,13 @@
this.$el.find('li[data-value].oe_custom_bg') : this.$el.find('li[data-value].oe_custom_bg') :
this.$el.find('li[data-value=""]'); this.$el.find('li[data-value=""]');
} }
$active.addClass("active");
this.$el.find('li:has(li[data-value].active)').addClass("active"); //don't set active on an OpenDialog link, else it not possible to click on it again after.
// TODO in Saas-4 - Once bootstrap is in less
// - add a class active-style to get the same display but without the active behaviour used by bootstrap in JS.
var classStr = _.string.contains($active[0].className, "oe_custom_bg") ? "btn-primary" : "active";
$active.addClass(classStr);
this.$el.find('li:has(li[data-value].active)').addClass(classStr);
} }
}); });

View File

@ -43,6 +43,7 @@
t-att-data-view-xmlid="xmlid if editable else None" t-att-data-view-xmlid="xmlid if editable else None"
t-att-data-main-object="repr(main_object) if editable else None"> t-att-data-main-object="repr(main_object) if editable else None">
<head> <head>
<script type="text/javascript" src="/web/static/js/watch.js"></script>
<t t-if="main_object and 'website_meta_title' in main_object"> <t t-if="main_object and 'website_meta_title' in main_object">
<t t-set="title" t-value="main_object.website_meta_title"/> <t t-set="title" t-value="main_object.website_meta_title"/>
</t> </t>
@ -74,6 +75,7 @@
// Bootstrap and jQuery UI conflicts // Bootstrap and jQuery UI conflicts
$.fn.bstooltip = $.fn.tooltip; $.fn.bstooltip = $.fn.tooltip;
$.fn.bsbutton = $.fn.button; $.fn.bsbutton = $.fn.button;
</script> </script>
<script type="text/javascript" src="/web/static/lib/qweb/qweb2.js"></script> <script type="text/javascript" src="/web/static/lib/qweb/qweb2.js"></script>

View File

@ -129,7 +129,7 @@ class sale_quote(http.Controller):
order_line_obj.write(request.cr, SUPERUSER_ID, [line_id], {'product_uom_qty': (quantity)}, context=request.context) order_line_obj.write(request.cr, SUPERUSER_ID, [line_id], {'product_uom_qty': (quantity)}, context=request.context)
return [str(quantity), str(order.amount_total)] return [str(quantity), str(order.amount_total)]
@http.route(["/quote/template/<model('sale.quote.template'):quote>"], type='http', auth="user", website=True) @http.route(["/quote/template/<model('sale.quote.template'):quote>"], type='http', auth="user", website=True, multilang=True)
def template_view(self, quote, **post): def template_view(self, quote, **post):
values = { 'template': quote } values = { 'template': quote }
return request.website.render('website_quote.so_template', values) return request.website.render('website_quote.so_template', values)

View File

@ -133,7 +133,12 @@ class sale_order(osv.osv):
def onchange_template_id(self, cr, uid, ids, template_id, partner=False, fiscal_position=False, context=None): def onchange_template_id(self, cr, uid, ids, template_id, partner=False, fiscal_position=False, context=None):
if not template_id: if not template_id:
return True return True
lines = []
if context is None:
context = {}
context = dict(context, lang=self.pool.get('res.partner').browse(cr, uid, partner, context).lang)
lines = [(5,)]
quote_template = self.pool.get('sale.quote.template').browse(cr, uid, template_id, context=context) quote_template = self.pool.get('sale.quote.template').browse(cr, uid, template_id, context=context)
for line in quote_template.quote_line: for line in quote_template.quote_line:
res = self.pool.get('sale.order.line').product_id_change(cr, uid, False, res = self.pool.get('sale.order.line').product_id_change(cr, uid, False,

View File

@ -411,7 +411,9 @@ class Ecommerce(http.Controller):
quantity = request.registry['website']._ecommerce_add_product_to_cart(request.cr, request.uid, quantity = request.registry['website']._ecommerce_add_product_to_cart(request.cr, request.uid,
product_id=product_id, order_line_id=order_line_id, set_number=set_number, product_id=product_id, order_line_id=order_line_id, set_number=set_number,
context=request.context) context=request.context)
return quantity order = self.get_order()
return [quantity,
order.get_number_of_products()]
@http.route(['/shop/checkout'], type='http', auth="public", website=True, multilang=True) @http.route(['/shop/checkout'], type='http', auth="public", website=True, multilang=True)
def checkout(self, **post): def checkout(self, **post):
@ -514,14 +516,7 @@ class Ecommerce(http.Controller):
if error: if error:
return request.website.render("website_sale.checkout", values) return request.website.render("website_sale.checkout", values)
company_name = checkout['company']
company_id = None
if post['company']:
company_ids = orm_partner.search(cr, SUPERUSER_ID, [("name", "ilike", company_name), ('is_company', '=', True)], context=context)
company_id = (company_ids and company_ids[0]) or orm_partner.create(cr, SUPERUSER_ID, {'name': company_name, 'is_company': True}, context)
billing_info = dict((k, v) for k,v in checkout.items() if "shipping_" not in k and k != "company") billing_info = dict((k, v) for k,v in checkout.items() if "shipping_" not in k and k != "company")
billing_info['parent_id'] = company_id
partner_id = None partner_id = None
public_id = request.registry['website'].get_public_user(cr, uid, context) public_id = request.registry['website'].get_public_user(cr, uid, context)
@ -542,7 +537,8 @@ class Ecommerce(http.Controller):
shipping_info = { shipping_info = {
'phone': post['shipping_phone'], 'phone': post['shipping_phone'],
'zip': post['shipping_zip'], 'zip': post['shipping_zip'],
'street': post['shipping_street'], 'street': checkout['company'],
'street2': post['shipping_street'],
'city': post['shipping_city'], 'city': post['shipping_city'],
'name': post['shipping_name'], 'name': post['shipping_name'],
'email': post['email'], 'email': post['email'],