diff --git a/addons/base_calendar/base_calendar.py b/addons/base_calendar/base_calendar.py index 4c4e7a16876..9cf07a4b73e 100644 --- a/addons/base_calendar/base_calendar.py +++ b/addons/base_calendar/base_calendar.py @@ -88,6 +88,16 @@ def base_calendar_id2real_id(base_calendar_id=None, with_date=False): return base_calendar_id and int(base_calendar_id) or base_calendar_id +def get_real_ids(ids): + if isinstance(ids, (str, int, long)): + return base_calendar_id2real_id(ids) + + if isinstance(ids, (list, tuple)): + res = [] + for id in ids: + res.append(base_calendar_id2real_id(id)) + return res + def real_id2base_calendar_id(real_id, recurrent_date): """ Convert a real event id (type int) into a "virtual/recurring event id" (type string). @@ -966,13 +976,13 @@ class calendar_event(osv.osv): def unlink_events(self, cr, uid, ids, context=None): """ - This function deletes event which are linked with the event with recurrent_uid + This function deletes event which are linked with the event with recurrent_id (Removes the events which refers to the same UID value) """ if context is None: context = {} for event_id in ids: - cr.execute("select id from %s where recurrent_uid=%%s" % (self._table), (event_id,)) + cr.execute("select id from %s where recurrent_id=%%s" % (self._table), (event_id,)) r_ids = map(lambda x: x[0], cr.fetchall()) self.unlink(cr, uid, r_ids, context=context) return True @@ -1050,8 +1060,8 @@ rule or repeating pattern of time to exclude from the recurring rule."), 'alarm_id': fields.many2one('res.alarm', 'Reminder', states={'done': [('readonly', True)]}, help="Set an alarm at this time, before the event occurs" ), 'base_calendar_alarm_id': fields.many2one('calendar.alarm', 'Alarm'), - 'recurrent_uid': fields.integer('Recurrent ID'), - 'recurrent_id': fields.datetime('Recurrent ID date'), + 'recurrent_id': fields.integer('Recurrent ID'), + 'recurrent_id_date': fields.datetime('Recurrent ID date'), 'vtimezone': fields.selection(_tz_get, size=64, string='Timezone'), 'user_id': fields.many2one('res.users', 'Responsible', states={'done': [('readonly', True)]}), 'organizer': fields.char("Organizer", size=256, states={'done': [('readonly', True)]}), # Map with organizer attribute of VEvent. @@ -1328,16 +1338,6 @@ rule or repeating pattern of time to exclude from the recurring rule."), data['end_type'] = 'end_date' return data - def remove_virtual_id(self, ids): - if isinstance(ids, (str, int, long)): - return base_calendar_id2real_id(ids) - - if isinstance(ids, (list, tuple)): - res = [] - for id in ids: - res.append(base_calendar_id2real_id(id)) - return res - def search(self, cr, uid, args, offset=0, limit=0, order=None, context=None, count=False): context = context or {} args_without_date = [] @@ -1387,6 +1387,13 @@ rule or repeating pattern of time to exclude from the recurring rule."), return True def write(self, cr, uid, ids, vals, context=None, check=True, update_check=True): + def _only_changes_to_apply_on_real_ids(field_names): + ''' return True if changes are only to be made on the real ids''' + for field in field_names: + if field not in ['message_follower_ids']: + return False + return True + context = context or {} if isinstance(ids, (str, int, long)): ids = [ids] @@ -1398,7 +1405,11 @@ rule or repeating pattern of time to exclude from the recurring rule."), continue ids.remove(event_id) real_event_id = base_calendar_id2real_id(event_id) - if not vals.get('recurrency', True): + + # if we are setting the recurrency flag to False or if we are only changing fields that + # should be only updated on the real ID and not on the virtual (like message_follower_ids): + # then set real ids to be updated. + if not vals.get('recurrency', True) or _only_changes_to_apply_on_real_ids(vals.keys()): ids.append(real_event_id) continue @@ -1408,13 +1419,15 @@ rule or repeating pattern of time to exclude from the recurring rule."), if data.get('rrule'): data.update( vals, - recurrent_uid=real_event_id, - recurrent_id=data.get('date'), + recurrent_id=real_event_id, + recurrent_id_date=data.get('date'), rrule_type=False, rrule='', recurrency=False, ) - + #do not copy the id + if data.get('id'): + del(data['id']) new_id = self.copy(cr, uid, real_event_id, default=data, context=context) date_new = event_id.split('-')[1] @@ -1507,7 +1520,7 @@ rule or repeating pattern of time to exclude from the recurring rule."), for r in result: for k in EXTRAFIELDS: - if (k in r) and ((not fields) or (k not in fields)): + if (k in r) and (fields and (k not in fields)): del r[k] if isinstance(ids, (str, int, long)): return result and result[0] or False diff --git a/addons/base_calendar/base_calendar_view.xml b/addons/base_calendar/base_calendar_view.xml index a922521d970..e3ad980dae7 100644 --- a/addons/base_calendar/base_calendar_view.xml +++ b/addons/base_calendar/base_calendar_view.xml @@ -100,8 +100,8 @@ + - @@ -162,7 +162,7 @@ + attrs="{'readonly':[('recurrent_id','!=',False)]}"/> diff --git a/addons/base_calendar/crm_meeting.py b/addons/base_calendar/crm_meeting.py index 9ceaea671ca..4745d6c5896 100644 --- a/addons/base_calendar/crm_meeting.py +++ b/addons/base_calendar/crm_meeting.py @@ -23,9 +23,8 @@ from osv import osv, fields import tools from tools.translate import _ -import base_calendar +from base_calendar import get_real_ids, base_calendar_id2real_id from base_status.base_state import base_state - # # crm.meeting is defined here so that it may be used by modules other than crm, # without forcing the installation of crm. @@ -66,6 +65,14 @@ class crm_meeting(base_state, osv.Model): 'state': 'open', } + def message_get_subscription_data(self, cr, uid, ids, context=None): + res = {} + for virtual_id in ids: + real_id = base_calendar_id2real_id(virtual_id) + result = super(crm_meeting, self).message_get_subscription_data(cr, uid, [real_id], context=context) + res[virtual_id] = result[real_id] + return res + def copy(self, cr, uid, id, default=None, context=None): default = default or {} default['attendee_ids'] = False @@ -115,3 +122,54 @@ class crm_meeting(base_state, osv.Model): def case_close_send_note(self, cr, uid, ids, context=None): return self.message_post(cr, uid, ids, body=_("Meeting completed."), context=context) + + def message_post(self, cr, uid, thread_id, body='', subject=None, type='notification', + subtype=None, parent_id=False, attachments=None, context=None, **kwargs): + cal_event_pool = self.pool.get('calendar.event') + if isinstance(thread_id, str): + thread_id = get_real_ids(thread_id) + return super(crm_meeting, self).message_post(cr, uid, thread_id, body=body, subject=subject, type=type, subtype=subtype, parent_id=parent_id, attachments=attachments, context=context, **kwargs) + +class mail_message(osv.osv): + _inherit = "mail.message" + + def search(self, cr, uid, args, offset=0, limit=0, order=None, context=None, count=False): + ''' + convert the search on real ids in the case it was asked on virtual ids, then call super() + ''' + for index in range(len(args)): + if args[index][0] == "res_id" and isinstance(args[index][2], str): + args[index][2] = get_real_ids(args[index][2]) + return super(mail_message, self).search(cr, uid, args, offset=offset, limit=limit, order=order, context=context, count=count) + +class ir_attachment(osv.osv): + _inherit = "ir.attachment" + + def search(self, cr, uid, args, offset=0, limit=0, order=None, context=None, count=False): + ''' + convert the search on real ids in the case it was asked on virtual ids, then call super() + ''' + for index in range(len(args)): + if args[index][0] == "res_id" and isinstance(args[index][2], str): + args[index][2] = get_real_ids(args[index][2]) + return super(ir_attachment, self).search(cr, uid, args, offset=offset, limit=limit, order=order, context=context, count=count) + + def write(self, cr, uid, ids, vals, context=None): + ''' + when posting an attachment (new or not), convert the virtual ids in real ids. + ''' + if isinstance(vals.get('res_id'), str): + vals['res_id'] = get_real_ids(vals.get('res_id')) + return super(ir_attachment, self).write(cr, uid, ids, vals, context=context) + +class invite_wizard(osv.osv_memory): + _inherit = 'mail.wizard.invite' + + def default_get(self, cr, uid, fields, context=None): + ''' + in case someone clicked on 'invite others' wizard in the followers widget, transform virtual ids in real ids + ''' + result = super(invite_wizard, self).default_get(cr, uid, fields, context=context) + if 'res_id' in result: + result['res_id'] = get_real_ids(result['res_id']) + return result diff --git a/addons/base_calendar/crm_meeting_view.xml b/addons/base_calendar/crm_meeting_view.xml index ec62b24dd7c..2efc76997cc 100644 --- a/addons/base_calendar/crm_meeting_view.xml +++ b/addons/base_calendar/crm_meeting_view.xml @@ -82,8 +82,7 @@ - + diff --git a/addons/base_calendar/test/test_crm_recurrent_meeting_case2.yml b/addons/base_calendar/test/test_crm_recurrent_meeting_case2.yml index 693f0d81c6b..0fd34fdd010 100644 --- a/addons/base_calendar/test/test_crm_recurrent_meeting_case2.yml +++ b/addons/base_calendar/test/test_crm_recurrent_meeting_case2.yml @@ -11,7 +11,7 @@ duration: 1.0 name: Test Meeting recurrency: true - recurrent_uid: 0.0 + recurrent_id: 0.0 rrule_type: daily sequence: 0.0 - @@ -37,7 +37,7 @@ we: true name: Review code with programmer recurrency: true - recurrent_uid: 0.0 + recurrent_id: 0.0 rrule_type: weekly sequence: 0.0 - @@ -57,7 +57,7 @@ duration: 1.0 name: Sprint Review recurrency: true - recurrent_uid: 0.0 + recurrent_id: 0.0 rrule_type: monthly sequence: 0.0 - @@ -92,6 +92,6 @@ I check whether the record is edited perfectly or not. - !python {model: crm.meeting}: | - meeting_ids = self.search(cr, uid, [('recurrent_uid', '=', ref('crm_meeting_reviewcodewithprogrammer0')), ('recurrent_id','=','2011-04-25 12:47:00')], context) + meeting_ids = self.search(cr, uid, [('recurrent_id', '=', ref('crm_meeting_reviewcodewithprogrammer0')), ('recurrent_id_date','=','2011-04-25 12:47:00')], context) assert meeting_ids, 'Meeting is not edited !' diff --git a/addons/sale_journal/__openerp__.py b/addons/sale_journal/__openerp__.py index 30a6a281c49..b5da06419c1 100644 --- a/addons/sale_journal/__openerp__.py +++ b/addons/sale_journal/__openerp__.py @@ -51,7 +51,7 @@ Some statistics by journals are provided. 'author': 'OpenERP SA', 'website': 'http://www.openerp.com', 'images': ['images/invoice_type.jpeg'], - 'depends': ['sale'], + 'depends': ['sale_stock'], 'data': [ 'security/ir.model.access.csv', 'sale_journal_view.xml',