From 0004301b23c79a019a12c19785a6d4052f916213 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 26 Mar 2013 17:50:15 +0100 Subject: [PATCH 001/388] [IMP] mail: now have a subject in composer. bzr revid: tde@openerp.com-20130326165015-czid1h8xot4mdhyi --- addons/mail/wizard/mail_compose_message.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py index 7e5b437623f..0d036e9402c 100644 --- a/addons/mail/wizard/mail_compose_message.py +++ b/addons/mail/wizard/mail_compose_message.py @@ -169,7 +169,12 @@ class mail_compose_message(osv.TransientModel): record_name = doc_name_get[0][1] else: record_name = False - return {'model': model, 'res_id': res_id, 'record_name': record_name} + return { + 'model': model, + 'res_id': res_id, + 'record_name': record_name, + 'subject': 'Re: %s' % record_name, + } def get_message_data(self, cr, uid, message_id, context=None): """ Returns a defaults-like dict with initial values for the composition @@ -187,7 +192,7 @@ class mail_compose_message(osv.TransientModel): # create subject re_prefix = _('Re:') - reply_subject = tools.ustr(message_data.subject or '') + reply_subject = tools.ustr(message_data.subject or tools.ustr(message_data.record_name or '') or '') if not (reply_subject.startswith('Re:') or reply_subject.startswith(re_prefix)) and message_data.subject: reply_subject = "%s %s" % (re_prefix, reply_subject) # get partner_ids from original message From 35b0b7f4b1656207560a470f776b9945dc176b30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 26 Mar 2013 17:59:40 +0100 Subject: [PATCH 002/388] [FIX] mail_message: todo are now unread bzr revid: tde@openerp.com-20130326165940-isag9vxn22vinlgy --- addons/mail/mail_message.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index 2f56e620543..156ceac214e 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -269,15 +269,15 @@ class mail_message(osv.Model): # all message have notifications: already set them as (un)starred if len(notif_ids) == len(msg_ids) or not create_missing: - notification_obj.write(cr, uid, notif_ids, {'starred': starred}, context=context) + notification_obj.write(cr, uid, notif_ids, {'starred': starred, 'read': False}, context=context) return starred # some messages do not have notifications: find which one, create notification, update starred status notified_msg_ids = [notification.message_id.id for notification in notification_obj.browse(cr, uid, notif_ids, context=context)] to_create_msg_ids = list(set(msg_ids) - set(notified_msg_ids)) for msg_id in to_create_msg_ids: - notification_obj.create(cr, uid, {'partner_id': user_pid, 'starred': starred, 'message_id': msg_id}, context=context) - notification_obj.write(cr, uid, notif_ids, {'starred': starred}, context=context) + notification_obj.create(cr, uid, {'partner_id': user_pid, 'starred': starred, 'message_id': msg_id, 'read': False}, context=context) + notification_obj.write(cr, uid, notif_ids, {'starred': starred, 'read': False}, context=context) return starred #------------------------------------------------------ From f307221f04ed89e4b0de5268c70601818da577e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Wed, 27 Mar 2013 12:17:50 +0100 Subject: [PATCH 003/388] [IMP] Cleaned the fix. bzr revid: tde@openerp.com-20130327111750-auc217sdkg4gieci --- addons/mail/wizard/mail_compose_message.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py index 0d036e9402c..e475baf82ae 100644 --- a/addons/mail/wizard/mail_compose_message.py +++ b/addons/mail/wizard/mail_compose_message.py @@ -165,16 +165,17 @@ class mail_compose_message(osv.TransientModel): :param int res_id: id of the document record this mail is related to """ doc_name_get = self.pool.get(model).name_get(cr, uid, [res_id], context=context) + record_name = False if doc_name_get: record_name = doc_name_get[0][1] - else: - record_name = False - return { + values = { 'model': model, 'res_id': res_id, 'record_name': record_name, - 'subject': 'Re: %s' % record_name, } + if record_name: + values['subject'] = 'Re: %s' % record_name + return values def get_message_data(self, cr, uid, message_id, context=None): """ Returns a defaults-like dict with initial values for the composition @@ -192,6 +193,8 @@ class mail_compose_message(osv.TransientModel): # create subject re_prefix = _('Re:') + if message_data.subject: + reply_subject = tools.ustr(message_data.subject or tools.ustr(message_data.record_name or '') or '') if not (reply_subject.startswith('Re:') or reply_subject.startswith(re_prefix)) and message_data.subject: reply_subject = "%s %s" % (re_prefix, reply_subject) From 92597407f877a060068805486fd236ac1e0b23af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Wed, 27 Mar 2013 12:19:10 +0100 Subject: [PATCH 004/388] [CLEAN] Cleaned the cleaning of the fix. bzr revid: tde@openerp.com-20130327111910-l7a9s5rk05b8jbme --- addons/mail/wizard/mail_compose_message.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/addons/mail/wizard/mail_compose_message.py b/addons/mail/wizard/mail_compose_message.py index e475baf82ae..da6307ba019 100644 --- a/addons/mail/wizard/mail_compose_message.py +++ b/addons/mail/wizard/mail_compose_message.py @@ -193,9 +193,7 @@ class mail_compose_message(osv.TransientModel): # create subject re_prefix = _('Re:') - if message_data.subject: - - reply_subject = tools.ustr(message_data.subject or tools.ustr(message_data.record_name or '') or '') + reply_subject = tools.ustr(message_data.subject or message_data.record_name or '') if not (reply_subject.startswith('Re:') or reply_subject.startswith(re_prefix)) and message_data.subject: reply_subject = "%s %s" % (re_prefix, reply_subject) # get partner_ids from original message From 9fa765194feef8caef812a5dfd95317c3f00d4ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Wed, 27 Mar 2013 12:20:49 +0100 Subject: [PATCH 005/388] [CLEAN] Cleaned the fix. bzr revid: tde@openerp.com-20130327112049-jmwcpwc50fsa6bf7 --- addons/mail/mail_message.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index 156ceac214e..a8fba3022e1 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -265,19 +265,25 @@ class mail_message(osv.Model): domain = [('partner_id', '=', user_pid), ('message_id', 'in', msg_ids)] if not create_missing: domain += [('starred', '=', not starred)] + values = { + 'starred': starred + } + if starred: + values['read'] = False + notif_ids = notification_obj.search(cr, uid, domain, context=context) # all message have notifications: already set them as (un)starred if len(notif_ids) == len(msg_ids) or not create_missing: - notification_obj.write(cr, uid, notif_ids, {'starred': starred, 'read': False}, context=context) + notification_obj.write(cr, uid, notif_ids, values, context=context) return starred # some messages do not have notifications: find which one, create notification, update starred status notified_msg_ids = [notification.message_id.id for notification in notification_obj.browse(cr, uid, notif_ids, context=context)] to_create_msg_ids = list(set(msg_ids) - set(notified_msg_ids)) for msg_id in to_create_msg_ids: - notification_obj.create(cr, uid, {'partner_id': user_pid, 'starred': starred, 'message_id': msg_id, 'read': False}, context=context) - notification_obj.write(cr, uid, notif_ids, {'starred': starred, 'read': False}, context=context) + notification_obj.create(cr, uid, dict(values, partner_id=user_pid, message_id=msg_id), context=context) + notification_obj.write(cr, uid, notif_ids, values, context=context) return starred #------------------------------------------------------ From 555b2cbd2617465ef474906a3b20e7d602cf1863 Mon Sep 17 00:00:00 2001 From: "Nimesh (Open ERP)" Date: Fri, 21 Dec 2012 15:50:56 +0530 Subject: [PATCH 006/388] [FIX] duplicate a holiday request. bzr revid: nco@tinyerp.com-20121221102056-ojgcvllqtnxeuk8e --- addons/hr_holidays/hr_holidays.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/addons/hr_holidays/hr_holidays.py b/addons/hr_holidays/hr_holidays.py index c7d7867911d..be8330c40a0 100644 --- a/addons/hr_holidays/hr_holidays.py +++ b/addons/hr_holidays/hr_holidays.py @@ -182,6 +182,16 @@ class hr_holidays(osv.osv): ('date_check2', "CHECK ( (type='add') OR (date_from <= date_to))", "The start date must be anterior to the end date."), ('date_check', "CHECK ( number_of_days_temp >= 0 )", "The number of days must be greater than 0."), ] + + def copy(self, cr, uid, id, default=None, context=None): + if default is None: + default = {} + if context is None: + context = {} + default = default.copy() + default['date_from'] = False + default['date_to'] = False + return super(hr_holidays, self).copy(cr, uid, id, default, context=context) def _create_resource_leave(self, cr, uid, leaves, context=None): '''This method will create entry in resource calendar leave object at the time of holidays validated ''' From bc40ea4ee95e894509eba03963f5cec6b703ece4 Mon Sep 17 00:00:00 2001 From: Arnaud Pineux Date: Wed, 9 Jan 2013 12:08:20 +0100 Subject: [PATCH 007/388] [FIX] The lunch 'history' or 'preferences' didn't show the last order. It now shows the 5 last orders of every product category bzr revid: api@openerp.com-20130109110820-fq4iae12p5sg4lam --- addons/lunch/lunch.py | 85 ++++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 41 deletions(-) diff --git a/addons/lunch/lunch.py b/addons/lunch/lunch.py index f61ecc8eb7d..3883a98d553 100644 --- a/addons/lunch/lunch.py +++ b/addons/lunch/lunch.py @@ -168,7 +168,7 @@ class lunch_order(osv.Model): line_ref = self.pool.get("lunch.order.line") if view_type == 'form': doc = etree.XML(res['arch']) - pref_ids = line_ref.search(cr, uid, [('user_id', '=', uid)], order='create_date desc', context=context) + pref_ids = line_ref.search(cr, uid, [('user_id', '=', uid)], order='id desc', context=context) xml_start = etree.Element("div") #If there are no preference (it's the first time for the user) if len(pref_ids)==0: @@ -222,55 +222,58 @@ class lunch_order(osv.Model): xml_pref_1.append(xml_pref_2) i = 0 value = value.values() + sorted_values = {} for val in value: - for pref in val.values(): - #We only show 5 preferences per category (or it will be too long) - if i==5: break - i+=1 - xml_pref_3 = etree.Element("div") - xml_pref_3.set('class','oe_lunch_vignette') - xml_pref_1.append(xml_pref_3) + for elmt in val.values(): + sorted_values[elmt.id]=elmt + for key, pref in sorted(sorted_values.iteritems(), key=lambda (k,v): (k,v), reverse=True): + #We only show 5 preferences per category (or it will be too long) + if i==5: break + i+=1 + xml_pref_3 = etree.Element("div") + xml_pref_3.set('class','oe_lunch_vignette') + xml_pref_1.append(xml_pref_3) - xml_pref_4 = etree.Element("span") - xml_pref_4.set('class','oe_lunch_button') - xml_pref_3.append(xml_pref_4) + xml_pref_4 = etree.Element("span") + xml_pref_4.set('class','oe_lunch_button') + xml_pref_3.append(xml_pref_4) - xml_pref_5 = etree.Element("button") - xml_pref_5.set('name',"add_preference_"+str(pref.id)) - xml_pref_5.set('class','oe_link oe_i oe_button_plus') - xml_pref_5.set('type','object') - xml_pref_5.set('string','+') - xml_pref_4.append(xml_pref_5) + xml_pref_5 = etree.Element("button") + xml_pref_5.set('name',"add_preference_"+str(pref.id)) + xml_pref_5.set('class','oe_link oe_i oe_button_plus') + xml_pref_5.set('type','object') + xml_pref_5.set('string','+') + xml_pref_4.append(xml_pref_5) - xml_pref_6 = etree.Element("button") - xml_pref_6.set('name',"add_preference_"+str(pref.id)) - xml_pref_6.set('class','oe_link oe_button_add') - xml_pref_6.set('type','object') - xml_pref_6.set('string',_("Add")) - xml_pref_4.append(xml_pref_6) + xml_pref_6 = etree.Element("button") + xml_pref_6.set('name',"add_preference_"+str(pref.id)) + xml_pref_6.set('class','oe_link oe_button_add') + xml_pref_6.set('type','object') + xml_pref_6.set('string',_("Add")) + xml_pref_4.append(xml_pref_6) - xml_pref_7 = etree.Element("div") - xml_pref_7.set('class','oe_group_text_button') - xml_pref_3.append(xml_pref_7) + xml_pref_7 = etree.Element("div") + xml_pref_7.set('class','oe_group_text_button') + xml_pref_3.append(xml_pref_7) - xml_pref_8 = etree.Element("div") - xml_pref_8.set('class','oe_lunch_text') - xml_pref_8.text = escape(pref.product_id.name)+str(" ") - xml_pref_7.append(xml_pref_8) + xml_pref_8 = etree.Element("div") + xml_pref_8.set('class','oe_lunch_text') + xml_pref_8.text = escape(pref.product_id.name)+str(" ") + xml_pref_7.append(xml_pref_8) - price = pref.product_id.price or 0.0 - cur = currency.name or '' - xml_pref_9 = etree.Element("span") - xml_pref_9.set('class','oe_tag') - xml_pref_9.text = str(price)+str(" ")+cur - xml_pref_8.append(xml_pref_9) + price = pref.product_id.price or 0.0 + cur = currency.name or '' + xml_pref_9 = etree.Element("span") + xml_pref_9.set('class','oe_tag') + xml_pref_9.text = str(price)+str(" ")+cur + xml_pref_8.append(xml_pref_9) - xml_pref_10 = etree.Element("div") - xml_pref_10.set('class','oe_grey') - xml_pref_10.text = escape(pref.note or '') - xml_pref_3.append(xml_pref_10) + xml_pref_10 = etree.Element("div") + xml_pref_10.set('class','oe_grey') + xml_pref_10.text = escape(pref.note or '') + xml_pref_3.append(xml_pref_10) - xml_start.append(xml_pref_1) + xml_start.append(xml_pref_1) first_node = doc.xpath("//div[@name='preferences']") if first_node and len(first_node)>0: From 61be1b4637fc04c1d95c807eff44e2c49d8d669e Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Mon, 21 Jan 2013 16:33:58 +0100 Subject: [PATCH 008/388] [FIX] kanban: display no_result message when there are no records in the kanban view with columns bzr revid: chm@openerp.com-20130121153358-tzp976npk1jp9yip --- addons/web_kanban/static/src/js/kanban.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/addons/web_kanban/static/src/js/kanban.js b/addons/web_kanban/static/src/js/kanban.js index 1d9ced0ca6d..6d361bc4311 100644 --- a/addons/web_kanban/static/src/js/kanban.js +++ b/addons/web_kanban/static/src/js/kanban.js @@ -223,7 +223,6 @@ instance.web_kanban.KanbanView = instance.web.View.extend({ }, do_search: function(domain, context, group_by) { var self = this; - this.$el.find('.oe_view_nocontent').remove(); this.search_domain = domain; this.search_context = context; this.search_group_by = group_by; @@ -235,6 +234,7 @@ instance.web_kanban.KanbanView = instance.web.View.extend({ self.$el.toggleClass('oe_kanban_grouped_by_m2o', self.grouped_by_m2o); var grouping = new instance.web.Model(self.dataset.model, context, domain).query().group_by(self.group_by); $.when(grouping).done(function(groups) { + self.$el.find('.oe_view_nocontent').remove(); if (groups) { self.do_process_groups(groups); } else { @@ -245,6 +245,7 @@ instance.web_kanban.KanbanView = instance.web.View.extend({ }, do_process_groups: function(groups) { var self = this; + this.$el.find('table:first').show(); this.$el.removeClass('oe_kanban_ungrouped').addClass('oe_kanban_grouped'); this.add_group_mutex.exec(function() { self.do_clear_groups(); @@ -253,13 +254,15 @@ instance.web_kanban.KanbanView = instance.web.View.extend({ self.no_result(); return false; } + self.nb_records = 0; var remaining = groups.length - 1, groups_array = []; return $.when.apply(null, _.map(groups, function (group, index) { var dataset = new instance.web.DataSetSearch(self, self.dataset.model, new instance.web.CompoundContext(self.dataset.get_context(), group.model.context()), group.model.domain()); return dataset.read_slice(self.fields_keys.concat(['__last_update']), { 'limit': self.limit }) - .then(function(records) { + .then(function (records) { + self.nb_records += records.length; self.dataset.ids.push.apply(self.dataset.ids, dataset.ids); groups_array[index] = new instance.web_kanban.KanbanGroup(self, records, group, dataset); if (!remaining--) { @@ -267,11 +270,16 @@ instance.web_kanban.KanbanView = instance.web.View.extend({ return self.do_add_groups(groups_array); } }); - })); + })).then(function () { + if(!self.nb_records) { + self.no_result(); + } + }); }); }, do_process_dataset: function() { var self = this; + this.$el.find('table:first').show(); this.$el.removeClass('oe_kanban_grouped').addClass('oe_kanban_ungrouped'); this.add_group_mutex.exec(function() { var def = $.Deferred(); @@ -447,7 +455,7 @@ instance.web_kanban.KanbanView = instance.web.View.extend({ || !this.options.action.help) { return; } - this.$el.find('.oe_view_nocontent').remove(); + this.$el.find('table:first').hide(); this.$el.prepend( $('
').html(this.options.action.help) ); From 9fc0f7229b5043b2972a4b879c794e7f8385c54e Mon Sep 17 00:00:00 2001 From: Vishmita Date: Tue, 22 Jan 2013 13:05:26 +0530 Subject: [PATCH 009/388] [Fix]From calendar view create customer or supplier invoice when select partner it generate error bzr revid: vja@tinyerp.com-20130122073526-fzmis5bnoutuy5f0 --- addons/web_calendar/static/src/js/calendar.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/addons/web_calendar/static/src/js/calendar.js b/addons/web_calendar/static/src/js/calendar.js index 9cac4db09d5..49e08412d2f 100644 --- a/addons/web_calendar/static/src/js/calendar.js +++ b/addons/web_calendar/static/src/js/calendar.js @@ -341,7 +341,11 @@ instance.web_calendar.CalendarView = instance.web.View.extend({ var data = { name: event_obj.text }; - data[this.date_start] = instance.web.datetime_to_str(event_obj.start_date); + if (this.fields[this.date_start].type == 'date') { + data[this.date_start] = instance.web.date_to_str(event_obj.start_date) + }else { + data[this.date_start] = instance.web.datetime_to_str(event_obj.start_date) + } if (this.date_stop) { data[this.date_stop] = instance.web.datetime_to_str(event_obj.end_date); } From d345c7b07a0d08bac01d3d5936c1f1d1516f0f46 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Tue, 22 Jan 2013 11:30:37 +0100 Subject: [PATCH 010/388] [IMP] kanban: no_message on hover columns with opacity effect bzr revid: chm@openerp.com-20130122103037-iyciy625vnhjak0x --- addons/web_kanban/static/src/css/kanban.css | 27 +++++++++++++++++ addons/web_kanban/static/src/css/kanban.sass | 29 +++++++++++++++++-- addons/web_kanban/static/src/js/kanban.js | 16 ++++++---- .../web_kanban/static/src/xml/web_kanban.xml | 8 +++++ 4 files changed, 72 insertions(+), 8 deletions(-) diff --git a/addons/web_kanban/static/src/css/kanban.css b/addons/web_kanban/static/src/css/kanban.css index 3083a9e30a5..5492d4923fe 100644 --- a/addons/web_kanban/static/src/css/kanban.css +++ b/addons/web_kanban/static/src/css/kanban.css @@ -172,9 +172,11 @@ } .openerp .oe_kanban_view .oe_kanban_add { top: -8px; + z-index: 2; } .openerp .oe_kanban_view .oe_kanban_header .oe_dropdown_toggle { top: -2px; + z-index: 2; } .openerp .oe_kanban_view .oe_kanban_card, .openerp .oe_kanban_view .oe_dropdown_toggle { cursor: pointer; @@ -190,6 +192,9 @@ width: 185px; padding: 10px; } +.openerp .oe_kanban_view .oe_kanban_quick_create { + z-index: 2; +} .openerp .oe_kanban_view .oe_kanban_quick_create input { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; @@ -607,6 +612,28 @@ background: white; } +.openerp .oe_kanban_grouped .oe_view_nocontent { + position: relative; + z-index: 1; + max-width: none; + height: 100%; +} +.openerp .oe_kanban_grouped .oe_view_nocontent .oe_view_nocontent_content { + margin-left: 90px; + margin-top: 5px; + max-width: 700px; +} +.openerp .oe_kanban_grouped .oe_view_nocontent .oe_view_nocontent_bg { + background: #eee; + opacity: 0.7; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + z-index: -1; +} + .openerp .oe_popup_form .oe_kanban_buttons .oe_highlight { color: #404040; background: none; diff --git a/addons/web_kanban/static/src/css/kanban.sass b/addons/web_kanban/static/src/css/kanban.sass index 988dee01051..4c4d8fa5dff 100644 --- a/addons/web_kanban/static/src/css/kanban.sass +++ b/addons/web_kanban/static/src/css/kanban.sass @@ -51,9 +51,28 @@ //background: url(data:image/pngbase64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAYAAACp8Z5+AAAAKElEQVQIHWP8DwTv379nAAFBQUEGhnfv3oHEwADEZgJLIRGMIClkLQCr3x2Htp/lLwAAAABJRU5ErkJggg==) background: white height: inherit - &.oe_kanban_grouped .oe_kanban_dummy_cell - background: url(/web/static/src/img/form_sheetbg.png) - width: 100% + &.oe_kanban_grouped + .oe_kanban_dummy_cell + background: url(/web/static/src/img/form_sheetbg.png) + width: 100% + .oe_view_nocontent + position: relative + z-index: 1 + max-width: none + height: 100% + .oe_view_nocontent_content + margin-left: 90px + margin-top: 5px + max-width: 700px + .oe_view_nocontent_bg + background: #eee + opacity: 0.7 + position: absolute + top: 0 + bottom: 0 + left: 0 + right: 0 + z-index: -1 .ui-sortable-placeholder border: 1px solid rgba(0,0,0,0.1) visibility: visible !important @@ -187,8 +206,10 @@ position: relative .oe_kanban_add top: -8px + z-index: 2 .oe_kanban_header .oe_dropdown_toggle top: -2px + z-index: 2 .oe_kanban_card, .oe_dropdown_toggle cursor: pointer display: inline-block @@ -200,6 +221,8 @@ .oe_kanban_no_group .oe_kanban_quick_create width: 185px padding: 10px + .oe_kanban_quick_create + z-index: 2 .oe_kanban_quick_create input @include box-sizing(border-box) outline: none diff --git a/addons/web_kanban/static/src/js/kanban.js b/addons/web_kanban/static/src/js/kanban.js index 6d361bc4311..758c4246d87 100644 --- a/addons/web_kanban/static/src/js/kanban.js +++ b/addons/web_kanban/static/src/js/kanban.js @@ -234,7 +234,7 @@ instance.web_kanban.KanbanView = instance.web.View.extend({ self.$el.toggleClass('oe_kanban_grouped_by_m2o', self.grouped_by_m2o); var grouping = new instance.web.Model(self.dataset.model, context, domain).query().group_by(self.group_by); $.when(grouping).done(function(groups) { - self.$el.find('.oe_view_nocontent').remove(); + self.remove_no_result(); if (groups) { self.do_process_groups(groups); } else { @@ -318,6 +318,9 @@ instance.web_kanban.KanbanView = instance.web.View.extend({ var $last_td = self.$el.find('.oe_kanban_groups_headers td:last'); var groups_started = _.map(this.groups, function(group) { if (!group.is_started) { + group.on("add_record", self, function () { + self.remove_no_result(); + }); return group.insertBefore($last_td); } }); @@ -455,15 +458,17 @@ instance.web_kanban.KanbanView = instance.web.View.extend({ || !this.options.action.help) { return; } - this.$el.find('table:first').hide(); - this.$el.prepend( - $('
').html(this.options.action.help) - ); + this.$el.find('table:first').css("position", "absolute"); + $(QWeb.render('KanbanView.nocontent', { content : this.options.action.help})).insertAfter(this.$('table:first')); var create_nocontent = this.$buttons; this.$el.find('.oe_view_nocontent').click(function() { create_nocontent.openerpBounce(); }); }, + remove_no_result: function() { + this.$el.find('table:first').css("position", false); + this.$el.find('.oe_view_nocontent').remove(); + }, /* * postprocessing of fields type many2many @@ -726,6 +731,7 @@ instance.web_kanban.KanbanGroup = instance.web.Widget.extend({ */ quick_created: function (record) { var id = record, self = this; + self.trigger("add_record"); this.dataset.read_ids([id], this.view.fields_keys) .done(function (records) { self.view.dataset.ids.push(id); diff --git a/addons/web_kanban/static/src/xml/web_kanban.xml b/addons/web_kanban/static/src/xml/web_kanban.xml index 67ee563c14d..7b3cfb10447 100644 --- a/addons/web_kanban/static/src/xml/web_kanban.xml +++ b/addons/web_kanban/static/src/xml/web_kanban.xml @@ -93,4 +93,12 @@
+ +
+
+
+ +
+
+
From b02c1eb263dadb4d4a4bf20025d0e4e448c73204 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 23 Jan 2013 11:31:02 +0100 Subject: [PATCH 011/388] [IMP] view: no message alias bzr revid: chm@openerp.com-20130123103102-81kafjq0l61uq8qx --- addons/web/static/src/js/view_list.js | 1 + addons/web/static/src/js/views.js | 29 ++++++++++++++++++++++- addons/web_kanban/static/src/js/kanban.js | 5 ++-- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/addons/web/static/src/js/view_list.js b/addons/web/static/src/js/view_list.js index fbbfabcacca..c0231487640 100644 --- a/addons/web/static/src/js/view_list.js +++ b/addons/web/static/src/js/view_list.js @@ -850,6 +850,7 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi this.$el.find('.oe_view_nocontent').click(function() { create_nocontent.openerpBounce(); }); + this.insert_alias(this.$el.find('.oe_view_nocontent')); } }); instance.web.ListView.List = instance.web.Class.extend( /** @lends instance.web.ListView.List# */{ diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js index 9fd49367171..8f5eed37521 100644 --- a/addons/web/static/src/js/views.js +++ b/addons/web/static/src/js/views.js @@ -1394,7 +1394,34 @@ instance.web.View = instance.web.Widget.extend({ is_action_enabled: function(action) { var attrs = this.fields_view.arch.attrs; return (action in attrs) ? JSON.parse(attrs[action]) : true; - } + }, + /** + * insert alias into the dom + */ + insert_alias: function ($dom) { + var self = this; + var context = this.options.action.context || {}; + if (context && context.alias) { + new instance.web.Model('mail.alias').call("get_alias", [], {'alias': context.alias}).then(function (alias_ids) { + if (alias_ids.length) { + var $alias = $('

'); + var global = false; + var inc = 0; + _.each(alias_ids, function (alias_id) { + if (alias_id.email.match(/@.+/)) { + if (inc && global != alias_id.global) { + $alias.append('
' + _t("or")); + global = alias_id.global; + } + $alias.append((inc? '
': '') + '' + alias_id.email + ''); + inc++; + } + }) + $dom.append($alias); + } + }); + } + }, }); /** diff --git a/addons/web_kanban/static/src/js/kanban.js b/addons/web_kanban/static/src/js/kanban.js index 758c4246d87..b1ed4f16973 100644 --- a/addons/web_kanban/static/src/js/kanban.js +++ b/addons/web_kanban/static/src/js/kanban.js @@ -453,6 +453,7 @@ instance.web_kanban.KanbanView = instance.web.View.extend({ } }, no_result: function() { + var self = this; if (this.groups.group_by || !this.options.action || !this.options.action.help) { @@ -460,10 +461,10 @@ instance.web_kanban.KanbanView = instance.web.View.extend({ } this.$el.find('table:first').css("position", "absolute"); $(QWeb.render('KanbanView.nocontent', { content : this.options.action.help})).insertAfter(this.$('table:first')); - var create_nocontent = this.$buttons; this.$el.find('.oe_view_nocontent').click(function() { - create_nocontent.openerpBounce(); + self.$buttons.openerpBounce(); }); + this.insert_alias(this.$el.find('.oe_view_nocontent_content')); }, remove_no_result: function() { this.$el.find('table:first').css("position", false); From d4fe5a47f3eda19d77b9c96318c3f7363f09504f Mon Sep 17 00:00:00 2001 From: Rifakat Date: Wed, 23 Jan 2013 16:09:11 +0530 Subject: [PATCH 012/388] [FIX] account: put a restriction to re-open a period which belongs to > the closed fiscal year, it must not be possible to re-open a period and post journal items when its fiscal year is closed bzr revid: rha@tinyerp.com-20130123103911-trxfkv0kemltvdv5 --- addons/account/account.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/addons/account/account.py b/addons/account/account.py index 8c7f058acc6..dd9e869ae4a 100644 --- a/addons/account/account.py +++ b/addons/account/account.py @@ -1026,6 +1026,9 @@ class account_period(osv.osv): def action_draft(self, cr, uid, ids, *args): mode = 'draft' + for period in self.browse(cr, uid, ids): + if period.fiscalyear_id.state == 'done': + raise osv.except_osv(_('Warning !'), _('You can not re-open a period which belongs to closed fiscal year')) cr.execute('update account_journal_period set state=%s where period_id in %s', (mode, tuple(ids),)) cr.execute('update account_period set state=%s where id in %s', (mode, tuple(ids),)) return True From 65555ae9720dfa2b9873dbd542abaf9a2b9bdab2 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 23 Jan 2013 12:16:28 +0100 Subject: [PATCH 013/388] [IMP] view: alias bzr revid: chm@openerp.com-20130123111628-m74jj7xj1c9t5zf9 --- addons/web/static/src/js/views.js | 8 +++++--- addons/web/static/src/xml/base.xml | 5 +++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js index 8f5eed37521..006d3e50c2d 100644 --- a/addons/web/static/src/js/views.js +++ b/addons/web/static/src/js/views.js @@ -1404,7 +1404,7 @@ instance.web.View = instance.web.Widget.extend({ if (context && context.alias) { new instance.web.Model('mail.alias').call("get_alias", [], {'alias': context.alias}).then(function (alias_ids) { if (alias_ids.length) { - var $alias = $('

'); + var $alias = $(QWeb.render('View.nocontent_alias')); var global = false; var inc = 0; _.each(alias_ids, function (alias_id) { @@ -1413,11 +1413,13 @@ instance.web.View = instance.web.Widget.extend({ $alias.append('
' + _t("or")); global = alias_id.global; } - $alias.append((inc? '
': '') + '' + alias_id.email + ''); + $alias.append('
' + alias_id.email + ''); inc++; } }) - $dom.append($alias); + if(inc) { + $dom.append($alias); + } } }); } diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml index 6d707bb4627..8d8adaf1a3a 100644 --- a/addons/web/static/src/xml/base.xml +++ b/addons/web/static/src/xml/base.xml @@ -1873,4 +1873,9 @@ + +

+ You can also create the document by sending an email to : +

+
From aec0de7a96599154eaf4742a33f33d48316c7a76 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 23 Jan 2013 12:38:34 +0100 Subject: [PATCH 014/388] [IMP] view: alias bzr revid: chm@openerp.com-20130123113834-xlujbrmxgrr8e8ft --- addons/web/static/src/js/views.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js index 006d3e50c2d..625f50ca2f8 100644 --- a/addons/web/static/src/js/views.js +++ b/addons/web/static/src/js/views.js @@ -1401,8 +1401,11 @@ instance.web.View = instance.web.Widget.extend({ insert_alias: function ($dom) { var self = this; var context = this.options.action.context || {}; - if (context && context.alias) { - new instance.web.Model('mail.alias').call("get_alias", [], {'alias': context.alias}).then(function (alias_ids) { + if (context && context.help_alias) { + new instance.web.Model('mail.alias').call("get_alias", [], { + 'model': this.options.action.res_model, + 'alias_defaults': context.help_alias + }).then(function (alias_ids) { if (alias_ids.length) { var $alias = $(QWeb.render('View.nocontent_alias')); var global = false; From cffa820e30441306cdb254633cf2db2e9f11354d Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 23 Jan 2013 12:39:02 +0100 Subject: [PATCH 015/388] [IMP] mail_alias: get_alias method return a list of dict (id, email, global) bzr revid: chm@openerp.com-20130123113902-suek7ycw1jm6h3sa --- addons/mail/mail_alias.py | 45 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/addons/mail/mail_alias.py b/addons/mail/mail_alias.py index d9c49d833ab..8e76efef859 100644 --- a/addons/mail/mail_alias.py +++ b/addons/mail/mail_alias.py @@ -22,6 +22,7 @@ import logging import re import unicodedata +import ast from openerp.osv import fields, osv from openerp.tools import ustr @@ -196,3 +197,47 @@ class mail_alias(osv.Model): model_id = self.pool.get('ir.model').search(cr, uid, [('model', '=', model_name)], context=context)[0] vals['alias_model_id'] = model_id return self.create(cr, uid, vals, context=context) + + def get_alias(self, cr, uid, model, alias_defaults={}, context=None): + """Return the mail alias + """ + model_id = self.pool.get('ir.model').search(cr, uid, [('model', '=', model)], context=context)[0] + + result = [] + # get the value with required attribute + domain = [('alias_model_id', '=', model_id)] + if alias_defaults: + for item in alias_defaults.items(): + domain += ['|', '|', '|', + ('alias_defaults', 'like', ("%%'%s': %s%%" % (item[0], item[1]))), + ('alias_defaults', 'like', ("%%'%s':%s%%" % (item[0], item[1]))), + ('alias_defaults', 'like', ("%%'%s': '%s'%%" % (item[0], item[1]))), + ('alias_defaults', 'like', ("%%'%s':'%s'%%" % (item[0], item[1])))] + else: + domain += [('alias_defaults', 'like', "{}")] + + ids = self.search(cr, uid, domain, context=context) + if ids: + for record in self.browse(cr, uid, ids, context=context): + test = True + if alias_defaults: + for item in ast.literal_eval(record.alias_defaults).items(): + if alias_defaults.get(item[0]) == None or alias_defaults.get(item[0]) != item[1]: + test = False + continue + if test: + result.append( {'id': record.id, 'email': "%s@%s" % (record.alias_name, record.alias_domain), 'global': False}) + + # get the default value + if alias_defaults: + domain = [('alias_model_id', '=', model_id)] + for item in alias_defaults.items(): + domain += [ + ('alias_defaults', 'not like', ("%%'%s'%%" % (item[0])))] + + ids = self.search(cr, uid, domain, context=context) + if ids: + for record in self.browse(cr, uid, ids, context=context): + result.append( {'id': record.id, 'email': "%s@%s" % (record.alias_name, record.alias_domain), 'global': True}) + + return result From dd185ca108804cc2c0ba515858289166021f6845 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 23 Jan 2013 12:43:36 +0100 Subject: [PATCH 016/388] [IMP] mail_alias: add the context help_alias to project, crm lead, crm issue, res partner lead bzr revid: chm@openerp.com-20130123114336-mgnafjnfk7yckd6q --- addons/crm/crm_lead_menu.xml | 13 +++++++++++-- addons/crm/res_partner_view.xml | 7 +++++-- addons/project/project_view.xml | 7 ++++++- addons/project_issue/project_issue_menu.xml | 3 +++ addons/project_issue/project_issue_view.xml | 15 ++++++++++++++- 5 files changed, 39 insertions(+), 6 deletions(-) diff --git a/addons/crm/crm_lead_menu.xml b/addons/crm/crm_lead_menu.xml index 8c38ed41a1c..623131cbf79 100644 --- a/addons/crm/crm_lead_menu.xml +++ b/addons/crm/crm_lead_menu.xml @@ -9,7 +9,11 @@ ['|', ('type','=','lead'), ('type','=',False)] - {'default_type':'lead', 'stage_type':'lead'} + { + 'default_type':'lead', + 'stage_type':'lead', + 'help_alias': {'type': 'lead'} + }

Click to create an unqualified lead. @@ -44,7 +48,12 @@ crm.lead kanban,tree,graph,form,calendar [('type','=','opportunity')] - {'stage_type': 'opportunity', 'default_type': 'opportunity', 'default_user_id': uid} + { + 'stage_type': 'opportunity', + 'default_type': 'opportunity', + 'default_user_id': uid, + 'help_alias': {'type': 'lead'} + } diff --git a/addons/crm/res_partner_view.xml b/addons/crm/res_partner_view.xml index 00a071fa954..a879dc49771 100644 --- a/addons/crm/res_partner_view.xml +++ b/addons/crm/res_partner_view.xml @@ -30,8 +30,11 @@ crm.lead kanban,tree,form,graph,calendar [('type','=','opportunity')] - {'search_default_partner_id': active_id, - 'stage_type': 'opportunity', 'default_type': 'opportunity'} + { + 'search_default_partner_id': active_id, + 'stage_type': 'opportunity', + 'default_type': 'opportunity', + 'help_alias': 'alias_defaults': {'type': 'lead'} diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml index b102c01193d..8059cb0b78a 100644 --- a/addons/project/project_view.xml +++ b/addons/project/project_view.xml @@ -50,7 +50,11 @@ Tasks project.task kanban,tree,form,calendar,gantt,graph - {'search_default_project_id': [active_id], 'default_project_id': active_id} + { + 'search_default_project_id': [active_id], + 'default_project_id': active_id, + 'help_alias': {'project_id': active_id} + }

@@ -612,6 +616,7 @@ project.task kanban,tree,form,calendar,gantt,graph + {'help_alias': {}}

Click to create a new task. diff --git a/addons/project_issue/project_issue_menu.xml b/addons/project_issue/project_issue_menu.xml index 78841f56156..38d0e830af8 100644 --- a/addons/project_issue/project_issue_menu.xml +++ b/addons/project_issue/project_issue_menu.xml @@ -13,6 +13,9 @@ + { + 'help_alias': {} + }

Click to report a new issue. diff --git a/addons/project_issue/project_issue_view.xml b/addons/project_issue/project_issue_view.xml index 77375450e9a..4ee6508c3b4 100644 --- a/addons/project_issue/project_issue_view.xml +++ b/addons/project_issue/project_issue_view.xml @@ -301,7 +301,20 @@ form Issues kanban,tree,form,calendar,graph - {'search_default_project_id': [active_id], 'default_project_id': active_id} + { + 'search_default_project_id': [active_id], + 'default_project_id': active_id, + 'help_alias': {'project_id': active_id} + } + +

+ Click to report a new issue. +

+ The OpenERP issues tacker allows you to efficiantly manage things + like internal requests, software development bugs, customer + complaints, project troubles, material breakdowns, etc. +

+
From b79cf38a37c32159bf459dfcf74fa76c53c29351 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 23 Jan 2013 13:12:06 +0100 Subject: [PATCH 017/388] [IMP] kanban: help message position bzr revid: chm@openerp.com-20130123121206-uehsdih50xy8jgts --- addons/web_kanban/static/src/css/kanban.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/web_kanban/static/src/css/kanban.css b/addons/web_kanban/static/src/css/kanban.css index 5492d4923fe..3eab33a0569 100644 --- a/addons/web_kanban/static/src/css/kanban.css +++ b/addons/web_kanban/static/src/css/kanban.css @@ -612,18 +612,18 @@ background: white; } -.openerp .oe_kanban_grouped .oe_view_nocontent { +.openerp .oe_kanban_view .oe_view_nocontent { position: relative; z-index: 1; max-width: none; height: 100%; } -.openerp .oe_kanban_grouped .oe_view_nocontent .oe_view_nocontent_content { +.openerp .oe_kanban_view .oe_view_nocontent .oe_view_nocontent_content { margin-left: 90px; margin-top: 5px; max-width: 700px; } -.openerp .oe_kanban_grouped .oe_view_nocontent .oe_view_nocontent_bg { +.openerp .oe_kanban_view .oe_view_nocontent .oe_view_nocontent_bg { background: #eee; opacity: 0.7; position: absolute; From 6416b6f27590ea643667ff8aba71a5cf5b0144e4 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 23 Jan 2013 13:13:46 +0100 Subject: [PATCH 018/388] [IMP] kanban: help message position bzr revid: chm@openerp.com-20130123121346-o1n8ne749npinkc4 --- addons/web_kanban/static/src/css/kanban.sass | 36 ++++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/addons/web_kanban/static/src/css/kanban.sass b/addons/web_kanban/static/src/css/kanban.sass index 4c4d8fa5dff..83ae61da356 100644 --- a/addons/web_kanban/static/src/css/kanban.sass +++ b/addons/web_kanban/static/src/css/kanban.sass @@ -51,28 +51,28 @@ //background: url(data:image/pngbase64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAYAAACp8Z5+AAAAKElEQVQIHWP8DwTv379nAAFBQUEGhnfv3oHEwADEZgJLIRGMIClkLQCr3x2Htp/lLwAAAABJRU5ErkJggg==) background: white height: inherit + .oe_view_nocontent + position: relative + z-index: 1 + max-width: none + height: 100% + .oe_view_nocontent_content + margin-left: 90px + margin-top: 5px + max-width: 700px + .oe_view_nocontent_bg + background: #eee + opacity: 0.7 + position: absolute + top: 0 + bottom: 0 + left: 0 + right: 0 + z-index: -1 &.oe_kanban_grouped .oe_kanban_dummy_cell background: url(/web/static/src/img/form_sheetbg.png) width: 100% - .oe_view_nocontent - position: relative - z-index: 1 - max-width: none - height: 100% - .oe_view_nocontent_content - margin-left: 90px - margin-top: 5px - max-width: 700px - .oe_view_nocontent_bg - background: #eee - opacity: 0.7 - position: absolute - top: 0 - bottom: 0 - left: 0 - right: 0 - z-index: -1 .ui-sortable-placeholder border: 1px solid rgba(0,0,0,0.1) visibility: visible !important From e3a7ae5ac20d2c8f7c3bf60c9c25480c3f935f96 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 23 Jan 2013 13:18:55 +0100 Subject: [PATCH 019/388] [IMP] mail_alias: add the context help_alias to hr applicant bzr revid: chm@openerp.com-20130123121855-je4gi42vf9xoe8rz --- addons/hr_recruitment/hr_recruitment_menu.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/hr_recruitment/hr_recruitment_menu.xml b/addons/hr_recruitment/hr_recruitment_menu.xml index dbd4335d730..e8865042cff 100644 --- a/addons/hr_recruitment/hr_recruitment_menu.xml +++ b/addons/hr_recruitment/hr_recruitment_menu.xml @@ -9,6 +9,7 @@ kanban,tree,form,graph,calendar + {'help_alias': {}}

Click to add a new job applicant. From 074ed6434dc378e68cd941d409337fbf4b910ad1 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 23 Jan 2013 14:35:11 +0100 Subject: [PATCH 020/388] [IMP] mail_alias: add test and comment bzr revid: chm@openerp.com-20130123133511-urqh79myokm32cgg --- addons/mail/mail_alias.py | 4 +- addons/mail/tests/__init__.py | 3 +- addons/mail/tests/test_mail_alias.py | 59 ++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 addons/mail/tests/test_mail_alias.py diff --git a/addons/mail/mail_alias.py b/addons/mail/mail_alias.py index 8e76efef859..0784303d886 100644 --- a/addons/mail/mail_alias.py +++ b/addons/mail/mail_alias.py @@ -199,7 +199,9 @@ class mail_alias(osv.Model): return self.create(cr, uid, vals, context=context) def get_alias(self, cr, uid, model, alias_defaults={}, context=None): - """Return the mail alias + """Return the mail alias for a document + This method is used by the web client (method web.view.insert_alias) + Arguments: model and content of alias_defaults column """ model_id = self.pool.get('ir.model').search(cr, uid, [('model', '=', model)], context=context)[0] diff --git a/addons/mail/tests/__init__.py b/addons/mail/tests/__init__.py index b945da54655..5d581e40276 100644 --- a/addons/mail/tests/__init__.py +++ b/addons/mail/tests/__init__.py @@ -19,10 +19,11 @@ # ############################################################################## -from . import test_mail_message, test_mail_features, test_message_read, test_invite +from . import test_mail_message, test_mail_features, test_message_read, test_invite, test_mail_alias checks = [ test_mail_message, + test_mail_alias, test_mail_features, test_message_read, test_invite, diff --git a/addons/mail/tests/test_mail_alias.py b/addons/mail/tests/test_mail_alias.py new file mode 100644 index 00000000000..803d45a8a65 --- /dev/null +++ b/addons/mail/tests/test_mail_alias.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Business Applications +# Copyright (c) 2012-TODAY OpenERP S.A. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp.tools import mute_logger +from openerp.tests import common + +class test_mail_alias(common.TransactionCase): + + def setUp(self): + super(test_mail_alias, self).setUp() + cr, uid = self.cr, self.uid + + # Usefull models + self.ir_model = self.registry('ir.model') + self.mail_alias = self.registry('mail.alias') + + #@mute_logger('openerp.addons.base.ir.ir_model', 'openerp.osv.orm') + def test_00_mail_alias(self): + """ Testing mail_group access rights and basic mail_thread features """ + cr, uid = self.cr, self.uid + + alias_name_0 = "global+alias+test_0" + alias_name_1 = "document+alias+test_1" + alias_defaults_1 = {'field_pigs': 11} + alias_name_2 = "document+alias+test_2" + alias_defaults_2 = {'field_pigs': 112} + + # Create an alias + partner_model_id = self.ir_model.search(cr, uid, [('model', '=', 'mail.alias')])[0] + alias_id_0 = self.mail_alias.create(cr, uid, + {'alias_model_id': partner_model_id, 'alias_name': alias_name_0, 'alias_defaults': {}}) + alias_id_1 = self.mail_alias.create(cr, uid, + {'alias_model_id': partner_model_id, 'alias_name': alias_name_1, 'alias_defaults': alias_defaults_1}) + alias_id_2 = self.mail_alias.create(cr, uid, + {'alias_model_id': partner_model_id, 'alias_name': alias_name_2, 'alias_defaults': alias_defaults_2}) + + # alias of the model and alias for a docmuent + alias = self.mail_alias.get_alias(cr, uid, 'mail.alias', {'field_pigs': 11}) + self.assertEqual(len(alias), 2, "get_alias don't return the alias of the document and the default alias of the model") + self.assertEqual(alias[0].get('id'), alias_id_1, "get_alias don't return the alias of the document") + self.assertEqual(alias[1].get('id'), alias_id_0, "get_alias don't return the default alias of the model") \ No newline at end of file From 6f91398ce9baccd659d81e4fd6f64674716b092e Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 23 Jan 2013 14:47:51 +0100 Subject: [PATCH 021/388] [IMP] mail_alias: add documentation bzr revid: chm@openerp.com-20130123134751-ka74ff0guzsjod1c --- addons/mail/doc/mail_alias.rst | 37 ++++++++++++++++++++++++++++++++++ addons/mail/mail_alias.py | 6 ++++-- 2 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 addons/mail/doc/mail_alias.rst diff --git a/addons/mail/doc/mail_alias.rst b/addons/mail/doc/mail_alias.rst new file mode 100644 index 00000000000..fa5a2fe0fda --- /dev/null +++ b/addons/mail/doc/mail_alias.rst @@ -0,0 +1,37 @@ +.. _mail_alias: + +mail.alias +============ + +Models ++++++++ + +``mail.alias`` is a class for mapping of an email address with a given OpenERP Document model. It is used by OpenERP's mail gateway when processing incoming emails sent to the system. If the recipient address (To) of the message matches a Mail Alias, the message will be either processed following the rules of that alias. If the message is a reply it will be attached to the existing discussion on the corresponding record, otherwise a new record of the corresponding model will be created. +This is meant to be used in combination with a catch-all email configuration on the company's mail server, so that as soon as a new mail.alias is created, it becomes immediately usable and OpenERP will accept email for it. + +.. versionchanged:: 7.1 + +Some Fields ++++++++++++ + + - ``alias_name`` : + The name of the email alias, e.g. 'jobs' + - ``alias_model_id`` : + The model (OpenERP Document Kind) to which this alias corresponds. Any incoming email that does not reply to an existing record will cause the creation of a new record of this model (e.g. a Project Task) + - ``alias_defaults`` : + A Python dictionary that will be evaluated to provide default values when creating new records for this alias. + - ``alias_domain`` : + +Methods ++++++++ + + - ``name_get`` : + Return the mail alias display alias_name, inclusing the implicit mail catchall domain from config. + e.g. `jobs@openerp.my.openerp.com` or `sales@openerp.my.openerp.com` + - ``create_unique_alias`` : + Creates an email.alias record according to the values provided in ``vals``, with 2 alterations: the ``alias_name`` value may be suffixed in order to make it unique, and the ``alias_model_id`` value will set to the model ID of the ``model_name`` value, if provided, + - ``get_alias`` : + Return the mail alias for a document (or the default mail alias of the model). + Arguments: + model (model OpenERP) + alias_defaults (A Python dictionary to provide default values when creating new records for this alias.) \ No newline at end of file diff --git a/addons/mail/mail_alias.py b/addons/mail/mail_alias.py index 0784303d886..f7cf115be55 100644 --- a/addons/mail/mail_alias.py +++ b/addons/mail/mail_alias.py @@ -199,9 +199,11 @@ class mail_alias(osv.Model): return self.create(cr, uid, vals, context=context) def get_alias(self, cr, uid, model, alias_defaults={}, context=None): - """Return the mail alias for a document + """Return the mail alias for a document (or the default mail alias of the model) This method is used by the web client (method web.view.insert_alias) - Arguments: model and content of alias_defaults column + Arguments: + model (model OpenERP) + alias_defaults (A Python dictionary to provide default values when creating new records for this alias.) """ model_id = self.pool.get('ir.model').search(cr, uid, [('model', '=', model)], context=context)[0] From 21938b80ff53265672c955522c30f0f0b0e1c608 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Fri, 25 Jan 2013 12:04:34 +0100 Subject: [PATCH 022/388] [IMP] crm: Sales Teams menu with breadcrum bzr revid: chm@openerp.com-20130125110434-whqnmhrvdqj0r9gh --- addons/crm/__openerp__.py | 3 + addons/crm/crm.py | 16 +++ addons/crm/crm_lead_data.xml | 1 + addons/crm/crm_salesteams.xml | 151 ++++++++++++++++++++++++ addons/crm/crm_view.xml | 94 +++++++-------- addons/crm/security/ir.model.access.csv | 2 +- addons/crm/static/src/css/crm.css | 22 ++++ 7 files changed, 242 insertions(+), 47 deletions(-) create mode 100644 addons/crm/crm_salesteams.xml create mode 100644 addons/crm/static/src/css/crm.css diff --git a/addons/crm/__openerp__.py b/addons/crm/__openerp__.py index 4a792abc9ee..46ce37f188c 100644 --- a/addons/crm/__openerp__.py +++ b/addons/crm/__openerp__.py @@ -80,6 +80,8 @@ Dashboard for CRM will include: 'crm_lead_view.xml', 'crm_lead_menu.xml', + 'crm_salesteams.xml', + 'crm_meeting_menu.xml', 'crm_phonecall_view.xml', @@ -113,6 +115,7 @@ Dashboard for CRM will include: 'test/ui/duplicate_lead.yml', 'test/ui/delete_lead.yml', ], + 'css': ['static/src/css/crm.css'], 'installable': True, 'application': True, 'auto_install': False, diff --git a/addons/crm/crm.py b/addons/crm/crm.py index df6d5e12b66..9fa6b6281f7 100644 --- a/addons/crm/crm.py +++ b/addons/crm/crm.py @@ -109,6 +109,20 @@ class crm_case_section(osv.osv): def get_full_name(self, cr, uid, ids, field_name, arg, context=None): return dict(self.name_get(cr, uid, ids, context=context)) + def get_number_leads(self, cr, uid, section_ids, field_name, arg, context=None): + res = dict.fromkeys(section_ids, 0) + lead_obj = self.pool.get('crm.lead') + for section_id in section_ids: + res[section_id] = lead_obj.search(cr, uid, [("section_id", "=", section_id), '|', '|', ("type", "=", "lead"), ("type", "=", "both"), ("type", "=", False), ('state', 'not in', ['done', 'cancel'])], count=True, context=context) + return res + + def get_number_opportunities(self, cr, uid, section_ids, field_name, arg, context=None): + res = dict.fromkeys(section_ids, 0) + lead_obj = self.pool.get('crm.lead') + for section_id in section_ids: + res[section_id] = lead_obj.search(cr, uid, [("section_id", "=", section_id), '|', ("type", "=", "opportunity"), ("type", "=", "both"), ('state', 'not in', ['done', 'cancel'])], context=context, count=True) + return res + _columns = { 'name': fields.char('Sales Team', size=64, required=True, translate=True), 'complete_name': fields.function(get_full_name, type='char', size=256, readonly=True, store=True), @@ -128,6 +142,8 @@ class crm_case_section(osv.osv): 'alias_id': fields.many2one('mail.alias', 'Alias', ondelete="cascade", required=True, help="The email address associated with this team. New emails received will automatically " "create new leads assigned to the team."), + 'number_lead': fields.function(get_number_leads, type='integer', readonly=True), + 'number_opportunity': fields.function(get_number_opportunities, type='integer', readonly=True), } def _get_stage_common(self, cr, uid, context): diff --git a/addons/crm/crm_lead_data.xml b/addons/crm/crm_lead_data.xml index bb590f49d73..d516b209864 100644 --- a/addons/crm/crm_lead_data.xml +++ b/addons/crm/crm_lead_data.xml @@ -45,6 +45,7 @@ Won + done diff --git a/addons/crm/crm_salesteams.xml b/addons/crm/crm_salesteams.xml new file mode 100644 index 00000000000..5bed5606b72 --- /dev/null +++ b/addons/crm/crm_salesteams.xml @@ -0,0 +1,151 @@ + + + + + + + + Leads + crm.lead + tree,form + ['|', ('type','=','lead'), ('type','=',False)] + { + 'search_default_section_id': [active_id], + 'default_section_id': active_id, + 'search_default_new': True, + 'search_default_open': True + } + +

+ Click to create a new lead. +

+ Use leads if you need a qualification step before creating an + opportunity or a customer. It can be a business card you received, + a contact form filled in your website, or a file of unqualified + prospects you import, etc. +

+ Once qualified, the lead can be converted into a business + opportunity and/or a new customer in your address book. +

+
+ + + + + + Leads + crm.lead + kanban,tree,form + [('type','=','opportunity')] + + { + 'search_default_section_id': [active_id], + 'default_section_id': active_id, + 'search_default_new': True, + 'search_default_open': True + } + +

+ Click to create a new lead. +

+ Use leads if you need a qualification step before creating an + opportunity or a customer. It can be a business card you received, + a contact form filled in your website, or a file of unqualified + prospects you import, etc. +

+ Once qualified, the lead can be converted into a business + opportunity and/or a new customer in your address book. +

+
+
+ + + + + crm.case.section.kanban + crm.case.section + + + + + + + + + + + +
+
+ í + +
+
+

+ +
+ + () +
+
+
+

+ +
+ + + +
+
+ + + +
+
+
+
+
+
+
+ + + + + Sales Teams + crm.case.section + form + kanban,tree,form + + +

+ Click to define a new sales team. +

+ Use sales team to organize your different salespersons or + departments into separate teams. Each team will work in + its own list of opportunities. +

+
+
+ + + + \ No newline at end of file diff --git a/addons/crm/crm_view.xml b/addons/crm/crm_view.xml index 2c156ca2ac2..23d71ef51d4 100644 --- a/addons/crm/crm_view.xml +++ b/addons/crm/crm_view.xml @@ -77,56 +77,58 @@ crm.case.section
- + - - - - - - - - - - - - - - - - - + +
- + + + diff --git a/addons/mail/mail_group_view.xml b/addons/mail/mail_group_view.xml index fba192b18bc..95af1df5967 100644 --- a/addons/mail/mail_group_view.xml +++ b/addons/mail/mail_group_view.xml @@ -69,39 +69,38 @@ - +

+
- -
-
+
- - - - - - - -
- This group is visible by everyone, - including your customers if you installed - the portal module. -
-
- Only the invited followers can read the - discussions on this group. -
-
+ + + + + + +
+ This group is visible by everyone, + including your customers if you installed + the portal module. +
+
+ Only the invited followers can read the + discussions on this group. +
diff --git a/addons/mail/static/src/css/mail_group.css b/addons/mail/static/src/css/mail_group.css index c1cefee9070..4f2b8a16dd0 100644 --- a/addons/mail/static/src/css/mail_group.css +++ b/addons/mail/static/src/css/mail_group.css @@ -14,6 +14,10 @@ padding: 0px 18px; } +.openerp .oe_form_sheetbg.openerp_mail_group_sheet .oe_avatar { + padding-top: 3px; +} + /* Resize footer width */ .openerp .oe_form div.oe_mail_group_footer { max-width: 80%; @@ -21,7 +25,7 @@ /* Resize group description */ .openerp .oe_form_sheetbg.openerp_mail_group_sheet .oe_form_field_text > textarea { - height: 40px; + height: 60px; } /* ------------------------------ */ diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml index 8059cb0b78a..dd54f41bb2d 100644 --- a/addons/project/project_view.xml +++ b/addons/project/project_view.xml @@ -105,6 +105,12 @@ + + + @@ -135,13 +141,6 @@ - -
- -
-
@@ -273,6 +272,12 @@
+ +
+ + + +
From ffa9a978c48e9e693f83859863cfaacbab4f08ff Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Fri, 1 Feb 2013 10:21:43 +0100 Subject: [PATCH 026/388] [IMP] salesteams bzr revid: chm@openerp.com-20130201092143-1y8zg4u1mxcgy2yz --- addons/crm/crm_salesteams.xml | 24 +++++++----------------- addons/crm/res_partner_view.xml | 3 ++- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/addons/crm/crm_salesteams.xml b/addons/crm/crm_salesteams.xml index e796ac789d0..6c32deb79cf 100644 --- a/addons/crm/crm_salesteams.xml +++ b/addons/crm/crm_salesteams.xml @@ -10,10 +10,7 @@ tree,form ['|', ('type','=','lead'), ('type','=',False)] { - 'search_default_section_id': [active_id], - 'default_section_id': active_id, - 'search_default_new': True, - 'search_default_open': True + 'search_default_section_id': [active_id], 'default_section_id': active_id, 'search_default_new': True, 'search_default_open': True, 'help_alias': {'type': "lead", 'section_id': active_id} }

@@ -39,10 +36,7 @@ [('type','=','opportunity')] { - 'search_default_section_id': [active_id], - 'default_section_id': active_id, - 'search_default_new': True, - 'search_default_open': True + 'search_default_section_id': [active_id], 'default_section_id': active_id, 'search_default_new': True, 'search_default_open': True, 'help_alias': {'type': "lead", 'section_id': active_id} }

@@ -95,16 +89,12 @@

diff --git a/addons/crm/res_partner_view.xml b/addons/crm/res_partner_view.xml index a879dc49771..9faf86b12a6 100644 --- a/addons/crm/res_partner_view.xml +++ b/addons/crm/res_partner_view.xml @@ -34,7 +34,8 @@ 'search_default_partner_id': active_id, 'stage_type': 'opportunity', 'default_type': 'opportunity', - 'help_alias': 'alias_defaults': {'type': 'lead'} + 'help_alias': {'type': 'lead'} + } From 0d3004e8290b7d9ff90d1f84ee7353b6a9e75694 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Fri, 1 Feb 2013 10:51:33 +0100 Subject: [PATCH 027/388] [IMP] view: only first alias displayed bzr revid: chm@openerp.com-20130201095133-i3p6vehexh7a9bqh --- addons/web/static/src/js/views.js | 20 ++++---------------- addons/web/static/src/xml/base.xml | 2 +- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js index 625f50ca2f8..4b532e633be 100644 --- a/addons/web/static/src/js/views.js +++ b/addons/web/static/src/js/views.js @@ -1406,23 +1406,11 @@ instance.web.View = instance.web.Widget.extend({ 'model': this.options.action.res_model, 'alias_defaults': context.help_alias }).then(function (alias_ids) { - if (alias_ids.length) { + if (alias_ids.length && alias_ids[0].email.match(/@.+/)) { + // alias_ids[0].global var $alias = $(QWeb.render('View.nocontent_alias')); - var global = false; - var inc = 0; - _.each(alias_ids, function (alias_id) { - if (alias_id.email.match(/@.+/)) { - if (inc && global != alias_id.global) { - $alias.append('
' + _t("or")); - global = alias_id.global; - } - $alias.append('
' + alias_id.email + ''); - inc++; - } - }) - if(inc) { - $dom.append($alias); - } + $alias.append('' + alias_ids[0].email + ''); + $dom.append($alias); } }); } diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml index 30a3f8f2351..47eb0214616 100644 --- a/addons/web/static/src/xml/base.xml +++ b/addons/web/static/src/xml/base.xml @@ -1873,7 +1873,7 @@

- You can also create the document by sending an email to : + You can also create documents by sending an email to:

From 18da8cdc5b22e63f3f43e941408cbe98d2c2e368 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Fri, 1 Feb 2013 12:56:42 +0100 Subject: [PATCH 028/388] [IMP] crm,project,mail: css for alias bzr revid: chm@openerp.com-20130201115642-n1wijg4exsibju84 --- addons/crm/__openerp__.py | 1 + addons/crm/crm_salesteams.xml | 31 ++++++++--------------- addons/crm/static/src/css/crm.css | 17 +++++++++++++ addons/crm/static/src/js/crm.js | 11 ++++++++ addons/mail/mail_group_view.xml | 3 +-- addons/project/project_view.xml | 10 +++----- addons/project/static/src/css/project.css | 17 +++++++++++++ 7 files changed, 60 insertions(+), 30 deletions(-) create mode 100644 addons/crm/static/src/js/crm.js diff --git a/addons/crm/__openerp__.py b/addons/crm/__openerp__.py index 46ce37f188c..1ae67f1fb55 100644 --- a/addons/crm/__openerp__.py +++ b/addons/crm/__openerp__.py @@ -116,6 +116,7 @@ Dashboard for CRM will include: 'test/ui/delete_lead.yml', ], 'css': ['static/src/css/crm.css'], + 'js': ['static/src/js/crm.js'], 'installable': True, 'application': True, 'auto_install': False, diff --git a/addons/crm/crm_salesteams.xml b/addons/crm/crm_salesteams.xml index 6c32deb79cf..e6caa03c042 100644 --- a/addons/crm/crm_salesteams.xml +++ b/addons/crm/crm_salesteams.xml @@ -59,7 +59,7 @@ crm.case.section.kanban crm.case.section - + @@ -70,29 +70,24 @@ -
+
-

- -
- - () -
-
-
-

+

+
+ %% +
@@ -101,12 +96,6 @@
- -
- - - -
diff --git a/addons/crm/static/src/css/crm.css b/addons/crm/static/src/css/crm.css index 06c612561e6..e9f7abfa7ae 100644 --- a/addons/crm/static/src/css/crm.css +++ b/addons/crm/static/src/css/crm.css @@ -19,4 +19,21 @@ -box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); } +.oe_kanban_crm_salesteams_alias { + margin: -8px 0 8px 0; +} +.oe_kanban_crm_salesteams_alias .oe_e { + font-size: 30px; + line-height: 6px; + vertical-align: top; + margin-right: 3px; + color: white; + text-shadow: 0px 0px 2px rgba(0, 0, 0, 1); + float: left; +} + +.oe_kanban_crm_salesteams_alias small { + display: block; + margin-left: 20px; +} \ No newline at end of file diff --git a/addons/crm/static/src/js/crm.js b/addons/crm/static/src/js/crm.js new file mode 100644 index 00000000000..e027313d6dc --- /dev/null +++ b/addons/crm/static/src/js/crm.js @@ -0,0 +1,11 @@ +openerp.crm = function(openerp) { + openerp.web_kanban.KanbanRecord.include({ + on_card_clicked: function() { + if (this.view.dataset.model === 'crm.case.section') { + this.$('.oe_kanban_crm_salesteams_list a').first().click(); + } else { + this._super.apply(this, arguments); + } + }, + }); +}; diff --git a/addons/mail/mail_group_view.xml b/addons/mail/mail_group_view.xml index 95af1df5967..feb62e9aea4 100644 --- a/addons/mail/mail_group_view.xml +++ b/addons/mail/mail_group_view.xml @@ -75,11 +75,10 @@

-
diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml index dd54f41bb2d..893eae68dcd 100644 --- a/addons/project/project_view.xml +++ b/addons/project/project_view.xml @@ -246,8 +246,10 @@ diff --git a/addons/project/static/src/css/project.css b/addons/project/static/src/css/project.css index 1ea3c705105..e4d2196d476 100644 --- a/addons/project/static/src/css/project.css +++ b/addons/project/static/src/css/project.css @@ -62,4 +62,21 @@ -box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); } +.oe_kanban_project_alias { + margin: -8px 0 8px 0; +} +.oe_kanban_project_alias .oe_e { + font-size: 30px; + line-height: 6px; + vertical-align: top; + margin-right: 3px; + color: white; + text-shadow: 0px 0px 2px rgba(0, 0, 0, 1); + float: left; +} + +.oe_kanban_project_alias small { + display: block; + margin-left: 20px; +} \ No newline at end of file From 3da294f56a1e025899e180e4c3abeda877a9db53 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Mon, 4 Feb 2013 15:58:24 +0100 Subject: [PATCH 029/388] [IMP] ir_action: averwrite read to add a dynamic_help on model bzr revid: chm@openerp.com-20130204145824-mq423czac9k2inzo --- openerp/addons/base/ir/ir_actions.py | 20 ++++++++++++++++++-- openerp/osv/orm.py | 3 +++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/openerp/addons/base/ir/ir_actions.py b/openerp/addons/base/ir/ir_actions.py index 4404b0a8a50..841e16af01c 100644 --- a/openerp/addons/base/ir/ir_actions.py +++ b/openerp/addons/base/ir/ir_actions.py @@ -216,9 +216,9 @@ class act_window(osv.osv): 'name': fields.char('Action Name', size=64, translate=True), 'type': fields.char('Action Type', size=32, required=True), 'view_id': fields.many2one('ir.ui.view', 'View Ref.', ondelete='cascade'), - 'domain': fields.char('Domain Value', size=250, + 'domain': fields.char('Domain Value', help="Optional domain filtering of the destination data, as a Python expression"), - 'context': fields.char('Context Value', size=250, required=True, + 'context': fields.char('Context Value', required=True, help="Context dictionary as Python expression, empty by default (Default: {})"), 'res_id': fields.integer('Record ID', help="Database ID of record to open in form view, when ``view_mode`` is set to 'form' only"), 'res_model': fields.char('Destination Model', size=64, required=True, @@ -261,6 +261,22 @@ class act_window(osv.osv): 'multi': False, } + def read(self, cr, uid, ids, fields=None, context=None, load='_classic_read'): + results = super(act_window, self).read(cr, uid, ids, fields=fields, context=context, load=load) + + if not fields or 'help' in fields: + context = dict(context) + dic = { + 'active_model' : context.get('active_model', None), + 'active_id' : context.get('active_id', None), + 'active_ids' : context.get('active_ids', None) + } + for res in results: + if res.get('res_model', False): + res['help'] = self.pool.get(res.get('res_model')).dynamic_help(cr, uid, res.get('help', ""), context=dict(context, **eval(res['context'], dic))) + + return results + def for_xml_id(self, cr, uid, module, xml_id, context=None): """ Returns the act_window object created for the provided xml_id diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index 6056e405b78..1bb98351e23 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -3614,6 +3614,9 @@ class BaseModel(object): return result and result[0] or False return result + def dynamic_help(self, cr, user, help, context=None): + return help + def _read_flat(self, cr, user, ids, fields_to_read, context=None, load='_classic_read'): if not context: context = {} From bd8cefa073eb97368edef60308d2a1ab722331e6 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Mon, 4 Feb 2013 16:00:58 +0100 Subject: [PATCH 030/388] [IMP] project: use dynamic_help to add alias on help bzr revid: chm@openerp.com-20130204150058-x2erdwbt71d1lz1p --- addons/crm/crm_lead_menu.xml | 6 +- addons/crm/crm_salesteams.xml | 62 +++++++++++++++---- addons/crm/res_partner_view.xml | 3 +- addons/hr_recruitment/hr_recruitment_menu.xml | 1 - addons/mail/mail_alias.py | 57 +++-------------- addons/project/project.py | 10 +++ addons/project/project_view.xml | 5 +- addons/project_issue/project_issue_menu.xml | 3 - addons/project_issue/project_issue_view.xml | 3 +- 9 files changed, 71 insertions(+), 79 deletions(-) diff --git a/addons/crm/crm_lead_menu.xml b/addons/crm/crm_lead_menu.xml index 623131cbf79..823e0595354 100644 --- a/addons/crm/crm_lead_menu.xml +++ b/addons/crm/crm_lead_menu.xml @@ -11,8 +11,7 @@ { 'default_type':'lead', - 'stage_type':'lead', - 'help_alias': {'type': 'lead'} + 'stage_type':'lead' }

@@ -51,8 +50,7 @@ { 'stage_type': 'opportunity', 'default_type': 'opportunity', - 'default_user_id': uid, - 'help_alias': {'type': 'lead'} + 'default_user_id': uid } diff --git a/addons/crm/crm_salesteams.xml b/addons/crm/crm_salesteams.xml index e6caa03c042..9a76c98a985 100644 --- a/addons/crm/crm_salesteams.xml +++ b/addons/crm/crm_salesteams.xml @@ -9,8 +9,10 @@ crm.lead tree,form ['|', ('type','=','lead'), ('type','=',False)] + + { - 'search_default_section_id': [active_id], 'default_section_id': active_id, 'search_default_new': True, 'search_default_open': True, 'help_alias': {'type': "lead", 'section_id': active_id} + 'search_default_section_id': [active_id], 'default_section_id': active_id, 'default_type':'lead', 'stage_type':'lead' }

@@ -27,32 +29,67 @@ + + + tree + + + + + + + form + + + + - Leads + Opportunities crm.lead - kanban,tree,form + kanban,tree,graph,form,calendar [('type','=','opportunity')] + { - 'search_default_section_id': [active_id], 'default_section_id': active_id, 'search_default_new': True, 'search_default_open': True, 'help_alias': {'type': "lead", 'section_id': active_id} + 'search_default_section_id': [active_id], 'default_section_id': active_id, 'stage_type': 'opportunity', 'default_type': 'opportunity', 'default_user_id': uid }

- Click to create a new lead. + Click to create a new opportunity.

- Use leads if you need a qualification step before creating an - opportunity or a customer. It can be a business card you received, - a contact form filled in your website, or a file of unqualified - prospects you import, etc. + OpenERP helps you keep track of your sales pipeline to follow + up potential sales and better forecast your future revenues.

- Once qualified, the lead can be converted into a business - opportunity and/or a new customer in your address book. + You will be able to plan meetings and phone calls from + opportunities, convert them into quotations, attach related + documents, track all discussions, and much more.

+ + + kanban + + + + + + + tree + + + + + + + form + + + + @@ -65,7 +102,6 @@ - @@ -80,7 +116,7 @@

-
+
%%
diff --git a/addons/crm/res_partner_view.xml b/addons/crm/res_partner_view.xml index 9faf86b12a6..150c1eeebbe 100644 --- a/addons/crm/res_partner_view.xml +++ b/addons/crm/res_partner_view.xml @@ -33,8 +33,7 @@ { 'search_default_partner_id': active_id, 'stage_type': 'opportunity', - 'default_type': 'opportunity', - 'help_alias': {'type': 'lead'} + 'default_type': 'opportunity' } diff --git a/addons/hr_recruitment/hr_recruitment_menu.xml b/addons/hr_recruitment/hr_recruitment_menu.xml index e8865042cff..dbd4335d730 100644 --- a/addons/hr_recruitment/hr_recruitment_menu.xml +++ b/addons/hr_recruitment/hr_recruitment_menu.xml @@ -9,7 +9,6 @@ kanban,tree,form,graph,calendar - {'help_alias': {}}

Click to add a new job applicant. diff --git a/addons/mail/mail_alias.py b/addons/mail/mail_alias.py index f7cf115be55..a079448487d 100644 --- a/addons/mail/mail_alias.py +++ b/addons/mail/mail_alias.py @@ -118,8 +118,13 @@ class mail_alias(osv.Model): mail catchall domain from config. e.g. `jobs@openerp.my.openerp.com` or `sales@openerp.my.openerp.com` """ - return [(record['id'], "%s@%s" % (record['alias_name'], record['alias_domain'])) - for record in self.read(cr, uid, ids, ['alias_name', 'alias_domain'], context=context)] + res = [] + for record in self.browse(cr, uid, ids, context=context): + if record.alias_name and record.alias_domain: + res.append((record['id'], "%s@%s" % (record.alias_name, record.alias_domain))) + else: + res.append((record['id'], False)) + return res def _find_unique(self, cr, uid, name, context=None): """Find a unique alias name similar to ``name``. If ``name`` is @@ -197,51 +202,3 @@ class mail_alias(osv.Model): model_id = self.pool.get('ir.model').search(cr, uid, [('model', '=', model_name)], context=context)[0] vals['alias_model_id'] = model_id return self.create(cr, uid, vals, context=context) - - def get_alias(self, cr, uid, model, alias_defaults={}, context=None): - """Return the mail alias for a document (or the default mail alias of the model) - This method is used by the web client (method web.view.insert_alias) - Arguments: - model (model OpenERP) - alias_defaults (A Python dictionary to provide default values when creating new records for this alias.) - """ - model_id = self.pool.get('ir.model').search(cr, uid, [('model', '=', model)], context=context)[0] - - result = [] - # get the value with required attribute - domain = [('alias_model_id', '=', model_id)] - if alias_defaults: - for item in alias_defaults.items(): - domain += ['|', '|', '|', - ('alias_defaults', 'like', ("%%'%s': %s%%" % (item[0], item[1]))), - ('alias_defaults', 'like', ("%%'%s':%s%%" % (item[0], item[1]))), - ('alias_defaults', 'like', ("%%'%s': '%s'%%" % (item[0], item[1]))), - ('alias_defaults', 'like', ("%%'%s':'%s'%%" % (item[0], item[1])))] - else: - domain += [('alias_defaults', 'like', "{}")] - - ids = self.search(cr, uid, domain, context=context) - if ids: - for record in self.browse(cr, uid, ids, context=context): - test = True - if alias_defaults: - for item in ast.literal_eval(record.alias_defaults).items(): - if alias_defaults.get(item[0]) == None or alias_defaults.get(item[0]) != item[1]: - test = False - continue - if test: - result.append( {'id': record.id, 'email': "%s@%s" % (record.alias_name, record.alias_domain), 'global': False}) - - # get the default value - if alias_defaults: - domain = [('alias_model_id', '=', model_id)] - for item in alias_defaults.items(): - domain += [ - ('alias_defaults', 'not like', ("%%'%s'%%" % (item[0])))] - - ids = self.search(cr, uid, domain, context=context) - if ids: - for record in self.browse(cr, uid, ids, context=context): - result.append( {'id': record.id, 'email': "%s@%s" % (record.alias_name, record.alias_domain), 'global': True}) - - return result diff --git a/addons/project/project.py b/addons/project/project.py index f89ce8391fc..f2b104315d0 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -887,8 +887,18 @@ class task(base_stage, osv.osv): for f in res['fields']: if 'Hours' in res['fields'][f]['string']: res['fields'][f]['string'] = res['fields'][f]['string'].replace('Hours',tm) + return res + + def dynamic_help(self, cr, uid, help, context=None): + if context.get('default_project_id'): + project_id = self.pool.get('project.project').browse(cr, uid, context.get('default_project_id'), context=context) + alias = project_id.alias_id and project_id.alias_id.name_get() or False + if alias and alias[0] and alias[0][1]: + help = "%s%s" % (help, _("

You can also create documents by sending an email to: %s
" % alias[0][1])) + return help + # ---------------------------------------- # Case management # ---------------------------------------- diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml index 893eae68dcd..da05f4ba259 100644 --- a/addons/project/project_view.xml +++ b/addons/project/project_view.xml @@ -53,7 +53,6 @@ { 'search_default_project_id': [active_id], 'default_project_id': active_id, - 'help_alias': {'project_id': active_id} } @@ -232,7 +231,6 @@ - @@ -247,7 +245,7 @@

-
+
%%
@@ -617,7 +615,6 @@ project.task kanban,tree,form,calendar,gantt,graph - {'help_alias': {}}

Click to create a new task. diff --git a/addons/project_issue/project_issue_menu.xml b/addons/project_issue/project_issue_menu.xml index 38d0e830af8..78841f56156 100644 --- a/addons/project_issue/project_issue_menu.xml +++ b/addons/project_issue/project_issue_menu.xml @@ -13,9 +13,6 @@ - { - 'help_alias': {} - }

Click to report a new issue. diff --git a/addons/project_issue/project_issue_view.xml b/addons/project_issue/project_issue_view.xml index 4ee6508c3b4..2cdf8f0c943 100644 --- a/addons/project_issue/project_issue_view.xml +++ b/addons/project_issue/project_issue_view.xml @@ -303,8 +303,7 @@ kanban,tree,form,calendar,graph { 'search_default_project_id': [active_id], - 'default_project_id': active_id, - 'help_alias': {'project_id': active_id} + 'default_project_id': active_id }

From c349508149be291dc4a4e90d6f521baee6f3d9d7 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Mon, 4 Feb 2013 16:03:04 +0100 Subject: [PATCH 031/388] [IMP] web view: remove insert_alias and add active_id, active_model, active_ids into the context for web/action/load bzr revid: chm@openerp.com-20130204150304-j11944irbcp4o4gf --- addons/web/static/src/js/view_list.js | 1 - addons/web/static/src/js/views.js | 22 +--------------------- addons/web/static/src/xml/base.xml | 5 ----- addons/web_kanban/static/src/js/kanban.js | 5 ++--- 4 files changed, 3 insertions(+), 30 deletions(-) diff --git a/addons/web/static/src/js/view_list.js b/addons/web/static/src/js/view_list.js index c0231487640..fbbfabcacca 100644 --- a/addons/web/static/src/js/view_list.js +++ b/addons/web/static/src/js/view_list.js @@ -850,7 +850,6 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi this.$el.find('.oe_view_nocontent').click(function() { create_nocontent.openerpBounce(); }); - this.insert_alias(this.$el.find('.oe_view_nocontent')); } }); instance.web.ListView.List = instance.web.Class.extend( /** @lends instance.web.ListView.List# */{ diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js index 4b532e633be..fbe53711c8a 100644 --- a/addons/web/static/src/js/views.js +++ b/addons/web/static/src/js/views.js @@ -1306,7 +1306,7 @@ instance.web.View = instance.web.Widget.extend({ } else if (action_data.type=="action") { return this.rpc('/web/action/load', { action_id: action_data.name, - context: instance.web.pyeval.eval('context', context), + context: _.extend({'active_model': dataset.model, 'active_ids': dataset.ids, 'active_id': record_id}, instance.web.pyeval.eval('context', context)), do_not_eval: true }).then(handler); } else { @@ -1395,26 +1395,6 @@ instance.web.View = instance.web.Widget.extend({ var attrs = this.fields_view.arch.attrs; return (action in attrs) ? JSON.parse(attrs[action]) : true; }, - /** - * insert alias into the dom - */ - insert_alias: function ($dom) { - var self = this; - var context = this.options.action.context || {}; - if (context && context.help_alias) { - new instance.web.Model('mail.alias').call("get_alias", [], { - 'model': this.options.action.res_model, - 'alias_defaults': context.help_alias - }).then(function (alias_ids) { - if (alias_ids.length && alias_ids[0].email.match(/@.+/)) { - // alias_ids[0].global - var $alias = $(QWeb.render('View.nocontent_alias')); - $alias.append('' + alias_ids[0].email + ''); - $dom.append($alias); - } - }); - } - }, }); /** diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml index 47eb0214616..7604814fe1d 100644 --- a/addons/web/static/src/xml/base.xml +++ b/addons/web/static/src/xml/base.xml @@ -1871,9 +1871,4 @@ - -

- You can also create documents by sending an email to: -

- diff --git a/addons/web_kanban/static/src/js/kanban.js b/addons/web_kanban/static/src/js/kanban.js index 9fac388d7bc..618e3c7e915 100644 --- a/addons/web_kanban/static/src/js/kanban.js +++ b/addons/web_kanban/static/src/js/kanban.js @@ -456,15 +456,14 @@ instance.web_kanban.KanbanView = instance.web.View.extend({ var self = this; if (this.groups.group_by || !this.options.action - || !this.options.action.help) { + || (!this.options.action.help)) { return; } this.$el.find('table:first').css("position", "absolute"); - $(QWeb.render('KanbanView.nocontent', { content : this.options.action.help})).insertAfter(this.$('table:first')); + $(QWeb.render('KanbanView.nocontent', { content : this.options.action.dynamic_help || this.options.action.help})).insertAfter(this.$('table:first')); this.$el.find('.oe_view_nocontent').click(function() { self.$buttons.openerpBounce(); }); - this.insert_alias(this.$el.find('.oe_view_nocontent_content')); }, remove_no_result: function() { this.$el.find('table:first').css("position", false); From d45be56572a5c53da81019da88a39551167fdd29 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Tue, 5 Feb 2013 12:10:05 +0100 Subject: [PATCH 032/388] [FIX] mail_alias: remove test for removed method get_alias bzr revid: chm@openerp.com-20130205111005-e339w5chgz6zrv6m --- addons/mail/tests/test_mail_alias.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/addons/mail/tests/test_mail_alias.py b/addons/mail/tests/test_mail_alias.py index 803d45a8a65..2bd3e345a49 100644 --- a/addons/mail/tests/test_mail_alias.py +++ b/addons/mail/tests/test_mail_alias.py @@ -50,10 +50,4 @@ class test_mail_alias(common.TransactionCase): alias_id_1 = self.mail_alias.create(cr, uid, {'alias_model_id': partner_model_id, 'alias_name': alias_name_1, 'alias_defaults': alias_defaults_1}) alias_id_2 = self.mail_alias.create(cr, uid, - {'alias_model_id': partner_model_id, 'alias_name': alias_name_2, 'alias_defaults': alias_defaults_2}) - - # alias of the model and alias for a docmuent - alias = self.mail_alias.get_alias(cr, uid, 'mail.alias', {'field_pigs': 11}) - self.assertEqual(len(alias), 2, "get_alias don't return the alias of the document and the default alias of the model") - self.assertEqual(alias[0].get('id'), alias_id_1, "get_alias don't return the alias of the document") - self.assertEqual(alias[1].get('id'), alias_id_0, "get_alias don't return the default alias of the model") \ No newline at end of file + {'alias_model_id': partner_model_id, 'alias_name': alias_name_2, 'alias_defaults': alias_defaults_2}) \ No newline at end of file From 01cddc42a5dc5f0996426f0243e06300d2345def Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Tue, 5 Feb 2013 12:22:09 +0100 Subject: [PATCH 033/388] [IMP] project: help alias in bold bzr revid: chm@openerp.com-20130205112209-nsn8m1fd3j8aje8j --- addons/project/project.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/project/project.py b/addons/project/project.py index f2b104315d0..407b8257d7d 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -896,7 +896,7 @@ class task(base_stage, osv.osv): project_id = self.pool.get('project.project').browse(cr, uid, context.get('default_project_id'), context=context) alias = project_id.alias_id and project_id.alias_id.name_get() or False if alias and alias[0] and alias[0][1]: - help = "%s%s" % (help, _("
You can also create documents by sending an email to: %s
" % alias[0][1])) + help = "%s%s" % (help, _("
You can also create documents by sending an email to: %s
" % alias[0][1])) return help # ---------------------------------------- From ec02389784ab1a41d91ab8df6d53c953444e86b4 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Tue, 5 Feb 2013 12:22:58 +0100 Subject: [PATCH 034/388] [FIX] ir_action: read ir.actions.act_window bzr revid: chm@openerp.com-20130205112258-heruqrx53dahqi02 --- openerp/addons/base/ir/ir_actions.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openerp/addons/base/ir/ir_actions.py b/openerp/addons/base/ir/ir_actions.py index 841e16af01c..aae45805502 100644 --- a/openerp/addons/base/ir/ir_actions.py +++ b/openerp/addons/base/ir/ir_actions.py @@ -265,7 +265,7 @@ class act_window(osv.osv): results = super(act_window, self).read(cr, uid, ids, fields=fields, context=context, load=load) if not fields or 'help' in fields: - context = dict(context) + context = dict(context or {}) dic = { 'active_model' : context.get('active_model', None), 'active_id' : context.get('active_id', None), @@ -273,7 +273,8 @@ class act_window(osv.osv): } for res in results: if res.get('res_model', False): - res['help'] = self.pool.get(res.get('res_model')).dynamic_help(cr, uid, res.get('help', ""), context=dict(context, **eval(res['context'], dic))) + custom_context = dict(context.items() + (eval(res['context'] or "{}", dic) or {}).items()) + res['help'] = self.pool.get(res.get('res_model')).dynamic_help(cr, uid, res.get('help', ""), context=custom_context) return results From 3dd59aa69b237ecdb5bd3abb193fd3e2abb97b15 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Tue, 5 Feb 2013 14:39:33 +0100 Subject: [PATCH 035/388] [IMP] project: multi alias if no default_project_id bzr revid: chm@openerp.com-20130205133933-0x3s16gh4ftnx21y --- addons/project/project.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/addons/project/project.py b/addons/project/project.py index 407b8257d7d..8e6462ccba3 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -892,11 +892,24 @@ class task(base_stage, osv.osv): def dynamic_help(self, cr, uid, help, context=None): + alias_txt = "" if context.get('default_project_id'): project_id = self.pool.get('project.project').browse(cr, uid, context.get('default_project_id'), context=context) alias = project_id.alias_id and project_id.alias_id.name_get() or False if alias and alias[0] and alias[0][1]: - help = "%s%s" % (help, _("
You can also create documents by sending an email to: %s
" % alias[0][1])) + alias_txt = alias[0][1] + else: + model_id = self.pool.get('ir.model').search(cr, uid, [("model", "=", self._name)], context=context)[0] + alias_obj = self.pool.get('mail.alias') + alias_nb = 0 + alias_ids = alias_obj.search(cr, uid, [("alias_model_id", "=", model_id)], context=context, limit=5) + if alias_ids: + for alias in alias_obj.browse(cr, uid, alias_ids, context=context): + email = "%s@%s" % (alias.alias_name, alias.alias_domain) + alias_txt = "%s%s%s" % (alias_txt, (alias_nb and ", " or " "), email) + alias_nb += 1 + if alias_txt: + help = "%s %s" % (help, _("
You can also create documents by sending an email to: %s
" % alias_txt)) return help # ---------------------------------------- From a58fb0df5c061f432871cf37673507bd12110632 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Tue, 5 Feb 2013 15:51:01 +0100 Subject: [PATCH 036/388] [IMP] project: display group with empty message bzr revid: chm@openerp.com-20130205145101-h6jk9uw8av79aygp --- addons/project/project.py | 5 ++--- addons/project/static/src/css/project.css | 4 ++++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/addons/project/project.py b/addons/project/project.py index 8e6462ccba3..244def53c47 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -605,8 +605,7 @@ class task(base_stage, osv.osv): search_domain = [] project_id = self._resolve_project_id_from_context(cr, uid, context=context) if project_id: - search_domain += ['|', ('project_ids', '=', project_id)] - search_domain += [('id', 'in', ids)] + search_domain += [('project_ids', '=', project_id)] stage_ids = stage_obj._search(cr, uid, search_domain, order=order, access_rights_uid=access_rights_uid, context=context) result = stage_obj.name_get(cr, access_rights_uid, stage_ids, context=context) # restore order of the search @@ -909,7 +908,7 @@ class task(base_stage, osv.osv): alias_txt = "%s%s%s" % (alias_txt, (alias_nb and ", " or " "), email) alias_nb += 1 if alias_txt: - help = "%s %s" % (help, _("
You can also create documents by sending an email to: %s
" % alias_txt)) + help = "%s %s" % (help, _("
You can also create documents by sending an email to: %s
" % alias_txt)) return help # ---------------------------------------- diff --git a/addons/project/static/src/css/project.css b/addons/project/static/src/css/project.css index e4d2196d476..99bcd960e0f 100644 --- a/addons/project/static/src/css/project.css +++ b/addons/project/static/src/css/project.css @@ -1,3 +1,7 @@ +.oe_list .oe_view_nocontent_create_alias { + padding-left: 78px; +} + .oe_kanban_project { width: 220px; min-height: 160px; From 8c58ae9ad20f3d9c5a2a4742e6e9bfe2070f2d82 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Tue, 5 Feb 2013 15:52:44 +0100 Subject: [PATCH 037/388] [IMP] kanban: auto close quick_create when click an other quick_create, and hide help message bzr revid: chm@openerp.com-20130205145244-309lce3bsl5fb704 --- addons/web_kanban/static/src/js/kanban.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/addons/web_kanban/static/src/js/kanban.js b/addons/web_kanban/static/src/js/kanban.js index 618e3c7e915..7db23b3225d 100644 --- a/addons/web_kanban/static/src/js/kanban.js +++ b/addons/web_kanban/static/src/js/kanban.js @@ -583,19 +583,26 @@ instance.web_kanban.KanbanGroup = instance.web.Widget.extend({ }); this.$el.find('.oe_kanban_add').click(function () { - if (self.quick) { - return self.quick.trigger('close'); + if (self.view.quick) { + self.view.quick.trigger('close'); } + if (self.quick) { + return false; + } + self.view.$el.find('.oe_view_nocontent').hide(); var ctx = {}; ctx['default_' + self.view.group_by] = self.value; self.quick = new (get_class(self.view.quick_create_class))(this, self.dataset, ctx, true) .on('added', self, self.proxy('quick_created')) .on('close', self, function() { + self.view.$el.find('.oe_view_nocontent').show(); this.quick.destroy(); + delete self.view.quick; delete this.quick; }); self.quick.appendTo($(".oe_kanban_group_list_header", self.$records)); self.quick.focus(); + self.view.quick = self.quick; }); // Add bounce effect on image '+' of kanban header when click on empty space of kanban grouped column. this.$records.on('click', '.oe_kanban_show_more', this.do_show_more); @@ -731,6 +738,7 @@ instance.web_kanban.KanbanGroup = instance.web.Widget.extend({ */ quick_created: function (record) { var id = record, self = this; + self.view.remove_no_result(); self.trigger("add_record"); this.dataset.read_ids([id], this.view.fields_keys) .done(function (records) { From db35042ff828b2b0cad8f74292658eb600f4f7f0 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Tue, 5 Feb 2013 16:15:48 +0100 Subject: [PATCH 038/388] [FIX] ir_action: read accept list ids or id bzr revid: chm@openerp.com-20130205151548-t66esec4ygrw6z4v --- openerp/addons/base/ir/ir_actions.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openerp/addons/base/ir/ir_actions.py b/openerp/addons/base/ir/ir_actions.py index aae45805502..7ea98b3b0cf 100644 --- a/openerp/addons/base/ir/ir_actions.py +++ b/openerp/addons/base/ir/ir_actions.py @@ -262,6 +262,9 @@ class act_window(osv.osv): } def read(self, cr, uid, ids, fields=None, context=None, load='_classic_read'): + u = isinstance(ids, (int, long)) + if u: + ids = [ids] results = super(act_window, self).read(cr, uid, ids, fields=fields, context=context, load=load) if not fields or 'help' in fields: @@ -276,6 +279,8 @@ class act_window(osv.osv): custom_context = dict(context.items() + (eval(res['context'] or "{}", dic) or {}).items()) res['help'] = self.pool.get(res.get('res_model')).dynamic_help(cr, uid, res.get('help', ""), context=custom_context) + if u: + return results[0] return results def for_xml_id(self, cr, uid, module, xml_id, context=None): From 18985e673f7b0d1bdc499020e02987cb4ba45d49 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Tue, 5 Feb 2013 17:09:32 +0100 Subject: [PATCH 039/388] [FIX] ir_action: read context with uid bzr revid: chm@openerp.com-20130205160932-nqr1rk4t3l2yjhrz --- openerp/addons/base/ir/ir_actions.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openerp/addons/base/ir/ir_actions.py b/openerp/addons/base/ir/ir_actions.py index 7ea98b3b0cf..d1aa04426bb 100644 --- a/openerp/addons/base/ir/ir_actions.py +++ b/openerp/addons/base/ir/ir_actions.py @@ -272,7 +272,8 @@ class act_window(osv.osv): dic = { 'active_model' : context.get('active_model', None), 'active_id' : context.get('active_id', None), - 'active_ids' : context.get('active_ids', None) + 'active_ids' : context.get('active_ids', None), + 'uid' : uid, } for res in results: if res.get('res_model', False): From bfcbb3f6198220e83a45b5d71ea6e8a07a8e288d Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Tue, 5 Feb 2013 17:10:02 +0100 Subject: [PATCH 040/388] [IMP] crm: dynamic_help bzr revid: chm@openerp.com-20130205161002-3dxect9a9x43852z --- addons/crm/crm_lead.py | 24 ++++++++++++++++++++++++ addons/project/project.py | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py index 4455663ca9a..d675753bcb2 100644 --- a/addons/crm/crm_lead.py +++ b/addons/crm/crm_lead.py @@ -84,6 +84,30 @@ class crm_lead(base_stage, format_address, osv.osv): }, } + def dynamic_help(self, cr, uid, help, context=None): + alias_txt = "" + if context.get('default_section_id'): + project_id = self.pool.get('crm.case.section').browse(cr, uid, context.get('default_section_id'), context=context) + alias = project_id.alias_id and project_id.alias_id.name_get() or False + if alias and alias[0] and alias[0][1]: + alias_txt = alias[0][1] + else: + model_id = self.pool.get('ir.model').search(cr, uid, [("model", "=", self._name)], context=context)[0] + alias_obj = self.pool.get('mail.alias') + alias_nb = 0 + alias_ids = alias_obj.search(cr, uid, [("alias_model_id", "=", model_id)], context=context, limit=5) + if alias_ids: + for alias in alias_obj.browse(cr, uid, alias_ids, context=context): + email = "%s@%s" % (alias.alias_name, alias.alias_domain) + alias_txt = "%s%s%s" % (alias_txt, (alias_nb and ", " or " "), email) + alias_nb += 1 + if alias_txt: + if context.get('default_type', False) == "opportunity": + help = "%s %s" % (help, _("
You can also create opportunities by sending an email to: %s
" % alias_txt)) + else: + help = "%s %s" % (help, _("
You can also create lead by sending an email to: %s
" % alias_txt)) + return help + def create(self, cr, uid, vals, context=None): if context is None: context = {} diff --git a/addons/project/project.py b/addons/project/project.py index 244def53c47..91dfc858113 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -908,7 +908,7 @@ class task(base_stage, osv.osv): alias_txt = "%s%s%s" % (alias_txt, (alias_nb and ", " or " "), email) alias_nb += 1 if alias_txt: - help = "%s %s" % (help, _("
You can also create documents by sending an email to: %s
" % alias_txt)) + help = "%s %s" % (help, _("
You can also create tasks by sending an email to: %s
" % alias_txt)) return help # ---------------------------------------- From b76f4c7a4553ed6ebf62a5fdc01c687a62ca49af Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 6 Feb 2013 10:44:14 +0100 Subject: [PATCH 041/388] [IMP] salesteams: add sales order and quotation bzr revid: chm@openerp.com-20130206094414-8f7kp19dam6su991 --- addons/crm/crm.py | 12 ++--- addons/crm/crm_lead.py | 27 +++--------- addons/crm/crm_salesteams.xml | 12 ++--- addons/crm/static/src/css/crm.css | 4 ++ addons/mail/mail_thread.py | 26 +++++++++++ addons/project/project.py | 26 +++-------- addons/sale/sale_view.xml | 1 + addons/sale_crm/sale_crm.py | 21 +++++++++ addons/sale_crm/sale_crm_view.xml | 73 +++++++++++++++++++++++++++++++ 9 files changed, 148 insertions(+), 54 deletions(-) diff --git a/addons/crm/crm.py b/addons/crm/crm.py index 9fa6b6281f7..c00b5ff2597 100644 --- a/addons/crm/crm.py +++ b/addons/crm/crm.py @@ -109,17 +109,17 @@ class crm_case_section(osv.osv): def get_full_name(self, cr, uid, ids, field_name, arg, context=None): return dict(self.name_get(cr, uid, ids, context=context)) - def get_number_leads(self, cr, uid, section_ids, field_name, arg, context=None): - res = dict.fromkeys(section_ids, 0) + def get_number_leads(self, cr, uid, ids, field_name, arg, context=None): + res = dict.fromkeys(ids, 0) lead_obj = self.pool.get('crm.lead') - for section_id in section_ids: + for section_id in ids: res[section_id] = lead_obj.search(cr, uid, [("section_id", "=", section_id), '|', '|', ("type", "=", "lead"), ("type", "=", "both"), ("type", "=", False), ('state', 'not in', ['done', 'cancel'])], count=True, context=context) return res - def get_number_opportunities(self, cr, uid, section_ids, field_name, arg, context=None): - res = dict.fromkeys(section_ids, 0) + def get_number_opportunities(self, cr, uid, ids, field_name, arg, context=None): + res = dict.fromkeys(ids, 0) lead_obj = self.pool.get('crm.lead') - for section_id in section_ids: + for section_id in ids: res[section_id] = lead_obj.search(cr, uid, [("section_id", "=", section_id), '|', ("type", "=", "opportunity"), ("type", "=", "both"), ('state', 'not in', ['done', 'cancel'])], context=context, count=True) return res diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py index d675753bcb2..20d9339ede5 100644 --- a/addons/crm/crm_lead.py +++ b/addons/crm/crm_lead.py @@ -85,28 +85,11 @@ class crm_lead(base_stage, format_address, osv.osv): } def dynamic_help(self, cr, uid, help, context=None): - alias_txt = "" - if context.get('default_section_id'): - project_id = self.pool.get('crm.case.section').browse(cr, uid, context.get('default_section_id'), context=context) - alias = project_id.alias_id and project_id.alias_id.name_get() or False - if alias and alias[0] and alias[0][1]: - alias_txt = alias[0][1] - else: - model_id = self.pool.get('ir.model').search(cr, uid, [("model", "=", self._name)], context=context)[0] - alias_obj = self.pool.get('mail.alias') - alias_nb = 0 - alias_ids = alias_obj.search(cr, uid, [("alias_model_id", "=", model_id)], context=context, limit=5) - if alias_ids: - for alias in alias_obj.browse(cr, uid, alias_ids, context=context): - email = "%s@%s" % (alias.alias_name, alias.alias_domain) - alias_txt = "%s%s%s" % (alias_txt, (alias_nb and ", " or " "), email) - alias_nb += 1 - if alias_txt: - if context.get('default_type', False) == "opportunity": - help = "%s %s" % (help, _("
You can also create opportunities by sending an email to: %s
" % alias_txt)) - else: - help = "%s %s" % (help, _("
You can also create lead by sending an email to: %s
" % alias_txt)) - return help + if context.get('default_type', None) == 'lead': + context['dynamic_help_model'] = 'crm.case.section' + context['dynamic_help_id'] = context.get('default_section_id', None) + context['dynamic_help_documents'] = _("leads") + return super(crm_lead, self).dynamic_help(cr, uid, help, context=context) def create(self, cr, uid, vals, context=None): if context is None: diff --git a/addons/crm/crm_salesteams.xml b/addons/crm/crm_salesteams.xml index 9a76c98a985..3c55f0198f7 100644 --- a/addons/crm/crm_salesteams.xml +++ b/addons/crm/crm_salesteams.xml @@ -51,7 +51,7 @@ kanban,tree,graph,form,calendar [('type','=','opportunity')] - + { 'search_default_section_id': [active_id], 'default_section_id': active_id, 'stage_type': 'opportunity', 'default_type': 'opportunity', 'default_user_id': uid } @@ -120,12 +120,12 @@ %%
diff --git a/addons/crm/static/src/css/crm.css b/addons/crm/static/src/css/crm.css index e9f7abfa7ae..a263393e8fa 100644 --- a/addons/crm/static/src/css/crm.css +++ b/addons/crm/static/src/css/crm.css @@ -36,4 +36,8 @@ .oe_kanban_crm_salesteams_alias small { display: block; margin-left: 20px; +} + +.oe_kanban_crm_salesteams_list a { + white-space: nowrap; } \ No newline at end of file diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index d75a9199369..27ca09136d6 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -35,6 +35,7 @@ from openerp import SUPERUSER_ID from openerp.addons.mail.mail_message import decode from openerp.osv import fields, osv from openerp.tools.safe_eval import safe_eval as eval +from openerp.tools.translate import _ _logger = logging.getLogger(__name__) @@ -88,6 +89,31 @@ class mail_thread(osv.AbstractModel): # :param function lambda: returns whether the tracking should record using this subtype _track = {} + def dynamic_help(self, cr, uid, help, context=None): + if not context.get('dynamic_help_model', None): + return help + + alias_txt = "" + if context.get('dynamic_help_id', None): + object_id = self.pool.get(context.get('dynamic_help_model')).browse(cr, uid, context.get('dynamic_help_id'), context=context) + alias = object_id.alias_id and object_id.alias_id.name_get() or False + if alias and alias[0] and alias[0][1]: + alias_txt = alias[0][1] + else: + model_id = self.pool.get('ir.model').search(cr, uid, [("model", "=", self._name)], context=context)[0] + alias_obj = self.pool.get('mail.alias') + alias_nb = 0 + alias_ids = alias_obj.search(cr, uid, [("alias_model_id", "=", model_id)], context=context, limit=5) + if alias_ids: + for alias in alias_obj.browse(cr, uid, alias_ids, context=context): + email = "%s@%s" % (alias.alias_name, alias.alias_domain) + alias_txt = "%s%s%s" % (alias_txt, (alias_nb and ", " or " "), email) + alias_nb += 1 + if alias_txt: + help = "%s %s" % (help, _("
You can also create %s by sending an email to: %s
" % (context.get('dynamic_help_documents', _("documents")), alias_txt))) + + return help + def _get_message_data(self, cr, uid, ids, name, args, context=None): """ Computes: - message_unread: has uid unread message for the document diff --git a/addons/project/project.py b/addons/project/project.py index 91dfc858113..a35ecfe4ece 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -891,26 +891,12 @@ class task(base_stage, osv.osv): def dynamic_help(self, cr, uid, help, context=None): - alias_txt = "" - if context.get('default_project_id'): - project_id = self.pool.get('project.project').browse(cr, uid, context.get('default_project_id'), context=context) - alias = project_id.alias_id and project_id.alias_id.name_get() or False - if alias and alias[0] and alias[0][1]: - alias_txt = alias[0][1] - else: - model_id = self.pool.get('ir.model').search(cr, uid, [("model", "=", self._name)], context=context)[0] - alias_obj = self.pool.get('mail.alias') - alias_nb = 0 - alias_ids = alias_obj.search(cr, uid, [("alias_model_id", "=", model_id)], context=context, limit=5) - if alias_ids: - for alias in alias_obj.browse(cr, uid, alias_ids, context=context): - email = "%s@%s" % (alias.alias_name, alias.alias_domain) - alias_txt = "%s%s%s" % (alias_txt, (alias_nb and ", " or " "), email) - alias_nb += 1 - if alias_txt: - help = "%s %s" % (help, _("
You can also create tasks by sending an email to: %s
" % alias_txt)) - return help - + context['dynamic_help_model'] = 'project.project' + context['dynamic_help_id'] = context.get('default_project_id', None) + context['dynamic_help_documents'] = _("tasks") + print context + return super(task, self).dynamic_help(cr, uid, help, context=context) + # ---------------------------------------- # Case management # ---------------------------------------- diff --git a/addons/sale/sale_view.xml b/addons/sale/sale_view.xml index 18fdb739923..bf5ccf8ab7b 100644 --- a/addons/sale/sale_view.xml +++ b/addons/sale/sale_view.xml @@ -340,6 +340,7 @@

+ diff --git a/addons/sale_crm/sale_crm.py b/addons/sale_crm/sale_crm.py index 1f3f85d5ed1..00a6503f70a 100644 --- a/addons/sale_crm/sale_crm.py +++ b/addons/sale_crm/sale_crm.py @@ -29,6 +29,27 @@ class sale_order(osv.osv): domain="['|',('section_id','=',section_id),('section_id','=',False), ('object_id.model', '=', 'crm.lead')]") } +class crm_case_section(osv.osv): + _inherit = 'crm.case.section' + + def get_number_saleorder(self, cr, uid, ids, field_name, arg, context=None): + res = dict.fromkeys(ids, 0) + obj = self.pool.get('sale.order') + for section_id in ids: + res[section_id] = obj.search(cr, uid, [("section_id", "=", section_id), ('state','not in',('draft','sent','cancel'))], context=context, count=True) + return res + + def get_number_quotation(self, cr, uid, ids, field_name, arg, context=None): + res = dict.fromkeys(ids, 0) + obj = self.pool.get('sale.order') + for section_id in ids: + res[section_id] = obj.search(cr, uid, [("section_id", "=", section_id), ('state','in',('draft','sent','cancel'))], context=context, count=True) + return res + + _columns = { + 'number_saleorder': fields.function(get_number_saleorder, type='integer', readonly=True), + 'number_quotation': fields.function(get_number_quotation, type='integer', readonly=True), + } class res_users(osv.Model): _inherit = 'res.users' diff --git a/addons/sale_crm/sale_crm_view.xml b/addons/sale_crm/sale_crm_view.xml index 0b5fce2f5cd..4c96e8b2cc5 100644 --- a/addons/sale_crm/sale_crm_view.xml +++ b/addons/sale_crm/sale_crm_view.xml @@ -113,5 +113,78 @@ + + + + Sales Orders + ir.actions.act_window + sale.order + form + tree,form,calendar,graph + + [('state','not in',('draft','sent','cancel'))] + { + 'search_default_section_id': [active_id], 'default_section_id': active_id + } + +

+ Click to create a quotation that can be converted into a sales + order. +

+ OpenERP will help you efficiently handle the complete sales flow: + quotation, sales order, delivery, invoicing and payment. +

+
+
+ + + Quotations + ir.actions.act_window + sale.order + form + + tree,form,calendar,graph + { + 'search_default_section_id': [active_id], 'default_section_id': active_id, 'show_address': 1 + } + [('state','in',('draft','sent','cancel'))] + + +

+ Click to create a quotation, the first step of a new sale. +

+ OpenERP will help you handle efficiently the complete sale flow: + from the quotation to the sales order, the + delivery, the invoicing and the payment collection. +

+ The social feature helps you organize discussions on each sales + order, and allow your customers to keep track of the evolution + of the sales order. +

+
+
+ + + crm.case.section.kanban + crm.case.section + + + + + + + + + + + QuotationQuotations + + + Sales OrderSales Orders + + + + + From 0c4a6566399121699d3ee7aedae660a53163ad8a Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 6 Feb 2013 12:57:36 +0100 Subject: [PATCH 042/388] [IMP] salesteams: add account, crm: on_change user_id, change the salesteams bzr revid: chm@openerp.com-20130206115736-fw3coo0u50itvjlq --- addons/crm/crm.py | 22 +++++++++++----------- addons/crm/crm_lead.py | 7 +++++++ addons/crm/crm_lead_view.xml | 4 ++-- addons/crm/crm_salesteams.xml | 8 +++++--- addons/crm/static/src/css/crm.css | 2 +- addons/sale_crm/sale_crm.py | 24 ++++++++++-------------- addons/sale_crm/sale_crm_view.xml | 15 +++++++++++++++ 7 files changed, 51 insertions(+), 31 deletions(-) diff --git a/addons/crm/crm.py b/addons/crm/crm.py index c00b5ff2597..471ba1613d8 100644 --- a/addons/crm/crm.py +++ b/addons/crm/crm.py @@ -109,19 +109,18 @@ class crm_case_section(osv.osv): def get_full_name(self, cr, uid, ids, field_name, arg, context=None): return dict(self.name_get(cr, uid, ids, context=context)) - def get_number_leads(self, cr, uid, ids, field_name, arg, context=None): + def get_number_items(self, cr, uid, ids, model, domain, context=None): res = dict.fromkeys(ids, 0) - lead_obj = self.pool.get('crm.lead') + obj = self.pool.get(model) for section_id in ids: - res[section_id] = lead_obj.search(cr, uid, [("section_id", "=", section_id), '|', '|', ("type", "=", "lead"), ("type", "=", "both"), ("type", "=", False), ('state', 'not in', ['done', 'cancel'])], count=True, context=context) + res[section_id] = obj.search(cr, uid, [("section_id", "=", section_id)] + domain, count=True, context=context) return res - def get_number_opportunities(self, cr, uid, ids, field_name, arg, context=None): - res = dict.fromkeys(ids, 0) - lead_obj = self.pool.get('crm.lead') - for section_id in ids: - res[section_id] = lead_obj.search(cr, uid, [("section_id", "=", section_id), '|', ("type", "=", "opportunity"), ("type", "=", "both"), ('state', 'not in', ['done', 'cancel'])], context=context, count=True) - return res + def _get_number_leads(self, cr, uid, ids, field_name, arg, context=None): + return self.get_number_items(cr, uid, ids, 'crm.lead', ['|', '|', ("type", "=", "lead"), ("type", "=", "both"), ("type", "=", False), ('state', 'not in', ['done', 'cancel'])], context=context) + + def _get_number_opportunities(self, cr, uid, ids, field_name, arg, context=None): + return self.get_number_items(cr, uid, ids, 'crm.lead', ['|', ("type", "=", "opportunity"), ("type", "=", "both"), ('state', 'not in', ['done', 'cancel'])], context=context) _columns = { 'name': fields.char('Sales Team', size=64, required=True, translate=True), @@ -142,8 +141,9 @@ class crm_case_section(osv.osv): 'alias_id': fields.many2one('mail.alias', 'Alias', ondelete="cascade", required=True, help="The email address associated with this team. New emails received will automatically " "create new leads assigned to the team."), - 'number_lead': fields.function(get_number_leads, type='integer', readonly=True), - 'number_opportunity': fields.function(get_number_opportunities, type='integer', readonly=True), + 'number_lead': fields.function(_get_number_leads, type='integer', readonly=True), + 'number_opportunity': fields.function(_get_number_opportunities, type='integer', readonly=True), + 'color': fields.integer('Color Index'), } def _get_stage_common(self, cr, uid, context): diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py index aec5e353d48..3f23284f03a 100644 --- a/addons/crm/crm_lead.py +++ b/addons/crm/crm_lead.py @@ -90,6 +90,13 @@ class crm_lead(base_stage, format_address, osv.osv): context['dynamic_help_documents'] = _("leads") return super(crm_lead, self).dynamic_help(cr, uid, help, context=context) + def onchange_user_id(self, cr, uid, ids, section_id, user_id, context=None): + if user_id: + section_ids = self.pool.get('crm.case.section').search(cr, uid, ['|', ('user_id', '=', user_id), ('member_ids', '=', user_id)], context=context) + if section_ids and (not section_id or section_id not in section_ids): + section_id = section_ids[0] + return {'value': {'section_id': section_id}} + def create(self, cr, uid, vals, context=None): if context is None: context = {} diff --git a/addons/crm/crm_lead_view.xml b/addons/crm/crm_lead_view.xml index 3e9249aa6fa..3f5c5449f87 100644 --- a/addons/crm/crm_lead_view.xml +++ b/addons/crm/crm_lead_view.xml @@ -152,7 +152,7 @@ --> - +