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 @@
-
+
@@ -129,8 +128,8 @@
+
-
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',