[IMP]: caldav, crm: Implemented maintanence of event data in attendee invitation + Improvements

bzr revid: rpa@openerp.co.in-20100108102850-0pqnfppm73fxz8s0
This commit is contained in:
rpa (Open ERP)
2010-01-08 15:58:50 +05:30
parent 0e4457b63b
commit 8fe7d4c0a7
3 changed files with 127 additions and 89 deletions
+16 -8
View File
@@ -14,7 +14,8 @@
<newline/>
<field name="user_id" select="1" on_change="onchange_user_id(user_id)"/>
<field name="email" />
<field name="role" select="1" />
<field name="role"/>
<field name="cutype"/>
<field name="rsvp" />
<separator string="" colspan="6" />
<label string="" colspan="2"/>
@@ -39,24 +40,31 @@
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Atendee details">
<field name="user_id" on_change="onchange_user_id(user_id)" />
<field name="email" select="1"/>
<field name="user_id"
on_change="onchange_user_id(user_id)" readonly="1" />
<field name="email" select="1" readonly="1" />
<newline />
<field name="role" select="1" />
<field name="cutype" select="1" />
<field name="role" select="1" readonly="1" string="Role" />
<field name="cutype" select="1" readonly="1" string="Invitation type" />
<newline />
<field name="rsvp" />
<field name="rsvp" readonly="1" />
<notebook colspan="4">
<page string="Details">
<field name="date" />
<newline />
<field name="sent_by_uid" />
<field name="dir" widget='url' />
<field name="language" />
<newline />
<field name="reference" colspan="4" />
</page>
<page string="Delegation Info">
<separator string="Delegated to" colspan="4" />
<field name="del_to_user_ids" nolabel="1" colspan="4" />
<field name="del_to_user_ids" nolabel="1"
colspan="4" readonly="1" />
<separator string="Delegated from" colspan="4" />
<field name="del_from_user_ids" nolabel="1" colspan="4" />
<field name="del_from_user_ids" nolabel="1"
colspan="4" readonly="1" />
</page>
</notebook>
<group col="6" colspan="4">
+110 -80
View File
@@ -43,7 +43,7 @@ def caldav_id2real_id(caldav_id = None, with_date=False):
return int(real_id)
return caldav_id and int(caldav_id) or caldav_id
def real_id2caldav_id(real_id, recurrent_date):
def real_id2caldav_id(real_id, recurrent_date):
if real_id and recurrent_date:
recurrent_date = time.strftime("%Y%m%d%H%M%S", \
time.strptime(recurrent_date, "%Y-%m-%d %H:%M:%S"))
@@ -64,7 +64,7 @@ def uid2openobjectid(cr, uidval, oomodel):
if id in ids:
return id
return False
def openobjectid2uid(cr, uidval, oomodel):
value = 'OpenObject-%s_%s@%s' % (oomodel, uidval, cr.dbname)
return value
@@ -87,12 +87,12 @@ class calendar_attendee(osv.osv):
'dir': {'field':'dir', 'type':'text'},
'language': {'field':'language', 'type':'text'},
}
def _get_address(self, name=None, email=None):
if name and email:
name += ':'
return (name or '') + (email and ('MAILTO:' + email) or '')
def _compute_data(self, cr, uid, ids, name, arg, context):
name = name[0]
result = {}
@@ -110,7 +110,7 @@ class calendar_attendee(osv.osv):
continue
else:
result[id][name] = self._get_address(attdata.sent_by_uid.name, \
attdata.sent_by_uid.address_id.email)
attdata.sent_by_uid.address_id.email)
if name == 'cn':
result[id][name] = self._get_address(attdata.user_id.name, attdata.email)
if name == 'delegated_to':
@@ -122,8 +122,21 @@ class calendar_attendee(osv.osv):
user_obj = self.pool.get('res.users')
fromdata = map(get_delegate_data, attdata.del_from_user_ids)
result[id][name] = ', '.join(fromdata)
return result
return result
def _links_get(self, cr, uid, context={}):
obj = self.pool.get('res.request.link')
ids = obj.search(cr, uid, [])
res = obj.read(cr, uid, ids, ['object', 'name'], context)
return [(r['object'], r['name']) for r in res]
def _lang_get(self, cr, uid, context={}):
obj = self.pool.get('res.lang')
ids = obj.search(cr, uid, [])
res = obj.read(cr, uid, ids, ['code', 'name'], context)
res = [((r['code']).replace('_', '-'), r['name']) for r in res]
return res
_columns = {
'cutype': fields.selection([('individual', 'Individual'), \
('group', 'Group'), ('resource', 'Resource'), \
@@ -131,10 +144,11 @@ class calendar_attendee(osv.osv):
'User Type', help="Specify the type of calendar user"),
'member': fields.char('Member', size=124, help="Indicate the groups \
that the attendee belongs to"),
'role': fields.selection([ ('req-participant', 'req-participant'), \
('chair', 'chair'), ('opt-participant', 'opt-participant'), \
('non-participant', 'non-participant')], 'User\'s Role', \
help='Participation role for the calendar user'),
'role': fields.selection([('req-participant', 'Participation required'), \
('chair', 'Chair Person'), \
('opt-participant', 'Optional Participation'), \
('non-participant', 'For information Purpose')], 'Role', \
help='Participation role for the calendar user'),
'state': fields.selection([('tentative', 'Tentative'),
('needs-action', 'Needs Action'),
('accepted', 'Accepted'),
@@ -146,20 +160,23 @@ favor of a reply is requested"),
'delegated_to': fields.function(_compute_data, method=True, \
string='Delegated To', type="char", size=124, store=True, \
multi='delegated_to', help="The users that the original request \
was delegated to"),
'del_to_user_ids': fields.many2many('res.users', 'att_del_to_user_rel',
was delegated to"),
'del_to_user_ids': fields.many2many('res.users', 'att_del_to_user_rel',
'attendee_id', 'user_id', 'Users'),
'delegated_from': fields.function(_compute_data, method=True, string=\
'Delegated From', type="char", store=True, size=124, multi='delegated_from'),
'del_from_user_ids': fields.many2many('res.users', 'att_del_from_user_rel', \
'attendee_id', 'user_id', 'Users'),
'sent_by': fields.function(_compute_data, method=True, string='Sent By', type="char", multi='sent_by', store=True, size=124, help="Specify the user that is acting on behalf of the calendar user"),
'sent_by_uid': fields.many2one('res.users', 'Sent by User'),
'sent_by_uid': fields.many2one('res.users', 'Sent by User'),
'cn': fields.function(_compute_data, method=True, string='Common name', type="char", size=124, multi='cn', store=True),
'dir': fields.char('URI Reference', size=124, help="Reference to the URI that points to the directory information corresponding to the attendee."),
'language': fields.char('Language', size=124, help="To specify the language for text values in a property or property parameter."),
'user_id': fields.many2one('res.users', 'User'),
'email': fields.char('Email', size=124),
'language': fields.selection(_lang_get, 'Language', help="To specify \
the language for text values in a property or property parameter."),
'user_id': fields.many2one('res.users', 'User'),
'email': fields.char('Email', size=124),
'date': fields.datetime('Date of event'),
'reference': fields.reference('Event Reference', selection=_links_get, size=128),
}
_defaults = {
'state': lambda *x: 'needs-action',
@@ -185,8 +202,8 @@ calendar_attendee()
class res_alarm(osv.osv):
_name = 'res.alarm'
_description = 'basic alarm information'
_columns = {
'name':fields.char('Name', size=256, required=True),
_columns = {
'name':fields.char('Name', size=256, required=True),
'trigger_occurs': fields.selection([('before', 'Before'), ('after', 'After')], \
'Trigger time', required=True),
'trigger_interval': fields.selection([('minutes', 'Minutes'), ('hours', 'Hours'), \
@@ -196,12 +213,12 @@ class res_alarm(osv.osv):
'The event ends')], 'Trigger Occures at', required=True),
'duration': fields.integer('Duration', help="""Duration' and 'Repeat' \
are both optional, but if one occurs, so MUST the other"""),
'repeat': fields.integer('Repeat'),
'repeat': fields.integer('Repeat'),
'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 = {
_defaults = {
'trigger_interval': lambda *x: 'minutes',
'trigger_duration': lambda *x: 5,
'trigger_occurs': lambda *x: 'before',
@@ -227,10 +244,10 @@ class calendar_alarm(osv.osv):
'duration': {'field': 'duration', 'type': 'text'},
'repeat': {'field': 'repeat', 'type': 'text'},
'attach': {'field': 'attach', 'type': 'text'},
}
}
_columns = {
'alarm_id': fields.many2one('res.alarm', 'Basic Alarm', ondelete='cascade'),
_columns = {
'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"""),
'action': fields.selection([('audio', 'Audio'), ('display', 'Display'), \
@@ -238,29 +255,29 @@ or contains the text to be used for display"""),
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'),
'attendee_ids': fields.many2many('calendar.attendee', 'alarm_attendee_rel', \
'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,
'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'),
'trigger_date' : fields.datetime('Trigger Date', readonly="True"),
'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'),
'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 = {
'action': lambda *x: 'email',
'state' : lambda *x: 'run',
}
'state' : lambda *x: 'run',
}
def create(self, cr, uid, vals, context={}):
def create(self, cr, uid, vals, context={}):
event_date = vals.get('event_date', False)
if event_date:
dtstart = datetime.datetime.strptime(vals['event_date'], "%Y-%m-%d %H:%M:%S")
@@ -272,7 +289,7 @@ or contains the text to be used for display"""),
delta = datetime.timedelta(minutes=vals['trigger_duration'])
trigger_date = dtstart + (vals['trigger_occurs'] == 'after' and delta or -delta)
vals['trigger_date'] = trigger_date
res = super(calendar_alarm, self).create(cr, uid, vals, context)
res = super(calendar_alarm, self).create(cr, uid, vals, context)
return res
def do_run_scheduler(self, cr, uid, automatic=False, use_new_cursor=False, \
@@ -283,31 +300,31 @@ or contains the text to be used for display"""),
cr.execute("select alarm.id as id \
from calendar_alarm alarm \
where alarm.state = %s and alarm.trigger_date <= %s", ('run', current_datetime))
res = cr.dictfetchall()
alarm_ids = map(lambda x: x['id'], res)
res = cr.dictfetchall()
alarm_ids = map(lambda x: x['id'], res)
attendee_obj = self.pool.get('calendar.attendee')
request_obj = self.pool.get('res.request')
mail_to = []
for alarm in self.browse(cr, uid, alarm_ids):
for alarm in self.browse(cr, uid, alarm_ids):
if alarm.action == 'display':
value = {
'name': alarm.name,
'act_from': alarm.user_id.id,
'act_to': alarm.user_id.id,
value = {
'name': alarm.name,
'act_from': alarm.user_id.id,
'act_to': alarm.user_id.id,
'body': alarm.description,
'trigger_date': alarm.trigger_date,
'ref_doc1' : '%s,%s' %(alarm.model_id.model, alarm.res_id)
'ref_doc1' : '%s,%s' %(alarm.model_id.model, alarm.res_id)
}
request_id = request_obj.create(cr, uid, value)
request_ids = [request_id]
for attendee in alarm.attendee_ids:
value['act_to'] = attendee.act_to.id
for attendee in alarm.attendee_ids:
value['act_to'] = attendee.user_id.id
request_id = request_obj.create(cr, uid, value)
request_ids.append(request_id)
request_obj.request_send(cr, uid, request_ids)
if alarm.action == 'email':
sub = '[Openobject Remainder] %s' %(alarm.name)
sub = '[Openobject Remainder] %s' %(alarm.name)
body = """
Name : %s
Date : %s
@@ -316,12 +333,12 @@ or contains the text to be used for display"""),
From :
%s
%s
""" %(alarm.name, alarm.trigger_date, alarm.description, alarm.user_id.name, alarm.user_id.sign)
mail_to = [alarm.user_id.address_id.email]
for att in alarm.attendee_ids:
mail_to.append(att.act_to.address_id.email)
for att in alarm.attendee_ids:
mail_to.append(att.user_id.address_id.email)
tools.email_send(
tools.confirm['from_mail'],
mail_to,
@@ -349,8 +366,8 @@ class ir_attachment(osv.osv):
for i, arg in enumerate(new_args):
if arg[0] == 'res_id':
new_args[i] = (arg[0], arg[1], caldav_id2real_id(arg[2]))
return super(ir_attachment, self).search(cr, uid, new_args, offset=offset,
limit=limit, order=order,
return super(ir_attachment, self).search(cr, uid, new_args, offset=offset,
limit=limit, order=order,
context=context, count=False)
ir_attachment()
@@ -392,7 +409,7 @@ class ir_model(osv.osv):
for val in data:
val['id'] = caldav_id2real_id(val['id'])
return data
ir_model()
class virtual_report_spool(web_services.report_spool):
@@ -466,7 +483,7 @@ class set_rrule_wizard(osv.osv_memory):
if freq == 'weekly':
byday = map(lambda x: x.upper(), filter(lambda x: datas.get(x) and x in weekdays, datas))
if byday:
if byday:
weekstring = ';BYDAY=' + ','.join(byday)
elif freq == 'monthly':
@@ -497,14 +514,14 @@ class set_rrule_wizard(osv.osv_memory):
rrule_string = 'FREQ=' + freq + weekstring + ';INTERVAL=' + \
str(datas.get('interval')) + enddate + monthstring + yearstring
# End logic
# End logic
return rrule_string
def do_add(self, cr, uid, ids, context={}):
datas = self.read(cr, uid, ids)[0]
if datas.get('interval') <= 0:
raise osv.except_osv(_('Error!'), ("Please select proper Interval"))
if not context or not context.get('model'):
return {}
@@ -512,7 +529,7 @@ class set_rrule_wizard(osv.osv_memory):
model = context.get('model')
obj = self.pool.get(model)
res_obj = obj.browse(cr, uid, context['active_id'])
rrule_string = self.compute_rule_string(cr, uid, datas)
obj.write(cr, uid, [res_obj.id], {'rrule' : rrule_string})
return {}
@@ -524,13 +541,18 @@ class invite_attendee_wizard(osv.osv_memory):
_description = "Invite Attendees"
_columns = {
'user_id': fields.many2one('res.users', 'User'),
'email': fields.char('Email', size=124),
'role': fields.selection([ ('REQ-PARTICIPANT', 'REQ-PARTICIPANT'), \
('CHAIR', 'CHAIR'), ('OPT-PARTICIPANT', 'OPT-PARTICIPANT'), \
('NON-PARTICIPANT', 'NON-PARTICIPANT')], 'User\'s Role', \
help='Participation role for the calendar user'),
'rsvp': fields.boolean('Required Reply?', help="Indicats whether the \
'user_id': fields.many2one('res.users', 'User'),
'email': fields.char('Email', size=124),
'role': fields.selection([('req-participant', 'Participation required'), \
('chair', 'Chair Person'), \
('opt-participant', 'Optional Participation'), \
('non-participant', 'For information Purpose')], 'Role', \
help='Participation role for the calendar user'),
'cutype': fields.selection([('individual', 'Individual'), \
('group', 'Group'), ('resource', 'Resource'), \
('room', 'Room'), ('unknown', 'Unknown') ], \
'User Type', help="Specify the type of calendar user"),
'rsvp': fields.boolean('Required Reply?', help="Indicats whether the \
favor of a reply is requested"),
}
@@ -544,16 +566,24 @@ favor of a reply is requested"),
res_obj = obj.browse(cr, uid, context['active_id'])
user_obj = self.pool.get('res.users')
attendee_obj = self.pool.get('calendar.attendee')
for user_id in datas.get('users', []):
user = user_obj.browse(cr, uid, user_id)
if not user.address_id.email:
raise osv.except_osv(_('Error!'), \
("User does not have an email Address"))
attendee_id = attendee_obj.create(cr, uid, {'user_id': user_id,\
'cn': user.name + ':MAILTO:' + user.address_id.email})
obj.write(cr, uid, res_obj.id, {'attendee_ids': [(6, 0, [attendee_id])]})
user = user_obj.browse(cr, uid, datas.get('user_id'))
if not user.address_id.email:
raise osv.except_osv(_('Error!'), \
("User does not have an email Address"))
val = {
'user_id': user.id,
'email': datas.get('email'),
'date': res_obj[context.get('field')],
'reference': '%s,%s' %(model, context['active_id']),
'language': (user.context_lang).replace('_', '-'),
'rsvp': datas.get('rsvp'),
'role': datas.get('role'),
'cutype': datas.get('cutype'),
}
attendee_id = attendee_obj.create(cr, uid, val)
obj.write(cr, uid, res_obj.id, {'attendee_ids': [(4, attendee_id)]})
return {}
def onchange_user_id(self, cr, uid, ids, user_id, *args, **argv):
if not user_id:
+1 -1
View File
@@ -110,7 +110,7 @@
<button string="Invite Attendees"
name="%(caldav.action_view_calendar_invite_attendee_wizard)d"
icon="terp-partner" type="action"
context="{'model' : 'crm.meeting'}" />
context="{'model' : 'crm.meeting', 'field': 'date'}" />
</page>
<page string="Partner Info">
<field name="partner_id" on_change="onchange_partner_id(partner_id, email_from)" />