[IMP] Calendar: invite attendnee, add origanizer detail into meetings

bzr revid: hmo@tinyerp.com-20100713111753-i5b2vc04cpye05wq
This commit is contained in:
Harry (OpenERP) 2010-07-13 16:47:53 +05:30
parent c145066710
commit 0c3569c69f
5 changed files with 121 additions and 97 deletions

View File

@ -383,7 +383,7 @@ property or property parameter."),
'rsvp': True,
'cutype': 'individual',
}
def copy(self, cr, uid, id, default=None, context=None):
raise osv.except_osv(_('Warning!'), _('Can not Duplicate'))
@ -408,7 +408,7 @@ property or property parameter."),
except ImportError:
return res
cal = vobject.iCalendar()
event = cal.add('vevent')
event = cal.add('vevent')
event.add('created').value = ics_datetime(time.strftime('%Y-%m-%d %H:%M:%S'))
event.add('dtstart').value = ics_datetime(event_obj.date)
event.add('dtend').value = ics_datetime(event_obj.date_deadline)
@ -419,10 +419,14 @@ property or property parameter."),
event.add('location').value = event_obj.location
if event_obj.rrule:
event.add('rrule').value = event_obj.rrule
if event_obj.user_id:
if event_obj.user_id or event_obj.organizer_id:
event_org = event.add('organizer')
event_org.params['CN'] = [event_obj.user_id.name]
event_org.value = 'MAILTO:' + (event_obj.user_id.user_email or event_obj.user_id.name)
organizer = event_obj.organizer_id
if not organizer:
organizer = event_obj.user_id
event_org.params['CN'] = [organizer.name]
event_org.value = 'MAILTO:' + (organizer.user_email or organizer.name)
if event_obj.alarm_id:
# computes alarm data
valarm = event.add('valarm')
@ -455,14 +459,14 @@ property or property parameter."),
attendee_add.value = 'MAILTO:' + (attendee.email or '')
res = cal.serialize()
return res
def _send_mail(self, cr, uid, ids, mail_to, email_from=tools.config.get('email_from', False), context=None):
"""
Send mail for event invitation to event attendees.
Send mail for event invitation to event attendees.
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of attendees IDs.
@param email_from: Email address for user sending the mail
@param email_from: Email address for user sending the mail
@param context: A standard dictionary for contextual values
@return: True
"""
@ -474,7 +478,7 @@ property or property parameter."),
sign = att.sent_by_uid and att.sent_by_uid.signature or ''
sign = '<br>'.join(sign and sign.split('\n') or [])
res_obj = att.ref
sub = '[%s Invitation][%d] %s' % (company, att.id, res_obj.name)
sub = res_obj.name
att_infos = []
other_invitaion_ids = self.search(cr, uid, [('ref', '=', res_obj._name + ',' + str(res_obj.id))])
for att2 in self.browse(cr, uid, other_invitaion_ids):
@ -495,12 +499,12 @@ property or property parameter."),
if mail_to and email_from:
attach = self.get_ics_file(cr, uid, res_obj, context=context)
tools.email_send(
email_from,
mail_to,
sub,
body,
attach=attach and [('invitation.ics', attach)] or None,
subtype='html',
email_from,
mail_to,
sub,
body,
attach=attach and [('invitation.ics', attach)] or None,
subtype='html',
reply_to=email_from
)
return True
@ -528,31 +532,28 @@ property or property parameter."),
@param uid: the current users ID for security checks,
@param ids: List of calendar attendees IDs
@param *args: Get Tupple value
@param context: A standard dictionary for contextual values
@param context: A standard dictionary for contextual values
"""
return self.write(cr, uid, ids, {'state': 'tentative'}, context)
def do_accept(self, cr, uid, ids, context=None, *args):
"""
Update state of invitation as Accepted and
Update state of invitation as Accepted and
if the invited user is other then event user it will make a copy of this event for invited user
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param ids: List of calendar attendees IDs.
@param context: A standard dictionary for contextual values
@param context: A standard dictionary for contextual values
@return: True
"""
if not context:
context = {}
for vals in self.browse(cr, uid, ids, context=context):
user = vals.user_id
if user:
if vals.ref and vals.ref.user_id:
mod_obj = self.pool.get(vals.ref._name)
if vals.ref:
if vals.ref.user_id.id != user.id:
defaults = {'user_id': user.id}
new_event = mod_obj.copy(cr, uid, vals.ref.id, default=defaults, context=context)
defaults = {'user_id': vals.user_id.id, 'organizer_id': vals.ref.user_id.id}
new_event = mod_obj.copy(cr, uid, vals.ref.id, default=defaults, context=context)
self.write(cr, uid, vals.id, {'state': 'accepted'}, context)
return True
@ -565,7 +566,8 @@ property or property parameter."),
@param ids: List of calendar attendees IDs
@param *args: Get Tupple value
@param context: A standard dictionary for contextual values """
if not context:
context = {}
return self.write(cr, uid, ids, {'state': 'declined'}, context)
def create(self, cr, uid, vals, context=None):
@ -585,7 +587,6 @@ property or property parameter."),
vals['cn'] = vals.get("cn")
res = super(calendar_attendee, self).create(cr, uid, vals, context)
return res
calendar_attendee()
class res_alarm(osv.osv):
@ -654,9 +655,9 @@ true, it will allow you to hide the event alarm information without removing it.
alarm_ids = res_alarm_obj.search(cr, uid, domain, context=context)
if not alarm_ids:
val = {
'trigger_duration': duration,
'trigger_interval': interval,
'trigger_occurs': occurs,
'trigger_duration': duration,
'trigger_interval': interval,
'trigger_occurs': occurs,
'trigger_related': related,
'name': str(duration) + ' ' + str(interval) + ' ' + str(occurs)
}
@ -724,35 +725,35 @@ class calendar_alarm(osv.osv):
__attribute__ = {}
_columns = {
'alarm_id': fields.many2one('res.alarm', 'Basic Alarm', ondelete='cascade'),
'alarm_id': fields.many2one('res.alarm', 'Basic Alarm', ondelete='cascade'),
'name': fields.char('Summary', size=124, help="""Contains the text to be \
used as the message subject for email \
or contains the text to be used for display"""),
or contains the text to be used for display"""),
'action': fields.selection([('audio', 'Audio'), ('display', 'Display'), \
('procedure', 'Procedure'), ('email', 'Email') ], 'Action', \
required=True, help="Defines the action to be invoked when an alarm is triggered"),
required=True, help="Defines the action to be invoked when an alarm is triggered"),
'description': fields.text('Description', help='Provides a more complete \
description of the calendar component, than that \
provided by the "SUMMARY" property'),
provided by the "SUMMARY" property'),
'attendee_ids': fields.many2many('calendar.attendee', 'alarm_attendee_rel', \
'alarm_id', 'attendee_id', 'Attendees', readonly=True),
'alarm_id', 'attendee_id', 'Attendees', readonly=True),
'attach': fields.binary('Attachment', help="""* Points to a sound resource,\
which is rendered when the alarm is triggered for audio,
* File which is intended to be sent as message attachments for email,
* Points to a procedure resource, which is invoked when\
the alarm is triggered for procedure."""),
'res_id': fields.integer('Resource ID'),
'model_id': fields.many2one('ir.model', 'Model'),
'user_id': fields.many2one('res.users', 'Owner'),
'event_date': fields.datetime('Event Date'),
'event_end_date': fields.datetime('Event End Date'),
'trigger_date': fields.datetime('Trigger Date', readonly="True"),
the alarm is triggered for procedure."""),
'res_id': fields.integer('Resource ID'),
'model_id': fields.many2one('ir.model', 'Model'),
'user_id': fields.many2one('res.users', 'Owner'),
'event_date': fields.datetime('Event Date'),
'event_end_date': fields.datetime('Event End Date'),
'trigger_date': fields.datetime('Trigger Date', readonly="True"),
'state':fields.selection([
('draft', 'Draft'),
('run', 'Run'),
('stop', 'Stop'),
('done', 'Done'),
], 'State', select=True, readonly=True),
('draft', 'Draft'),
('run', 'Run'),
('stop', 'Stop'),
('done', 'Done'),
], 'State', select=True, readonly=True),
}
_defaults = {
@ -801,7 +802,7 @@ class calendar_alarm(osv.osv):
current_datetime = datetime.now()
request_obj = self.pool.get('res.request')
alarm_ids = self.search(cr, uid, [('state', '!=', 'done')], context=context)
mail_to = []
for alarm in self.browse(cr, uid, alarm_ids, context=context):
@ -916,10 +917,10 @@ class calendar_event(osv.osv):
return {}
event = self.browse(cr, uid, ids, context=context)[0]
value = {
'duration': 24
'duration': 24
}
return {'value': value}
def onchange_dates(self, cr, uid, ids, start_date, duration=False, end_date=False, allday=False, context=None):
"""Returns duration and/or end date based on values passed
@param self: The object pointer
@ -1082,11 +1083,11 @@ class calendar_event(osv.osv):
'duration': fields.float('Duration', states={'done': [('readonly', True)]}),
'description': fields.text('Description', states={'done': [('readonly', True)]}),
'class': fields.selection([('public', 'Public'), ('private', 'Private'), \
('confidential', 'Confidential')], 'Mark as', states={'done': [('readonly', True)]}),
'location': fields.char('Location', size=264, help="Location of Event", states={'done': [('readonly', True)]}),
('confidential', 'Confidential')], 'Mark as', states={'done': [('readonly', True)]}),
'location': fields.char('Location', size=264, help="Location of Event", states={'done': [('readonly', True)]}),
'show_as': fields.selection([('free', 'Free'), ('busy', 'Busy')], \
'Show as', states={'done': [('readonly', True)]}),
'base_calendar_url': fields.char('Caldav URL', size=264),
'base_calendar_url': fields.char('Caldav URL', size=264),
'state': fields.selection([('tentative', 'Tentative'),
('confirmed', 'Confirmed'),
('cancelled', 'Cancelled')], 'State', readonly=True),
@ -1110,6 +1111,7 @@ e.g.: Every other month on the last Sunday of the month for 10 occurrences:\
'vtimezone': fields.related('user_id', 'context_tz', type='char', size=24, \
string='Timezone', store=True),
'user_id': fields.many2one('res.users', 'Responsible', states={'done': [('readonly', True)]}),
'organizer_id': fields.many2one('res.users', 'Organizer', states={'done': [('readonly', True)]}),
'freq': fields.selection([('None', 'No Repeat'), \
('secondly', 'Secondly'), \
('minutely', 'Minutely'), \
@ -1136,25 +1138,27 @@ e.g.: Every other month on the last Sunday of the month for 10 occurrences:\
('SU', 'Sunday')], 'Weekday'),
'byday': fields.selection([('1', 'First'), ('2', 'Second'), \
('3', 'Third'), ('4', 'Fourth'), \
('5', 'Fifth'), ('-1', 'Last')], 'By day'),
'month_list': fields.selection(months.items(), 'Month'),
'end_date': fields.date('Repeat Until'),
('5', 'Fifth'), ('-1', 'Last')], 'By day'),
'month_list': fields.selection(months.items(), 'Month'),
'end_date': fields.date('Repeat Until'),
'attendee_ids': fields.many2many('calendar.attendee', 'event_attendee_rel', \
'event_id', 'attendee_id', 'Attendees'),
'allday': fields.boolean('All Day', states={'done': [('readonly', True)]}),
'event_id', 'attendee_id', 'Attendees'),
'allday': fields.boolean('All Day', states={'done': [('readonly', True)]}),
'active': fields.boolean('Active', help="If the active field is set to \
true, it will allow you to hide the event alarm information without removing it.")
}
_defaults = {
'state': 'tentative',
'state': 'tentative',
'class': 'public',
'show_as': 'busy',
'freq': 'None',
'select1': 'date',
'interval': 1,
'active': 1,
}
'user_id': lambda self, cr, uid, ctx: uid,
'organizer_id': lambda self, cr, uid, ctx: uid,
}
def open_event(self, cr, uid, ids, context=None):
"""
@ -1183,26 +1187,26 @@ true, it will allow you to hide the event alarm information without removing it.
id4 = data_obj.browse(cr, uid, id4, context=context).res_id
for id in ids:
value = {
'name': _('Event'),
'view_type': 'form',
'view_mode': 'form,tree',
'res_model': 'calendar.event',
'view_id': False,
'views': [(id2, 'form'), (id3, 'tree'), (id4, 'calendar')],
'type': 'ir.actions.act_window',
'res_id': base_calendar_id2real_id(id),
'name': _('Event'),
'view_type': 'form',
'view_mode': 'form,tree',
'res_model': 'calendar.event',
'view_id': False,
'views': [(id2, 'form'), (id3, 'tree'), (id4, 'calendar')],
'type': 'ir.actions.act_window',
'res_id': base_calendar_id2real_id(id),
'nodestroy': True
}
return value
def modify_this(self, cr, uid, event_id, defaults, real_date, context=None, *args):
"""Modifies only one event record out of virtual recurrent events
"""Modifies only one event record out of virtual recurrent events
and creates new event as a specific instance of a Recurring Event",
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param event_id: Id of Recurring Event
@param event_id: Id of Recurring Event
@param real_date: Date of event recurrence that is being modified
@param context: A standard dictionary for contextual values
@param *args: Get Tupple Value
@ -1225,7 +1229,7 @@ true, it will allow you to hide the event alarm information without removing it.
def modify_all(self, cr, uid, event_ids, defaults, context=None, *args):
"""
Modifies the recurring event
Modifies the recurring event
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@param event_ids: List of crm meetings IDs.
@ -1252,7 +1256,7 @@ true, it will allow you to hide the event alarm information without removing it.
def get_recurrent_ids(self, cr, uid, select, base_start_date, base_until_date, limit=100):
"""Gives virtual event ids for recurring events based on value of Recurrence Rule
This method gives ids of dates that comes between start date and end date of calendar views
This method gives ids of dates that comes between start date and end date of calendar views
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current users ID for security checks,
@ -1418,8 +1422,7 @@ true, it will allow you to hide the event alarm information without removing it.
until_date = arg[2]
res = super(calendar_event, self).search(cr, uid, args_without_date, \
offset, limit, order, context, count)
#Search Event ID which are invitted
return self.get_recurrent_ids(cr, uid, res, start_date, until_date, limit)
@ -1558,7 +1561,7 @@ true, it will allow you to hide the event alarm information without removing it.
event_id = [int(event_id)]
for record in self.read(cr, uid, event_id, ['date', 'rrule', 'exdate']):
if record['rrule']:
# Remove one of the recurrent event
# Remove one of the recurrent event
date_new = time.strftime("%Y-%m-%d %H:%M:%S", \
time.strptime(date_new, "%Y%m%d%H%M%S"))
exdate = (record['exdate'] and (record['exdate'] + ',') or '') + ''.join((re.compile('\d')).findall(date_new)) + 'Z'
@ -1584,7 +1587,7 @@ true, it will allow you to hide the event alarm information without removing it.
alarm_obj = self.pool.get('res.alarm')
alarm_obj.do_alarm_create(cr, uid, [res], self._name, 'date', context=context)
return res
def do_tentative(self, cr, uid, ids, context=None, *args):
""" Makes event invitation as Tentative
@param self: The object pointer
@ -1592,10 +1595,10 @@ true, it will allow you to hide the event alarm information without removing it.
@param uid: the current users ID for security checks,
@param ids: List of Event IDs
@param *args: Get Tupple value
@param context: A standard dictionary for contextual values
@param context: A standard dictionary for contextual values
"""
return self.write(cr, uid, ids, {'state': 'tentative'}, context)
def do_cancel(self, cr, uid, ids, context=None, *args):
""" Makes event invitation as Tentative
@param self: The object pointer
@ -1603,7 +1606,7 @@ true, it will allow you to hide the event alarm information without removing it.
@param uid: the current users ID for security checks,
@param ids: List of Event IDs
@param *args: Get Tupple value
@param context: A standard dictionary for contextual values
@param context: A standard dictionary for contextual values
"""
return self.write(cr, uid, ids, {'state': 'cancelled'}, context)
@ -1614,7 +1617,7 @@ true, it will allow you to hide the event alarm information without removing it.
@param uid: the current users ID for security checks,
@param ids: List of Event IDs
@param *args: Get Tupple value
@param context: A standard dictionary for contextual values
@param context: A standard dictionary for contextual values
"""
return self.write(cr, uid, ids, {'state': 'confirmed'}, context)
@ -1758,9 +1761,9 @@ class ir_model(osv.osv):
_inherit = 'ir.model'
def read(self, cr, uid, ids, fields=None, context=None,
def read(self, cr, uid, ids, fields=None, context=None,
load='_classic_read'):
"""
"""
Overrides orm read method.
@param self: The object pointer
@param cr: the current row, from the database cursor,
@ -1807,7 +1810,7 @@ class res_users(osv.osv):
_inherit = 'res.users'
def _get_user_avail(self, cr, uid, ids, context=None):
"""
"""
Get User Availability
@param self: The object pointer
@param cr: the current row, from the database cursor,
@ -1838,7 +1841,7 @@ class res_users(osv.osv):
return res
def _get_user_avail_fun(self, cr, uid, ids, name, args, context=None):
"""
"""
Get User Availability Function
@param self: The object pointer
@param cr: the current row, from the database cursor,

View File

@ -1,7 +1,7 @@
<?xml version="1.0"?>
<openerp>
<data noupdate="1">
<record model="document.directory" id="document.dir_calendars">
<field name="name">Calendars</field>
<field name="calendar_collection">True</field>
@ -14,6 +14,11 @@
<field name="type">vevent</field>
</record>
<record model="basic.calendar.attributes" id="field_event_organizer">
<field name="name">organizer</field>
<field name="type">vevent</field>
</record>
<record model="basic.calendar.attributes" id="field_event_uid">
<field name="name">uid</field>
<field name="type">vevent</field>
@ -58,12 +63,12 @@
<field name="name">valarm</field>
<field name="type">vevent</field>
</record>
<record model="basic.calendar.attributes" id="field_event_vtimezone">
<field name="name">vtimezone</field>
<field name="type">vevent</field>
</record>
<record model="basic.calendar.attributes" id="field_event_priority">
<field name="name">priority</field>
<field name="type">vevent</field>
@ -181,12 +186,12 @@
<field name="name">seq</field>
<field name="type">vtodo</field>
</record>
<record model="basic.calendar.attributes" id="field_todo_vtimezone">
<field name="name">vtimezone</field>
<field name="type">vtodo</field>
</record>
<record model="basic.calendar.attributes" id="field_todo_url">
<field name="name">url</field>
<field name="type">vtodo</field>

View File

@ -228,6 +228,8 @@ class CalDAV(object):
att_data = []
for cal_data in child.getChildren():
if cal_data.name.lower() == 'organizer':
self.ical_set(cal_data.name.lower(), {'name':cal_data.params['CN']}, 'value')
if cal_data.name.lower() == 'attendee':
ctx = context.copy()
if cal_children:
@ -307,6 +309,13 @@ class CalDAV(object):
ical = tz_obj.export_cal(cr, uid, None, \
data[map_field], ical, context=context)
timezones.append(data[map_field])
elif field == 'organizer' and data[map_field]:
event_org = vevent.add('organizer')
organizer_id = data[map_field][0]
user_obj = self.pool.get('res.users')
organizer = user_obj.browse(cr, uid, organizer_id, context=context)
event_org.params['CN'] = [organizer.name]
event_org.value = 'MAILTO:' + (organizer.user_email or organizer.name)
elif data[map_field]:
if map_type in ("char", "text"):
if field in ('exdate'):
@ -528,7 +537,6 @@ class Calendar(CalDAV, osv.osv):
})
self.__attribute__ = get_attribute_mapping(cr, uid, child.name.lower(), context=context)
val = self.parse_ics(cr, uid, child, cal_children=cal_children, context=context)
val.update({'user_id': uid})
vals.append(val)
obj = self.pool.get(cal_children[child.name.lower()])
if hasattr(obj, 'check_import'):

View File

@ -107,6 +107,7 @@
<group col="2" colspan="2">
<separator colspan="2" string="Assignment"/>
<field name="user_id" />
<field name="organizer_id" groups="base.group_extended"/>
<field name="section_id" widget="selection"
groups="base.group_extended"/>
</group><group col="2" colspan="2">
@ -344,7 +345,7 @@
</field>
</field>
</record>
</data>
</openerp>

View File

@ -1,6 +1,6 @@
<?xml version="1.0"?>
<openerp>
<data noupdate="1">
<data noupdate="1">
<!-- Event Attribute mapping for Calendar-->
@ -22,13 +22,20 @@
<field name="calendar_id" ref="caldav.basic_calendar1" />
<field name="object_id" search="[('model','=','calendar.alarm')]" />
</record>
<record model="basic.calendar.lines" id="base_calendar.calendar_lines_attendee">
<field name="name">attendee</field>
<field name="calendar_id" ref="caldav.basic_calendar1" />
<field name="object_id" search="[('model','=','calendar.attendee')]" />
</record>
<record model="basic.calendar.fields" id="map_event_0">
<field name="name" ref="caldav.field_event_organizer"/>
<field name="type_id" ref="base_calendar.calendar_lines_event" />
<field name="field_id" search="[('name','=','organizer_id'),('model_id.model','=','calendar.event')]" />
<field name="fn">field</field>
</record>
<record model="basic.calendar.fields" id="map_event_1">
<field name="name" ref="caldav.field_event_uid"/>
<field name="type_id" ref="base_calendar.calendar_lines_event" />
@ -42,7 +49,7 @@
<field name="field_id" search="[('name','=','recurrent_id'),('model_id.model','=','calendar.event')]" />
<field name="fn">field</field>
</record>
<record model="basic.calendar.fields" id="map_event_3">
<field name="name" ref="caldav.field_event_vtimezone"/>
<field name="type_id" ref="base_calendar.calendar_lines_event" />
@ -55,7 +62,7 @@
<field name="type_id" ref="base_calendar.calendar_lines_event" />
<field name="field_id" search="[('name','=','attendee_ids'),('model_id.model','=','crm.meeting')]" />
<field name="fn">field</field>
</record>
</record>
<record model="basic.calendar.fields" id="map_event_5">
<field name="name" ref="caldav.field_event_rrule"/>
@ -154,7 +161,7 @@
<field name="type_id" ref="base_calendar.calendar_lines_event" />
<field name="field_id" search="[('name','=','name'),('model_id.model','=','calendar.event')]" />
<field name="fn">field</field>
</record>
</record>
@ -313,7 +320,7 @@
<field name="fn">field</field>
</record>
</data>
</openerp>