diff --git a/addons/account/account_invoice.py b/addons/account/account_invoice.py index cc4dada2317..d0da6e41f5e 100644 --- a/addons/account/account_invoice.py +++ b/addons/account/account_invoice.py @@ -114,7 +114,7 @@ class account_invoice(models.Model): def _compute_residual(self): nb_inv_in_partial_rec = max_invoice_id = 0 self.residual = 0.0 - for line in self.move_id.line_id: + for line in self.sudo().move_id.line_id: if line.account_id.type in ('receivable', 'payable'): if line.currency_id == self.currency_id: self.residual += line.amount_residual_currency @@ -1397,8 +1397,7 @@ class account_invoice_line(models.Model): res = [] for line in inv.invoice_line: mres = self.move_line_get_item(line) - if not mres: - continue + mres['invl_id'] = line.id res.append(mres) tax_code_found = False taxes = line.invoice_line_tax_id.compute_all( diff --git a/addons/account_anglo_saxon/invoice.py b/addons/account_anglo_saxon/invoice.py index a4d9f48e359..0b3c573b943 100644 --- a/addons/account_anglo_saxon/invoice.py +++ b/addons/account_anglo_saxon/invoice.py @@ -124,7 +124,7 @@ class account_invoice_line(osv.osv): account_prec = decimal_precision.precision_get(cr, uid, 'Account') # calculate and write down the possible price difference between invoice price and product price for line in res: - if a == line['account_id'] and i_line.product_id.id == line['product_id']: + if line.get('invl_id', 0) == i_line.id and a == line['account_id']: uom = i_line.product_id.uos_id or i_line.product_id.uom_id valuation_price_unit = self.pool.get('product.uom')._compute_price(cr, uid, uom.id, i_line.product_id.standard_price, i_line.uos_id.id) if inv.currency_id.id != company_currency: diff --git a/addons/calendar/controllers/main.py b/addons/calendar/controllers/main.py index d0fdb47ab0b..6831e9a130d 100644 --- a/addons/calendar/controllers/main.py +++ b/addons/calendar/controllers/main.py @@ -54,7 +54,7 @@ class meeting_invitation(http.Controller): # Function used, in RPC to check every 5 minutes, if notification to do for an event or not @http.route('/calendar/notify', type='json', auth="none") def notify(self): - registry = openerp.modules.registry.RegistryManager.get(request.session.db) + registry = request.registry uid = request.session.uid context = request.session.context with registry.cursor() as cr: @@ -63,7 +63,7 @@ class meeting_invitation(http.Controller): @http.route('/calendar/notify_ack', type='json', auth="none") def notify_ack(self, type=''): - registry = openerp.modules.registry.RegistryManager.get(request.session.db) + registry = request.registry uid = request.session.uid context = request.session.context with registry.cursor() as cr: diff --git a/addons/email_template/tests/test_mail.py b/addons/email_template/tests/test_mail.py index f5a99137351..c176e00e118 100644 --- a/addons/email_template/tests/test_mail.py +++ b/addons/email_template/tests/test_mail.py @@ -237,8 +237,8 @@ class test_message_compose(TestMail): email_template.send_mail(cr, uid, email_template_id, self.group_pigs_id, force_send=True, context=context) sent_emails = self._build_email_kwargs_list email_to_lst = [ - ['b@b.b', 'c@c.c'], ['"Administrator" '], - ['"Raoul Grosbedon" '], ['"Bert Tartignole" ']] + ['b@b.b', 'c@c.c'], ['Administrator '], + ['Raoul Grosbedon '], ['Bert Tartignole ']] self.assertEqual(len(sent_emails), 4, 'email_template: send_mail: 3 valid email recipients + email_to -> should send 4 emails') for email in sent_emails: self.assertIn(email['email_to'], email_to_lst, 'email_template: send_mail: wrong email_recipients') diff --git a/addons/fleet/fleet_view.xml b/addons/fleet/fleet_view.xml index 89faafad841..9c418bacc90 100644 --- a/addons/fleet/fleet_view.xml +++ b/addons/fleet/fleet_view.xml @@ -468,7 +468,7 @@ - + @@ -676,7 +676,7 @@ - + @@ -778,7 +778,7 @@ - + diff --git a/addons/gamification/models/goal.py b/addons/gamification/models/goal.py index ce5be513aef..118991773ec 100644 --- a/addons/gamification/models/goal.py +++ b/addons/gamification/models/goal.py @@ -194,7 +194,7 @@ class gamification_goal(osv.Model): _columns = { 'definition_id': fields.many2one('gamification.goal.definition', string='Goal Definition', required=True, ondelete="cascade"), - 'user_id': fields.many2one('res.users', string='User', required=True), + 'user_id': fields.many2one('res.users', string='User', required=True, auto_join=True), 'line_id': fields.many2one('gamification.challenge.line', string='Challenge Line', ondelete="cascade"), 'challenge_id': fields.related('line_id', 'challenge_id', string="Challenge", @@ -239,7 +239,7 @@ class gamification_goal(osv.Model): 'state': 'draft', 'start_date': fields.date.today, } - _order = 'create_date desc, end_date desc, definition_id, id' + _order = 'start_date desc, end_date desc, definition_id, id' def _check_remind_delay(self, cr, uid, goal, context=None): """Verify if a goal has not been updated for some time and send a diff --git a/addons/l10n_be_coda/wizard/account_coda_import.py b/addons/l10n_be_coda/wizard/account_coda_import.py index 2670a44ec33..ad21a780611 100644 --- a/addons/l10n_be_coda/wizard/account_coda_import.py +++ b/addons/l10n_be_coda/wizard/account_coda_import.py @@ -40,7 +40,7 @@ class account_coda_import(osv.osv_memory): } _defaults = { - 'coda_fname': lambda *a: '', + 'coda_fname': 'coda.txt', } def coda_parsing(self, cr, uid, ids, context=None, batch=False, codafile=None, codafilename=None): diff --git a/addons/mail/mail_mail.py b/addons/mail/mail_mail.py index 602810f7423..cfc7a5f0099 100644 --- a/addons/mail/mail_mail.py +++ b/addons/mail/mail_mail.py @@ -21,6 +21,7 @@ import base64 import logging +from email.utils import formataddr from urlparse import urljoin from openerp import api, tools @@ -184,11 +185,10 @@ class mail_mail(osv.Model): def send_get_mail_to(self, cr, uid, mail, partner=None, context=None): """Forge the email_to with the following heuristic: - - if 'partner' and mail is a notification on a document: followers (Followers of 'Doc' ) - - elif 'partner', no notificatoin or no doc: recipient specific (Partner Name ) + - if 'partner', recipient specific (Partner Name ) - else fallback on mail.email_to splitting """ if partner: - email_to = ['"%s" <%s>' % (partner.name, partner.email)] + email_to = [formataddr((partner.name, partner.email))] else: email_to = tools.email_split(mail.email_to) return email_to diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index c7c1fad81ad..6413e1c090b 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -24,6 +24,7 @@ import logging from openerp import tools from email.header import decode_header +from email.utils import formataddr from openerp import SUPERUSER_ID, api from openerp.osv import osv, orm, fields from openerp.tools import html_email_clean @@ -170,9 +171,9 @@ class mail_message(osv.Model): def _get_default_from(self, cr, uid, context=None): this = self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context=context) if this.alias_name and this.alias_domain: - return '%s <%s@%s>' % (this.name, this.alias_name, this.alias_domain) + return formataddr((this.name, '%s@%s' % (this.alias_name, this.alias_domain))) elif this.email: - return '%s <%s>' % (this.name, this.email) + return formataddr((this.name, this.email)) raise osv.except_osv(_('Invalid Action!'), _("Unable to send email, please configure the sender's email address or alias.")) def _get_default_author(self, cr, uid, context=None): diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index 0eb4d35c22d..8f1bc05872c 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -37,6 +37,7 @@ import time import xmlrpclib import re from email.message import Message +from email.utils import formataddr from urllib import urlencode from openerp import api, tools @@ -722,12 +723,10 @@ class mail_thread(osv.AbstractModel): aliases.update(dict((res_id, '%s@%s' % (catchall_alias, alias_domain)) for res_id in left_ids)) # compute name of reply-to company_name = self.pool['res.users'].browse(cr, SUPERUSER_ID, uid, context=context).company_id.name - res.update( - dict((res_id, '"%(company_name)s%(document_name)s" <%(email)s>' % - {'company_name': company_name, - 'document_name': doc_names.get(res_id) and ' ' + re.sub(r'[^\w+.]+', '-', doc_names[res_id]) or '', - 'email': aliases[res_id] - } or False) for res_id in aliases.keys())) + for res_id in aliases.keys(): + email_name = '%s%s' % (company_name, doc_names.get(res_id) and (' ' + doc_names[res_id]) or '') + email_addr = aliases[res_id] + res[res_id] = formataddr((email_name, email_addr)) left_ids = set(ids).difference(set(aliases.keys())) if left_ids and default: res.update(dict((res_id, default) for res_id in left_ids)) diff --git a/addons/mail/tests/test_mail_features.py b/addons/mail/tests/test_mail_features.py index 84e0d4252b1..8726cf3c2a2 100644 --- a/addons/mail/tests/test_mail_features.py +++ b/addons/mail/tests/test_mail_features.py @@ -448,7 +448,7 @@ class test_mail(TestMail): 'message_post: mail.mail notifications should have been auto-deleted!') # Test: notifications emails: to a and b, c is email only, r is author - test_emailto = ['"Administrator" ', '"Bert Tartopoils" '] + test_emailto = ['Administrator ', 'Bert Tartopoils '] # test_emailto = ['"Followers of -Pigs-" ', '"Followers of -Pigs-" '] self.assertEqual(len(sent_emails), 2, 'message_post: notification emails wrong number of send emails') @@ -461,7 +461,7 @@ class test_mail(TestMail): 'message_post: notification email sent to more than one email address instead of a precise partner') self.assertIn(sent_email['email_to'][0], test_emailto, 'message_post: notification email email_to incorrect') - self.assertEqual(sent_email['reply_to'], '"YourCompany -Pigs-" ', + self.assertEqual(sent_email['reply_to'], u'"YourCompany \\"Pigs\\" !รน $%-" ', 'message_post: notification email reply_to incorrect') self.assertEqual(_subject, sent_email['subject'], 'message_post: notification email subject incorrect') @@ -518,7 +518,7 @@ class test_mail(TestMail): self.assertFalse(self.mail_mail.search(cr, uid, [('mail_message_id', '=', msg2_id)]), 'mail.mail notifications should have been auto-deleted!') # Test: emails send by server (to a, b, c, d) - test_emailto = [u'"Administrator" ', u'"Bert Tartopoils" ', u'"Carine Poilvache" ', u'"D\xe9d\xe9 Grosbedon" '] + test_emailto = [u'Administrator ', u'Bert Tartopoils ', u'Carine Poilvache ', u'D\xe9d\xe9 Grosbedon '] # test_emailto = [u'"Followers of Pigs" ', u'"Followers of Pigs" ', u'"Followers of Pigs" ', u'"Followers of Pigs" '] # self.assertEqual(len(sent_emails), 3, 'sent_email number of sent emails incorrect') for sent_email in sent_emails: diff --git a/addons/mail/tests/test_mail_message.py b/addons/mail/tests/test_mail_message.py index 7bbc9aa5a64..9883449d754 100644 --- a/addons/mail/tests/test_mail_message.py +++ b/addons/mail/tests/test_mail_message.py @@ -81,7 +81,7 @@ class TestMailMessage(TestMail): alias_domain = 'schlouby.fr' raoul_from = 'Raoul Grosbedon ' raoul_from_alias = 'Raoul Grosbedon ' - raoul_reply_alias = '"YourCompany Pigs" ' + raoul_reply_alias = 'YourCompany Pigs ' # -------------------------------------------------- # Case1: without alias_domain @@ -151,7 +151,7 @@ class TestMailMessage(TestMail): msg_id = self.mail_message.create(cr, user_raoul_id, {}) msg = self.mail_message.browse(cr, user_raoul_id, msg_id) # Test: generated reply_to - self.assertEqual(msg.reply_to, '"YourCompany" ', + self.assertEqual(msg.reply_to, 'YourCompany ', 'mail_mail: reply_to should equal the catchall email alias') # Do: create a mail_mail diff --git a/addons/payment_paypal/models/paypal.py b/addons/payment_paypal/models/paypal.py index 3f8872396f8..3021c685e90 100644 --- a/addons/payment_paypal/models/paypal.py +++ b/addons/payment_paypal/models/paypal.py @@ -42,8 +42,8 @@ class AcquirerPaypal(osv.Model): _columns = { 'paypal_email_account': fields.char('Paypal Email ID', required_if_provider='paypal'), 'paypal_seller_account': fields.char( - 'Paypal Seller ID', - help='The Seller ID is used to ensure communications coming from Paypal are valid and secured.'), + 'Paypal Merchant ID', + help='The Merchant ID is used to ensure communications coming from Paypal are valid and secured.'), 'paypal_use_ipn': fields.boolean('Use IPN', help='Paypal Instant Payment Notification'), # Server 2 server 'paypal_api_enabled': fields.boolean('Use Rest API'), diff --git a/addons/point_of_sale/static/src/xml/pos.xml b/addons/point_of_sale/static/src/xml/pos.xml index 04104510cf2..ece15535b0b 100644 --- a/addons/point_of_sale/static/src/xml/pos.xml +++ b/addons/point_of_sale/static/src/xml/pos.xml @@ -902,7 +902,7 @@

Phone:
- User:
+ User:
Shop:

diff --git a/addons/portal_sale/portal_sale.py b/addons/portal_sale/portal_sale.py index b0997f78a7c..e7078bc732e 100644 --- a/addons/portal_sale/portal_sale.py +++ b/addons/portal_sale/portal_sale.py @@ -21,6 +21,7 @@ from openerp import SUPERUSER_ID from openerp.osv import osv, fields +from openerp import SUPERUSER_ID class sale_order(osv.Model): @@ -36,7 +37,7 @@ class sale_order(osv.Model): def _portal_payment_block(self, cr, uid, ids, fieldname, arg, context=None): result = dict.fromkeys(ids, False) payment_acquirer = self.pool['payment.acquirer'] - for this in self.browse(cr, uid, ids, context=context): + for this in self.browse(cr, SUPERUSER_ID, ids, context=context): if this.state not in ('draft', 'cancel') and not this.invoiced: result[this.id] = payment_acquirer.render_payment_block( cr, uid, this.name, this.amount_total, this.pricelist_id.currency_id.id, diff --git a/addons/portal_sale/security/ir.model.access.csv b/addons/portal_sale/security/ir.model.access.csv index 191b2bd82a0..2afc50fe5bb 100644 --- a/addons/portal_sale/security/ir.model.access.csv +++ b/addons/portal_sale/security/ir.model.access.csv @@ -5,16 +5,8 @@ access_account_invoice,account.invoice,account.model_account_invoice,base.group_ access_account_invoice_tax,account.invoice.tax,account.model_account_invoice_tax,base.group_portal,1,0,0,0 access_account_invoice_line,account.invoice.line,account.model_account_invoice_line,base.group_portal,1,0,0,0 access_account_journal,account.journal,account.model_account_journal,base.group_portal,1,0,0,0 -access_account_voucher,account.voucher,account_voucher.model_account_voucher,base.group_portal,1,0,0,0 -access_account_voucher_line,account.voucher.line,account_voucher.model_account_voucher_line,base.group_portal,1,0,0,0 -access_account_move,account.move,account.model_account_move,base.group_portal,1,0,0,0 -access_account_move_line,account.move.line,account.model_account_move_line,base.group_portal,1,0,0,0 -access_account_move_reconcile,account.move.reconcile,account.model_account_move_reconcile,base.group_portal,1,0,0,0 -access_account_fiscalyear,account.sequence.fiscalyear,account.model_account_sequence_fiscalyear,base.group_portal,1,0,0,0 +access_sale_shop,sale.shop,sale.model_sale_shop,base.group_portal,1,0,0,0 access_product_list,product.pricelist,product.model_product_pricelist,base.group_portal,1,0,0,0 access_res_partner,res.partner,base.model_res_partner,base.group_portal,1,0,0,0 access_account_tax,account.tax,account.model_account_tax,base.group_portal,1,0,0,0 -access_account_fiscalyear,account.fiscalyear,account.model_account_fiscalyear,base.group_portal,1,0,0,0 access_res_partner_category,res.partner.category,base.model_res_partner_category,base.group_portal,1,0,0,0 -access_account_period,account.period,account.model_account_period,base.group_portal,1,0,0,0 -access_account_account,account.account,account.model_account_account,base.group_portal,1,0,0,0 diff --git a/addons/portal_sale/security/portal_security.xml b/addons/portal_sale/security/portal_security.xml index e1328fa7cf2..8bf02ba0fd5 100644 --- a/addons/portal_sale/security/portal_security.xml +++ b/addons/portal_sale/security/portal_security.xml @@ -18,7 +18,7 @@ their documents through the portal.
Portal Personal Quotations/Sales Orders - [('message_follower_ids','in',[user.partner_id.id])] + [('message_follower_ids','child_of',[user.commercial_partner_id.id])] @@ -26,17 +26,32 @@ their documents through the portal. + + Portal Sales Orders Line + + [('order_id.message_follower_ids','child_of',[user.commercial_partner_id.id])] + + + + Portal Personal Account Invoices - [('message_follower_ids','in',[user.partner_id.id])] + [('message_follower_ids','child_of',[user.commercial_partner_id.id])] + + + + + Portal Invoice Lines + + [('invoice_id.message_follower_ids','child_of',[user.commercial_partner_id.id])] Portal Personal Contacts - [('message_follower_ids','in',[user.partner_id.id])] + [('message_follower_ids','in',[user.commercial_partner_id.id])] diff --git a/addons/procurement/procurement.py b/addons/procurement/procurement.py index d9053cbd60b..12d40a39be1 100644 --- a/addons/procurement/procurement.py +++ b/addons/procurement/procurement.py @@ -20,6 +20,7 @@ ############################################################################## import time +from psycopg2 import OperationalError from openerp import SUPERUSER_ID from openerp.osv import fields, osv @@ -193,31 +194,49 @@ class procurement_order(osv.osv): def reset_to_confirmed(self, cr, uid, ids, context=None): return self.write(cr, uid, ids, {'state': 'confirmed'}, context=context) - def run(self, cr, uid, ids, context=None): + def run(self, cr, uid, ids, autocommit=False, context=None): for procurement_id in ids: #we intentionnaly do the browse under the for loop to avoid caching all ids which would be resource greedy #and useless as we'll make a refresh later that will invalidate all the cache (and thus the next iteration #will fetch all the ids again) procurement = self.browse(cr, uid, procurement_id, context=context) if procurement.state not in ("running", "done"): - if self._assign(cr, uid, procurement, context=context): - procurement.refresh() - res = self._run(cr, uid, procurement, context=context or {}) - if res: - self.write(cr, uid, [procurement.id], {'state': 'running'}, context=context) + try: + if self._assign(cr, uid, procurement, context=context): + procurement.refresh() + res = self._run(cr, uid, procurement, context=context or {}) + if res: + self.write(cr, uid, [procurement.id], {'state': 'running'}, context=context) + else: + self.write(cr, uid, [procurement.id], {'state': 'exception'}, context=context) else: + self.message_post(cr, uid, [procurement.id], body=_('No rule matching this procurement'), context=context) self.write(cr, uid, [procurement.id], {'state': 'exception'}, context=context) - else: - self.message_post(cr, uid, [procurement.id], body=_('No rule matching this procurement'), context=context) - self.write(cr, uid, [procurement.id], {'state': 'exception'}, context=context) + if autocommit: + cr.commit() + except OperationalError: + if autocommit: + cr.rollback() + continue + else: + raise return True - def check(self, cr, uid, ids, context=None): + def check(self, cr, uid, ids, autocommit=False, context=None): done_ids = [] for procurement in self.browse(cr, uid, ids, context=context): - result = self._check(cr, uid, procurement, context=context) - if result: - done_ids.append(procurement.id) + try: + result = self._check(cr, uid, procurement, context=context) + if result: + done_ids.append(procurement.id) + if autocommit: + cr.commit() + except OperationalError: + if autocommit: + cr.rollback() + continue + else: + raise if done_ids: self.write(cr, uid, done_ids, {'state': 'done'}, context=context) return done_ids @@ -291,11 +310,14 @@ class procurement_order(osv.osv): dom = [('state', '=', 'confirmed')] if company_id: dom += [('company_id', '=', company_id)] + prev_ids = [] while True: ids = self.search(cr, SUPERUSER_ID, dom, context=context) - if not ids: + if not ids or prev_ids == ids: break - self.run(cr, SUPERUSER_ID, ids, context=context) + else: + prev_ids = ids + self.run(cr, SUPERUSER_ID, ids, autocommit=use_new_cursor, context=context) if use_new_cursor: cr.commit() @@ -304,12 +326,14 @@ class procurement_order(osv.osv): dom = [('state', '=', 'running')] if company_id: dom += [('company_id', '=', company_id)] + prev_ids = [] while True: ids = self.search(cr, SUPERUSER_ID, dom, offset=offset, context=context) - if not ids: + if not ids or prev_ids == ids: break - done = self.check(cr, SUPERUSER_ID, ids, context=context) - offset += len(ids) - len(done) + else: + prev_ids = ids + self.check(cr, SUPERUSER_ID, ids, autocommit=use_new_cursor, context=context) if use_new_cursor: cr.commit() diff --git a/addons/stock/procurement.py b/addons/stock/procurement.py index 2024b016ef3..aa097cc664a 100644 --- a/addons/stock/procurement.py +++ b/addons/stock/procurement.py @@ -26,6 +26,7 @@ from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FO from openerp import SUPERUSER_ID from dateutil.relativedelta import relativedelta from datetime import datetime +from psycopg2 import OperationalError import openerp class procurement_group(osv.osv): @@ -204,8 +205,8 @@ class procurement_order(osv.osv): return True return super(procurement_order, self)._run(cr, uid, procurement, context=context) - def run(self, cr, uid, ids, context=None): - res = super(procurement_order, self).run(cr, uid, ids, context=context) + def run(self, cr, uid, ids, autocommit=False, context=None): + res = super(procurement_order, self).run(cr, uid, ids, autocommit=autocommit, context=context) #after all the procurements are run, check if some created a draft stock move that needs to be confirmed #(we do that in batch because it fasts the picking assignation and the picking state computation) move_to_confirm_ids = [] @@ -335,36 +336,51 @@ class procurement_order(osv.osv): orderpoint_obj = self.pool.get('stock.warehouse.orderpoint') procurement_obj = self.pool.get('procurement.order') - offset = 0 - ids = [1] dom = company_id and [('company_id', '=', company_id)] or [] - while ids: - ids = orderpoint_obj.search(cr, uid, dom, offset=offset, limit=100) + orderpoint_ids = orderpoint_obj.search(cr, uid, dom) + prev_ids = [] + while orderpoint_ids: + ids = orderpoint_ids[:100] + del orderpoint_ids[:100] for op in orderpoint_obj.browse(cr, uid, ids, context=context): - prods = self._product_virtual_get(cr, uid, op) - if prods is None: - continue - if prods < op.product_min_qty: - qty = max(op.product_min_qty, op.product_max_qty) - prods - - reste = qty % op.qty_multiple - if reste > 0: - qty += op.qty_multiple - reste - - if qty <= 0: + try: + prods = self._product_virtual_get(cr, uid, op) + if prods is None: continue + if prods < op.product_min_qty: + qty = max(op.product_min_qty, op.product_max_qty) - prods - qty -= orderpoint_obj.subtract_procurements(cr, uid, op, context=context) + reste = qty % op.qty_multiple + if reste > 0: + qty += op.qty_multiple - reste - if qty > 0: - proc_id = procurement_obj.create(cr, uid, - self._prepare_orderpoint_procurement(cr, uid, op, qty, context=context), - context=context) - self.check(cr, uid, [proc_id]) - self.run(cr, uid, [proc_id]) - offset += len(ids) + if qty <= 0: + continue + + qty -= orderpoint_obj.subtract_procurements(cr, uid, op, context=context) + + if qty > 0: + proc_id = procurement_obj.create(cr, uid, + self._prepare_orderpoint_procurement(cr, uid, op, qty, context=context), + context=context) + self.check(cr, uid, [proc_id]) + self.run(cr, uid, [proc_id]) + if use_new_cursor: + cr.commit() + except OperationalError: + if use_new_cursor: + orderpoint_ids.append(op.id) + cr.rollback() + continue + else: + raise if use_new_cursor: cr.commit() + if prev_ids == ids: + break + else: + prev_ids = ids + if use_new_cursor: cr.commit() cr.close() diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index a4930c51353..11d22d2b373 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -1418,16 +1418,18 @@ class ExportFormat(object): raise NotImplementedError() def base(self, data, token): + params = simplejson.loads(data) model, fields, ids, domain, import_compat = \ operator.itemgetter('model', 'fields', 'ids', 'domain', 'import_compat')( - simplejson.loads(data)) + params) Model = request.session.model(model) - ids = ids or Model.search(domain, 0, False, False, request.context) + context = dict(req.context or {}, **params.get('context', {})) + ids = ids or Model.search(domain, 0, False, False, context) field_names = map(operator.itemgetter('name'), fields) - import_data = Model.export_data(ids, field_names, self.raw_data, context=request.context).get('datas',[]) + import_data = Model.export_data(ids, field_names, self.raw_data, context=context).get('datas',[]) if import_compat: columns_headers = field_names diff --git a/addons/web/static/src/js/data_export.js b/addons/web/static/src/js/data_export.js index 2f7ff81d089..192a9d7c9fc 100644 --- a/addons/web/static/src/js/data_export.js +++ b/addons/web/static/src/js/data_export.js @@ -406,6 +406,7 @@ instance.web.DataExport = instance.web.Dialog.extend({ fields: exported_fields, ids: this.ids_to_export, domain: this.domain, + context: this.dataset.context, import_compat: !!this.$el.find("#import_compat").val(), })}, complete: instance.web.unblockUI, diff --git a/addons/web/static/src/js/search.js b/addons/web/static/src/js/search.js index 7ed70f7bc68..efe4a0f11c1 100644 --- a/addons/web/static/src/js/search.js +++ b/addons/web/static/src/js/search.js @@ -487,7 +487,6 @@ instance.web.SearchView = instance.web.Widget.extend(/** @lends instance.web.Sea */ setup_global_completion: function () { var self = this; - this.autocomplete = new instance.web.search.AutoComplete(this, { source: this.proxy('complete_global_search'), select: this.proxy('select_completion'), diff --git a/addons/web/static/src/js/view_list.js b/addons/web/static/src/js/view_list.js index 9a192e4db90..173fae49e31 100644 --- a/addons/web/static/src/js/view_list.js +++ b/addons/web/static/src/js/view_list.js @@ -522,7 +522,7 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi self.dataset.index = 0; } } else if (self.dataset.index >= self.records.length) { - self.dataset.index = 0; + self.dataset.index = self.records.length ? 0 : null; } self.compute_aggregates(); diff --git a/addons/web_graph/static/src/js/pivot_table.js b/addons/web_graph/static/src/js/pivot_table.js index 086e7205990..b842b00f00d 100644 --- a/addons/web_graph/static/src/js/pivot_table.js +++ b/addons/web_graph/static/src/js/pivot_table.js @@ -423,14 +423,15 @@ openerp.web_graph.PivotTable = openerp.web.Class.extend({ attrs.value = [attrs.value]; } attrs.value = _.range(grouped_on.length).map(function (i) { + var grp = grouped_on[i], + field = self.fields[grp]; if (attrs.value[i] === false) { return _t('Undefined'); } else if (attrs.value[i] instanceof Array) { return attrs.value[i][1]; - }else if (grouped_on && self.fields[grouped_on].type === 'selection'){ - var selection = self.fields[grouped_on].selection; - var value_lookup = _.where(selection, {0:attrs.value[i]}); - return value_lookup ? value_lookup[0][1] : _t('Undefined'); + } else if (field && field.type === 'selection') { + var selected = _.where(field.selection, {0: attrs.value[i]})[0]; + return selected ? selected[1] : attrs.value[i]; } return attrs.value[i]; }); diff --git a/addons/web_kanban/static/src/js/kanban.js b/addons/web_kanban/static/src/js/kanban.js index 4c859c4badc..df897e51f06 100644 --- a/addons/web_kanban/static/src/js/kanban.js +++ b/addons/web_kanban/static/src/js/kanban.js @@ -310,6 +310,8 @@ instance.web_kanban.KanbanView = instance.web.View.extend({ var kgroup = new instance.web_kanban.KanbanGroup(self, records, null, self.dataset); if (!_.isEmpty(self.dataset.ids) && (self.dataset.index === null || self.dataset.index >= self.dataset.ids.length)) { self.dataset.index = 0; + } else if (_.isEmpty(self.dataset.ids)){ + self.dataset.index = null; } self.do_add_groups([kgroup]).done(function() { if (_.isEmpty(records)) { diff --git a/addons/website_crm_partner_assign/views/website_crm_partner_assign.xml b/addons/website_crm_partner_assign/views/website_crm_partner_assign.xml index 3f0e52879e8..2285ee7933f 100644 --- a/addons/website_crm_partner_assign/views/website_crm_partner_assign.xml +++ b/addons/website_crm_partner_assign/views/website_crm_partner_assign.xml @@ -131,8 +131,8 @@

World Map

diff --git a/addons/website_customer/controllers/main.py b/addons/website_customer/controllers/main.py index d4b996a0ab6..02a42b0b621 100644 --- a/addons/website_customer/controllers/main.py +++ b/addons/website_customer/controllers/main.py @@ -59,8 +59,11 @@ class WebsiteCustomer(http.Controller): partner_count = partner_obj.search_count(cr, openerp.SUPERUSER_ID, domain, context=request.context) # pager + url = '/customers/' + if country_id: + url += 'country/%s' % country_id pager = request.website.pager( - url="/customers", total=partner_count, page=page, step=self._references_per_page, + url=url, total=partner_count, page=page, step=self._references_per_page, scope=7, url_args=post ) diff --git a/addons/website_customer/views/website_customer.xml b/addons/website_customer/views/website_customer.xml index db64eb916f4..5d0a8f6d7ba 100644 --- a/addons/website_customer/views/website_customer.xml +++ b/addons/website_customer/views/website_customer.xml @@ -84,8 +84,8 @@

World Map

diff --git a/addons/website_event/controllers/main.py b/addons/website_event/controllers/main.py index a25542898ef..10cc24182b9 100644 --- a/addons/website_event/controllers/main.py +++ b/addons/website_event/controllers/main.py @@ -90,9 +90,12 @@ class website_event(http.Controller): if searches["type"] != 'all': current_type = type_obj.browse(cr, uid, int(searches['type']), context=context) domain_search["type"] = [("type", "=", int(searches["type"]))] - if searches["country"] != 'all': + + if searches["country"] != 'all' and searches["country"] != 'online': current_country = country_obj.browse(cr, uid, int(searches['country']), context=context) - domain_search["country"] = [("country_id", "=", int(searches["country"]))] + domain_search["country"] = ['|', ("country_id", "=", int(searches["country"])), ("country_id", "=", False)] + elif searches["country"] == 'online': + domain_search["country"] = [("country_id", "=", False)] def dom_without(without): domain = [('state', "in", ['draft','confirm','done'])] diff --git a/addons/website_event/views/website_event.xml b/addons/website_event/views/website_event.xml index 92aadbe6957..5b3688823ff 100644 --- a/addons/website_event/views/website_event.xml +++ b/addons/website_event/views/website_event.xml @@ -57,6 +57,7 @@

+ Online not published

@@ -179,7 +180,13 @@
diff --git a/openerp/addons/base/ir/ir_cron.py b/openerp/addons/base/ir/ir_cron.py index b94707cef59..98d492c1cb1 100644 --- a/openerp/addons/base/ir/ir_cron.py +++ b/openerp/addons/base/ir/ir_cron.py @@ -160,8 +160,8 @@ class ir_cron(osv.osv): """ try: with api.Environment.manage(): - now = fields.datetime.context_timestamp(job_cr, SUPERUSER_ID, datetime.now()) - nextcall = fields.datetime.context_timestamp(job_cr, SUPERUSER_ID, datetime.strptime(job['nextcall'], DEFAULT_SERVER_DATETIME_FORMAT)) + now = fields.datetime.context_timestamp(job_cr, job['user_id'], datetime.now()) + nextcall = fields.datetime.context_timestamp(job_cr, job['user_id'], datetime.strptime(job['nextcall'], DEFAULT_SERVER_DATETIME_FORMAT)) numbercall = job['numbercall'] ok = False diff --git a/openerp/addons/base/res/res_partner_view.xml b/openerp/addons/base/res/res_partner_view.xml index 29814491c9e..5a84dc927cc 100644 --- a/openerp/addons/base/res/res_partner_view.xml +++ b/openerp/addons/base/res/res_partner_view.xml @@ -31,7 +31,6 @@ - @@ -183,8 +182,7 @@ - - + diff --git a/openerp/models.py b/openerp/models.py index bbcee1f3890..ae366aa647e 100644 --- a/openerp/models.py +++ b/openerp/models.py @@ -3168,6 +3168,11 @@ class BaseModel(object): env = self.env cr, user, context = env.args + # FIXME: The query construction needs to be rewritten using the internal Query + # object, as in search(), to avoid ambiguous column references when + # reading/sorting on a table that is auto_joined to another table with + # common columns (e.g. the magical columns) + # Construct a clause for the security rules. # 'tables' holds the list of tables necessary for the SELECT, including # the ir.rule clauses, and contains at least self._table. diff --git a/openerp/osv/fields.py b/openerp/osv/fields.py index 7a0c3623b26..2126fffab60 100644 --- a/openerp/osv/fields.py +++ b/openerp/osv/fields.py @@ -466,17 +466,16 @@ class datetime(_column): registry = openerp.modules.registry.RegistryManager.get(cr.dbname) user = registry['res.users'].browse(cr, SUPERUSER_ID, uid) tz_name = user.tz + utc_timestamp = pytz.utc.localize(timestamp, is_dst=False) # UTC = no DST if tz_name: try: - utc = pytz.utc context_tz = pytz.timezone(tz_name) - utc_timestamp = utc.localize(timestamp, is_dst=False) # UTC = no DST return utc_timestamp.astimezone(context_tz) except Exception: _logger.debug("failed to compute context/client-specific timestamp, " "using the UTC value", exc_info=True) - return timestamp + return utc_timestamp class binary(_column): _type = 'binary'