diff --git a/addons/account/test/account_fiscalyear_close.yml b/addons/account/test/account_fiscalyear_close.yml index b80cfd0e6e9..cc683ca8d46 100644 --- a/addons/account/test/account_fiscalyear_close.yml +++ b/addons/account/test/account_fiscalyear_close.yml @@ -4,31 +4,27 @@ !record {model: account.fiscalyear, id: account_fiscalyear_fiscalyear0}: code: !eval "'FY%s'% (datetime.now().year+1)" company_id: base.main_company - date_start: !eval "'%s-01-01' %(datetime.now().year+1)" - date_stop: !eval "'%s-12-31' %(datetime.now().year+1)" - name: !eval "'Fiscal Year %s' %(datetime.now().year+1)" + date_start: !eval "'%s-01-01' %(datetime.now().year-1)" + date_stop: !eval "'%s-12-31' %(datetime.now().year-1)" + name: !eval "'Fiscal Year %s' %(datetime.now().year-1)" - - I create a period for the opening entries for the new fiscalyear + I generate periods for the new fiscalyear - - !record {model: account.period, id: account_period_jan11}: - company_id: base.main_company - date_start: !eval "'%s-01-01'% (datetime.now().year+1)" - date_stop: !eval "'%s-01-01'% (datetime.now().year+1)" - fiscalyear_id: account_fiscalyear_fiscalyear0 - name: !eval "'OP %s' %(datetime.now().year+1)" - special: 1 + !python {model: account.fiscalyear}: | + self.create_period(cr, uid, [ref("account_fiscalyear_fiscalyear0")]) - - I create a new account invoice a the partner in current fiscalyear + I create a new account invoice in the created fiscalyear - !record {model: account.invoice, id: account_invoice_current1}: partner_id: base.res_partner_2 + date_invoice: !eval "'%s-01-02' %(datetime.now().year-1)" invoice_line: - partner_id: base.res_partner_2 quantity: 1.0 price_unit: 15.00 name: Bying stuff - - I validate it the invoice + I validate the invoice - !workflow {model: account.invoice, action: invoice_open, ref: account.account_invoice_current1} - @@ -44,13 +40,13 @@ company_id: base.main_company centralisation: 1 - - I called the Generate Fiscalyear Opening Entries wizard + I call the Generate Fiscalyear Opening Entries wizard - !record {model: account.fiscalyear.close, id: account_fiscalyear_close_0}: - fy2_id: account_fiscalyear_fiscalyear0 - fy_id: account.data_fiscalyear + fy2_id: account.data_fiscalyear + fy_id: account_fiscalyear_fiscalyear0 journal_id: account.close_journal - period_id: account_period_jan11 + period_id: account.period_1 report_name: End of Fiscal Year Entry - I clicked on create Button @@ -63,7 +59,7 @@ I close the previous fiscalyear - !record {model: account.fiscalyear.close.state, id: account_fiscalyear_close_state_0}: - fy_id: data_fiscalyear + fy_id: account_fiscalyear_fiscalyear0 - I clicked on Close States Button to close fiscalyear - @@ -74,10 +70,10 @@ - I check that the fiscalyear state is now "Done" - - !assert {model: account.fiscalyear, id: data_fiscalyear, string: Fiscal Year is in Done state}: + !assert {model: account.fiscalyear, id: account_fiscalyear_fiscalyear0, string: Fiscal Year is in Done state}: - state == 'done' - I check that the past accounts are taken into account in partner credit - - !assert {model: res.partner, id: base.res_partner_2}: - - credit == 15.0, "Total Receivable does not takes unreconciled previous moves" + !assert {model: res.partner, id: base.res_partner_2, string: Total Receivable does not takes unreconciled moves of previous years}: + - credit == 15.0 diff --git a/addons/board/controllers.py b/addons/board/controllers.py index 3bdebe1ef26..93634627352 100644 --- a/addons/board/controllers.py +++ b/addons/board/controllers.py @@ -1,24 +1,22 @@ # -*- coding: utf-8 -*- from xml.etree import ElementTree -import openerp from openerp.addons.web.controllers.main import load_actions_from_ir_values +from openerp.addons.web.http import Controller, route, request -class Board(openerp.addons.web.http.Controller): - _cp_path = '/board' - - @openerp.addons.web.http.jsonrequest - def add_to_dashboard(self, req, menu_id, action_id, context_to_save, domain, view_mode, name=''): +class Board(Controller): + @route('/board/add_to_dashboard', type='json', auth='user') + def add_to_dashboard(self, menu_id, action_id, context_to_save, domain, view_mode, name=''): # FIXME move this method to board.board model - dashboard_action = load_actions_from_ir_values( - req, 'action', 'tree_but_open', [('ir.ui.menu', menu_id)], False) + dashboard_action = load_actions_from_ir_values('action', 'tree_but_open', + [('ir.ui.menu', menu_id)], False) if dashboard_action: action = dashboard_action[0][2] if action['res_model'] == 'board.board' and action['views'][0][1] == 'form': # Maybe should check the content instead of model board.board ? view_id = action['views'][0][0] - board = req.session.model(action['res_model']).fields_view_get(view_id, 'form') + board = request.session.model(action['res_model']).fields_view_get(view_id, 'form') if board and 'arch' in board: xml = ElementTree.fromstring(board['arch']) column = xml.find('./board/column') @@ -32,10 +30,10 @@ class Board(openerp.addons.web.http.Controller): }) column.insert(0, new_action) arch = ElementTree.tostring(xml, 'utf-8') - return req.session.model('ir.ui.view.custom').create({ - 'user_id': req.session._uid, + return request.session.model('ir.ui.view.custom').create({ + 'user_id': request.session.uid, 'ref_id': view_id, 'arch': arch - }, req.context) + }, request.context) return False diff --git a/addons/hr_holidays/hr_holidays_workflow.xml b/addons/hr_holidays/hr_holidays_workflow.xml index b563dbf68d4..c539ff6de41 100644 --- a/addons/hr_holidays/hr_holidays_workflow.xml +++ b/addons/hr_holidays/hr_holidays_workflow.xml @@ -55,6 +55,7 @@ refuse + function holidays_refuse() diff --git a/addons/im/static/src/js/im.js b/addons/im/static/src/js/im.js index 6fbf452f974..f4b74adebf6 100644 --- a/addons/im/static/src/js/im.js +++ b/addons/im/static/src/js/im.js @@ -62,16 +62,12 @@ this.user_search_dm = new instance.web.DropMisordered(); }, start: function() { + var self = this; this.$el.css("right", -this.$el.outerWidth()); $(window).scroll(_.bind(this.calc_box, this)); $(window).resize(_.bind(this.calc_box, this)); this.calc_box(); - this.on("change:current_search", this, this.search_changed); - this.search_changed(); - - var self = this; - return this.c_manager.start_polling().then(function() { self.c_manager.on("new_conversation", self, function(conv) { conv.$el.droppable({ @@ -80,6 +76,7 @@ } }); }); + self.search_changed(); }); }, calc_box: function() { @@ -174,4 +171,4 @@ openerp.webclient.to_kitten(); }; -})(); \ No newline at end of file +})(); diff --git a/addons/l10n_fr/fr_fiscal_templates.xml b/addons/l10n_fr/fr_fiscal_templates.xml index b11f8d4f0dd..bf49d15e08c 100644 --- a/addons/l10n_fr/fr_fiscal_templates.xml +++ b/addons/l10n_fr/fr_fiscal_templates.xml @@ -2,6 +2,12 @@ + + + + diff --git a/addons/mail/mail_mail.py b/addons/mail/mail_mail.py index 91799b0ac63..8e99655dddb 100644 --- a/addons/mail/mail_mail.py +++ b/addons/mail/mail_mail.py @@ -157,9 +157,9 @@ class mail_mail(osv.Model): 'action': 'mail.action_mail_redirect', } if mail.notification: - fragment.update({ - 'message_id': mail.mail_message_id.id, - }) + fragment['message_id'] = mail.mail_message_id.id + elif mail.model and mail.res_id: + fragment.update(model=mail.model, res_id=mail.res_id) url = urljoin(base_url, "?%s#%s" % (urlencode(query), urlencode(fragment))) return _("""Access your messages and documents in OpenERP""") % url else: diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index b902f733207..9692b94f159 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -566,29 +566,37 @@ class mail_thread(osv.AbstractModel): self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid, context=context) act_model, act_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, *self._get_inbox_action_xml_id(cr, uid, context=context)) action = self.pool.get(act_model).read(cr, uid, act_id, []) + params = context.get('params') + msg_id = model = res_id = None - # if msg_id specified: try to redirect to the document or fallback on the Inbox - msg_id = context.get('params', {}).get('message_id') - if not msg_id: + if params: + msg_id = params.get('message_id') + model = params.get('model') + res_id = params.get('res_id') + if not msg_id and not (model and res_id): return action - msg = self.pool.get('mail.message').browse(cr, uid, msg_id, context=context) - if msg.model and msg.res_id: - action.update({ - 'context': { - 'search_default_model': msg.model, - 'search_default_res_id': msg.res_id, - } - }) - if self.pool.get(msg.model).check_access_rights(cr, uid, 'read', raise_exception=False): + if msg_id and not (model and res_id): + msg = self.pool.get('mail.message').browse(cr, uid, msg_id, context=context) + model, res_id = msg.model, msg.res_id + + # if model + res_id found: try to redirect to the document or fallback on the Inbox + if model and res_id: + model_obj = self.pool.get(model) + if model_obj.check_access_rights(cr, uid, 'read', raise_exception=False): try: - model_obj = self.pool.get(msg.model) - model_obj.check_access_rule(cr, uid, [msg.res_id], 'read', context=context) + model_obj.check_access_rule(cr, uid, [res_id], 'read', context=context) if not hasattr(model_obj, '_get_formview_action'): - action = self.pool.get('mail.thread')._get_formview_action(cr, uid, msg.res_id, model=msg.model, context=context) + action = self.pool.get('mail.thread')._get_formview_action(cr, uid, res_id, model=model, context=context) else: - action = model_obj._get_formview_action(cr, uid, msg.res_id, context=context) + action = model_obj._get_formview_action(cr, uid, res_id, context=context) except (osv.except_osv, orm.except_orm): pass + action.update({ + 'context': { + 'search_default_model': model, + 'search_default_res_id': res_id, + } + }) return action #------------------------------------------------------ diff --git a/addons/mail/tests/test_mail_features.py b/addons/mail/tests/test_mail_features.py index 0688bf02606..62c76db5a40 100644 --- a/addons/mail/tests/test_mail_features.py +++ b/addons/mail/tests/test_mail_features.py @@ -231,6 +231,8 @@ class test_mail(TestMail): def test_11_notification_url(self): """ Tests designed to test the URL added in notification emails. """ cr, uid, group_pigs = self.cr, self.uid, self.group_pigs + # Test URL formatting + base_url = self.registry('ir.config_parameter').get_param(cr, uid, 'web.base.url') # Partner data partner_raoul = self.res_partner.browse(cr, uid, self.partner_raoul_id) @@ -243,19 +245,59 @@ class test_mail(TestMail): # Test: link for nobody -> None url = mail_mail._get_partner_access_link(self.mail_mail, cr, uid, mail) self.assertEqual(url, None, - 'notification email: mails not send to a specific partner should not have any URL') + 'notification email: mails not send to a specific partner should not have any URL') # Test: link for partner -> None url = mail_mail._get_partner_access_link(self.mail_mail, cr, uid, mail, partner=partner_bert) self.assertEqual(url, None, - 'notification email: mails send to a not-user partner should not have any URL') + 'notification email: mails send to a not-user partner should not have any URL') # Test: link for user -> signin url = mail_mail._get_partner_access_link(self.mail_mail, cr, uid, mail, partner=partner_raoul) + self.assertIn(base_url, url, + 'notification email: link should contain web.base.url') + self.assertIn('db=%s' % cr.dbname, url, + 'notification email: link should contain database name') self.assertIn('action=mail.action_mail_redirect', url, - 'notification email: link should contain the redirect action') + 'notification email: link should contain the redirect action') self.assertIn('login=%s' % partner_raoul.user_ids[0].login, url, - 'notification email: link should contain the user login') + 'notification email: link should contain the user login') + + # Test: link for user -> with model and res_id + mail_mail_id = self.mail_mail.create(cr, uid, {'model': 'mail.group', 'res_id': group_pigs.id}) + mail = self.mail_mail.browse(cr, uid, mail_mail_id) + url = mail_mail._get_partner_access_link(self.mail_mail, cr, uid, mail, partner=partner_raoul) + self.assertIn(base_url, url, + 'notification email: link should contain web.base.url') + self.assertIn('db=%s' % cr.dbname, url, + 'notification email: link should contain database name') + self.assertIn('action=mail.action_mail_redirect', url, + 'notification email: link should contain the redirect action') + self.assertIn('login=%s' % partner_raoul.user_ids[0].login, url, + 'notification email: link should contain the user login') + self.assertIn('model=mail.group', url, + 'notification email: link should contain the model when having not notification email on a record') + self.assertIn('res_id=%s' % group_pigs.id, url, + 'notification email: link should contain the res_id when having not notification email on a record') + + # Test: link for user -> with model and res_id + mail_mail_id = self.mail_mail.create(cr, uid, {'notification': True, 'model': 'mail.group', 'res_id': group_pigs.id}) + mail = self.mail_mail.browse(cr, uid, mail_mail_id) + url = mail_mail._get_partner_access_link(self.mail_mail, cr, uid, mail, partner=partner_raoul) + self.assertIn(base_url, url, + 'notification email: link should contain web.base.url') + self.assertIn('db=%s' % cr.dbname, url, + 'notification email: link should contain database name') + self.assertIn('action=mail.action_mail_redirect', url, + 'notification email: link should contain the redirect action') + self.assertIn('login=%s' % partner_raoul.user_ids[0].login, url, + 'notification email: link should contain the user login') + self.assertIn('message_id=%s' % mail.mail_message_id.id, url, + 'notification email: link based on message should contain the mail_message id') + self.assertNotIn('model', url, + 'notification email: link based on message should not contain model') + self.assertNotIn('res_id', url, + 'notification email: link based on message should not contain res_id') @mute_logger('openerp.addons.mail.mail_thread', 'openerp.osv.orm') def test_12_inbox_redirection(self): @@ -267,24 +309,54 @@ class test_mail(TestMail): # No specific parameters -> should redirect to Inbox action = mail_thread.message_redirect_action(self.mail_thread, cr, self.user_raoul_id, {'params': {}}) - self.assertEqual(action.get('type'), 'ir.actions.client', - 'URL redirection: action without parameters should redirect to client action Inbox') - self.assertEqual(action.get('id'), act_id, - 'URL redirection: action without parameters should redirect to client action Inbox') + self.assertEqual( + action.get('type'), 'ir.actions.client', + 'URL redirection: action without parameters should redirect to client action Inbox' + ) + self.assertEqual( + action.get('id'), act_id, + 'URL redirection: action without parameters should redirect to client action Inbox' + ) - # Bert has read access to Pigs -> should redirect to form view of Pigs + # Raoul has read access to Pigs -> should redirect to form view of Pigs action = mail_thread.message_redirect_action(self.mail_thread, cr, self.user_raoul_id, {'params': {'message_id': msg_id}}) - self.assertEqual(action.get('type'), 'ir.actions.act_window', - 'URL redirection: action with message_id for read-accredited user should redirect to Pigs') - self.assertEqual(action.get('res_id'), group_pigs.id, - 'URL redirection: action with message_id for read-accredited user should redirect to Pigs') + self.assertEqual( + action.get('type'), 'ir.actions.act_window', + 'URL redirection: action with message_id for read-accredited user should redirect to Pigs' + ) + self.assertEqual( + action.get('res_id'), group_pigs.id, + 'URL redirection: action with message_id for read-accredited user should redirect to Pigs' + ) + action = mail_thread.message_redirect_action(self.mail_thread, cr, self.user_raoul_id, {'params': {'model': 'mail.group', 'res_id': group_pigs.id}}) + self.assertEqual( + action.get('type'), 'ir.actions.act_window', + 'URL redirection: action with message_id for read-accredited user should redirect to Pigs' + ) + self.assertEqual( + action.get('res_id'), group_pigs.id, + 'URL redirection: action with message_id for read-accredited user should redirect to Pigs' + ) # Bert has no read access to Pigs -> should redirect to Inbox action = mail_thread.message_redirect_action(self.mail_thread, cr, self.user_bert_id, {'params': {'message_id': msg_id}}) - self.assertEqual(action.get('type'), 'ir.actions.client', - 'URL redirection: action without parameters should redirect to client action Inbox') - self.assertEqual(action.get('id'), act_id, - 'URL redirection: action without parameters should redirect to client action Inbox') + self.assertEqual( + action.get('type'), 'ir.actions.client', + 'URL redirection: action without parameters should redirect to client action Inbox' + ) + self.assertEqual( + action.get('id'), act_id, + 'URL redirection: action without parameters should redirect to client action Inbox' + ) + action = mail_thread.message_redirect_action(self.mail_thread, cr, self.user_bert_id, {'params': {'model': 'mail.group', 'res_id': group_pigs.id}}) + self.assertEqual( + action.get('type'), 'ir.actions.client', + 'URL redirection: action without parameters should redirect to client action Inbox' + ) + self.assertEqual( + action.get('id'), act_id, + 'URL redirection: action without parameters should redirect to client action Inbox' + ) def test_20_message_post(self): """ Tests designed for message_post. """ diff --git a/addons/procurement/procurement.py b/addons/procurement/procurement.py index 2ce046fe454..032952aa511 100644 --- a/addons/procurement/procurement.py +++ b/addons/procurement/procurement.py @@ -139,7 +139,7 @@ class procurement_order(osv.osv): if not proc.note or '_first_pass_done_' not in proc.note or proc.state not in ('confirmed', 'exception'): super(procurement_order, self).message_track(cr, uid, [proc.id], tracked_fields, initial_values, context=context) if proc.state == 'exception': - cr.execute("""UPDATE procurement_order set note = CONCAT(note, %s) WHERE id = %s""", ('_first_pass_done_',proc.id)) + cr.execute("""UPDATE procurement_order set note = TRIM(both E'\n' FROM COALESCE(note, '') || %s) WHERE id = %s""", ('\n\n_first_pass_done_',proc.id)) return True