[IMP] Add mail when date has been updates on an event

bzr revid: jke@openerp.com-20131126180106-yc91907yvfu24usg
This commit is contained in:
jke-openerp 2013-11-26 19:01:06 +01:00
parent 96bd471e92
commit d264c28565
4 changed files with 148 additions and 53 deletions

View File

@ -251,7 +251,7 @@ class calendar_attendee(osv.osv):
res = cal.serialize()
return res
def _send_mail(self, cr, uid, ids, email_from=tools.config.get('email_from', False), context=None):
def _send_mail_to_attendees(self, cr, uid, ids, email_from=tools.config.get('email_from', False), template_xmlid='crm_email_template_meeting_invitation', context=None):
"""
Send mail for event invitation to event attendees.
@param email_from: email address for user sending the mail
@ -274,13 +274,14 @@ class calendar_attendee(osv.osv):
ids = [ids]
print "IDS too send = ", ids
print "IDS to send = ", ids
for attendee in self.browse(cr, uid, ids, context=context):
res_obj = attendee.ref
if res_obj:
dummy,template_id = data_pool.get_object_reference(cr, uid, 'base_calendar', "crm_email_template_meeting_invitation")
dummy,template_id = data_pool.get_object_reference(cr, uid, 'base_calendar', template_xmlid)
dummy,act_id = data_pool.get_object_reference(cr, uid, 'base_calendar', "view_crm_meeting_calendar")
body = template_pool.browse(cr, uid, template_id, context=context).body_html
if attendee.email and email_from:
ics_file = self.get_ics_file(cr, uid, res_obj, context=context)
local_context['att_obj'] = attendee
@ -305,7 +306,6 @@ class calendar_attendee(osv.osv):
if not attendee.partner_id.opt_out:
mail_id.append(mail_pool.create(cr, uid, vals, context=context))
if mail_id:
try:
res = mail_pool.send(cr, uid, mail_id, context=context)
@ -313,17 +313,7 @@ class calendar_attendee(osv.osv):
print e
return res
def do_attendee_decline(self, cr, uid, ids, context=None):
return self.do_decline(cr, uid, ids, context=context)
def do_attendee_accept(self, cr, uid, ids, context=None):
return self.do_accept(cr, uid, ids, context=context)
def do_attendee_maybe(self, cr, uid, ids, context=None):
return self.do_tentative(cr, uid, ids, context=context)
def onchange_user_id(self, cr, uid, ids, user_id, *args, **argv):
"""
Make entry on email and availbility on change of user_id field.
@ -354,9 +344,8 @@ class calendar_attendee(osv.osv):
meeting_obj = self.pool.get('crm.meeting')
res = self.write(cr, uid, ids, {'state': 'accepted'}, context)
for attendee in self.browse(cr, uid, ids, context=context):
meeting_ids = meeting_obj.search(cr, uid, [('attendee_ids', '=', attendee.id)], context=context)
if meeting_ids:
meeting_obj.message_post(cr, uid, get_real_ids(meeting_ids), body=_(("%s has accepted invitation") % (attendee.cn)),subtype="base_calendar.subtype_invitation", context=context)
if attendee.ref:
meeting_obj.message_post(cr, uid, attendee.ref.id, body=_(("%s has accepted invitation") % (attendee.cn)),subtype="base_calendar.subtype_invitation", context=context)
return res
@ -369,10 +358,9 @@ class calendar_attendee(osv.osv):
context = {}
meeting_obj = self.pool.get('crm.meeting')
res = self.write(cr, uid, ids, {'state': 'declined'}, context)
for attandee in self.browse(cr, uid, ids, context=context):
meeting_ids = meeting_obj.search(cr, uid, [('attendee_ids', '=', attandee.id)], context=context)
if meeting_ids:
meeting_obj.message_post(cr, uid, get_real_ids(meeting_ids), body=_(("%s has declined invitation") % (attandee.cn)),subtype="base_calendar.subtype_invitation", context=context)
for attendee in self.browse(cr, uid, ids, context=context):
if attendee.ref:
meeting_obj.message_post(cr, uid, attendee.ref.id, body=_(("%s has declined invitation") % (attendee.cn)),subtype="base_calendar.subtype_invitation", context=context)
return res
def create(self, cr, uid, vals, context=None):
@ -590,7 +578,7 @@ class calendar_alarm_manager(osv.osv):
print "cond 1 = ", one_date - timedelta(minutes=alarm.duration_minutes), " < ", datetime.now() + timedelta(seconds=in_the_next_X_seconds)
#print "cond 2", one_date - timedelta(minutes=alarm.duration_minutes), " > ",datetime.strptime(after.split('.')[0], "%Y-%m-%d %H:%M:%S")
print
if alarm.type in alarm_type and \
one_date - timedelta(minutes=alarm.duration_minutes) < datetime.now() + timedelta(seconds=in_the_next_X_seconds) and \
(not after or one_date - timedelta(minutes=alarm.duration_minutes) > datetime.strptime(after.split('.')[0], "%Y-%m-%d %H:%M:%S")):
@ -989,9 +977,10 @@ class crm_meeting(osv.Model):
for id in ids:
#read these fields as SUPERUSER because if the record is private a normal search could return False and raise an error
data = self.browse(cr, SUPERUSER_ID, id, context=context)
if data.interval < 0:
if data.interval and data.interval < 0:
raise osv.except_osv(_('Warning!'), _('Interval cannot be negative.'))
if data.count <= 0:
if data.count and data.count <= 0:
raise osv.except_osv(_('Warning!'), _('Count cannot be negative or 0.'))
data = self.read(cr, uid, id, ['id','byday','recurrency', 'month_list','end_date', 'rrule_type', 'month_by', 'interval', 'count', 'end_type', 'mo', 'tu', 'we', 'th', 'fr', 'sa', 'su', 'day', 'week_list' ], context=context)
@ -1158,8 +1147,7 @@ class crm_meeting(osv.Model):
diff = end - start
duration = float(diff.days)* 24 + (float(diff.seconds) / 3600)
value['duration'] = round(duration, 2)
print "Out value : ", value
return {'value': value}
def unlink_events(self, cr, uid, ids, context=None):
@ -1183,12 +1171,13 @@ class crm_meeting(osv.Model):
att_obj = self.pool.get('calendar.attendee')
user_obj = self.pool.get('res.users')
current_user = user_obj.browse(cr, uid, uid, context=context)
res = {}
for event in self.browse(cr, uid, ids, context):
attendees = {}
for att in event.attendee_ids:
attendees[att.partner_id.id] = True
new_attendees = []
new_att_partner_ids = [] #avoid to rebrowse attendees
new_att_partner_ids = []
# mail_to = ""
for partner in event.partner_ids:
if partner.id in attendees:
@ -1211,7 +1200,7 @@ class crm_meeting(osv.Model):
if not current_user.email or current_user.email != partner.email :
mail_from = current_user.email or tools.config.get('email_from', False)
print "Send mail... from ",mail_from, " to ",att_id
if self.pool.get('calendar.attendee')._send_mail(cr, uid, att_id, email_from = mail_from, context=context):
if self.pool.get('calendar.attendee')._send_mail_to_attendees(cr, uid, att_id, email_from = mail_from, context=context):
self.message_post(cr, uid, event.id, body=_("An invitation email has been sent to attendee %s") % (partner.name,),subtype="base_calendar.subtype_invitation", context=context)
else:
print "DON'T SEND MAIL TO MYSELF !"
@ -1228,18 +1217,20 @@ class crm_meeting(osv.Model):
all_attendee_ids = [att.partner_id.id for att in event.attendee_ids]
partner_ids_to_remove = map(lambda x: x, set(all_attendee_ids + new_att_partner_ids) - set(all_partner_ids))
attendee_ids_to_remove = []
if partner_ids_to_remove:
attendee_ids_to_remove =self.pool.get("calendar.attendee").search(cr,uid,[('partner_id.id','in',partner_ids_to_remove),('ref.id','=',event.id)],context=context)
if attendee_ids_to_remove:
self.pool.get("calendar.attendee").unlink(cr, uid, attendee_ids_to_remove, context)
## NEED TO UNSUBSCRIBE ?
return {
'new_partner_ids' : new_att_partner_ids,
'new_attendee_ids' : new_attendees,
'all_partner_ids' : all_partner_ids,
'all_attendee_ids' : all_attendee_ids
}
res[event.id] = {
'new_attendee_ids' : new_attendees ,
'old_attendee_ids' : all_attendee_ids ,
'removed_attendee_ids' : attendee_ids_to_remove
}
return res
def get_recurrent_ids(self, cr, uid, select, domain, limit=100, context=None):
"""Gives virtual event ids for recurring events based on value of Recurrence Rule
@ -1491,7 +1482,7 @@ class crm_meeting(osv.Model):
current_user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
if current_user.email:
if self.pool.get('calendar.attendee')._send_mail(cr, uid, [att.id for att in event.attendee_ids], email_from = current_user.email, context=context):
if self.pool.get('calendar.attendee')._send_mail_to_attendees(cr, uid, [att.id for att in event.attendee_ids], email_from = current_user.email, context=context):
self.message_post(cr, uid, event.id, body=_("An invitation email has been sent to attendee(s)"), subtype="base_calendar.subtype_invitation", context=context)
return;
@ -1643,10 +1634,20 @@ class crm_meeting(osv.Model):
print values
if values.get('date', False):
print "Date has been changed !!!! --> SEND MAIL"
if attendees_create:
attendees_create = attendees_create[ids[0]]
mail_to_ids = list(set(attendees_create['old_attendee_ids']) - set(attendees_create['removed_attendee_ids']))
print 'xxxToSend to ', mail_to_ids
else:
mail_to_ids = [att.id for att in self.browse(cr,uid,int(ids[0]),context=context).attendee_ids]
print 'yyyToSend to ', mail_to_ids
if mail_to_ids:
current_user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
if self.pool.get('calendar.attendee')._send_mail_to_attendees(cr, uid, mail_to_ids, template_xmlid='crm_email_template_meeting_changedate',email_from=current_user.email, context=context):
self.message_post(cr, uid, int(ids[0]), body=_("A email has been send to specify that the date has been changed !"),subtype="base_calendar.subtype_invitation", context=context)
else:
print 'Send mail return false'
return res or True and False
def create(self, cr, uid, vals, context=None):

View File

@ -230,7 +230,108 @@
]]></field>
</record>
<record id="crm_email_template_meeting_changedate" model="email.template">
<field name="name">Meeting Invitation </field>
<field name="email_from">${object.user_id.email or ''}</field>
<field name="subject">${object.name} - Date updated</field>
<field name="email_to" >${ctx['att_obj'].email}</field>
<field name="model_id" ref="base_calendar.model_crm_meeting"/>
<field name="auto_delete" eval="True"/>
<field name="body_html"><![CDATA[
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<title>${object.name}</title>
</head>
<body>
<div style="border-radius: 2px; max-width: 1200px; height: auto;margin-left: auto;margin-right: auto;background-color:#f9f9f9;">
<div style="height:auto;text-align: center;font-size : 30px;color: #8A89BA;">
<strong>${object.name}</strong>
</div>
<div style="height: 50px;text-align: left;font-size : 14px;border-collapse: separate;margin-top:10px">
<strong style="margin-left:12px">Hello ${ctx['att_obj'].cn}</strong> ,<br/>
<p style="margin-left:12px">The date of the meeting has been changed...<br/>The meeting create by ${object.user_id.partner_id.name} is now scheduled for : ${object.date}.</p>
</div>
<div style="height: auto;margin-left:12px;margin-top:30px;">
<table>
<tr>
<td>
<div style="border-top-left-radius:3px;border-top-right-radius:3px;font-size:12px;border-collapse:separate;text-align:center;font-weight:bold;color:#ffffff;width:130px;min-height: 18px;border-color:#ffffff;background:#8a89ba;padding-top: 4px;">${object.get_interval(object.date, 'dayname')}</div>
<div style="font-size:48px;min-height:auto;font-weight:bold;text-align:center;color: #5F5F5F;background-color: #E1E2F8;width: 130px;">
${object.get_interval(object.date,'day')}
</div>
<div style='font-size:12px;text-align:center;font-weight:bold;color:#ffffff;background-color:#8a89ba'>${object.get_interval(object.date, 'month')}</div>
<div style="border-collapse:separate;color:#8a89ba;text-align:center;width: 128px;font-size:12px;border-bottom-right-radius:3px;font-weight:bold;border:1px solid;border-bottom-left-radius:3px;">${object.get_interval(object.date, 'time')}</div>
</td>
<td>
<table cellspacing="0" cellpadding="0" border="0" style="margin-top: 15px; margin-left: 10px;font-size: 16px;">
% if object.location:
<tr style=" height: 30px;">
<td style="vertical-align:top;">
<div style="height: 25px; width: 120px; background : # CCCCCC; font-family: Lucica Grande', Ubuntu, Arial, Verdana, sans-serif;">
Where
</div>
</td>
<td colspan="1" style="vertical-align:top;">
<div style = "font-family: Lucica Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 14px" >
: ${object.location}
<span style= "color:#A9A9A9; ">(<a href="http://maps.google.com/maps?oi=map&q=${object.location}">View Map</a>)
</span>
</div>
</td>
</tr>
% endif
% if object.description :
<tr style=" height:auto;">
<td style="vertical-align:top;">
<div style="height:auto; width: 120px; background : # CCCCCC; font-family: Lucica Grande', Ubuntu, Arial, Verdana, sans-serif;">
What
</div>
</td>
<td colspan="3" style="vertical-align:text-top;">
<div style="font-family: Lucica Grande', Ubuntu, Arial, Verdana, sans-serif;">
: ${object.description or ''}
</div>
</td>
</tr>
% endif
<tr style=" height: 30px;">
<td style="height: 25px;width: 120px; background : # CCCCCC; font-family: Lucica Grande', Ubuntu, Arial, Verdana, sans-serif;">
<div>
Attendees
</div>
</td>
<td colspan="3">
: <div style='display:inline-block; border-radius: 50%; width:10px; height:10px;background:grey;'></div>
<span style="margin-left:5px">You</span>
% for attendee in object.attendee_ids:
% if attendee.cn != ctx['att_obj'].cn:
<div style='display:inline-block; border-radius: 50%; width:10px; height:10px;background:${ctx['color'][attendee.state]};'></div>
<span style="margin-left:5px">${attendee.cn}</span>
% endif
% endfor
</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
<div style="height: auto;width:300px; margin:0 auto;padding-top:20px;">
<a style="padding: 8px 30px 8px 30px;border-radius: 6px;border: 1px solid #CCCCCC;background:#8A89BA;margin : 0 15px 0 0;text-decoration: none;color:#FFFFFF;" href="${ctx['base_url']}/meeting_invitation/accept?db=${ctx['dbname']}&token=${ctx['att_obj'].access_token}&action=${ctx['action_id']}&id=${object.id}">Accept</a>
<a style="padding: 8px 30px 8px 30px;border-radius: 6px;border: 1px solid #CCCCCC;background:#808080;text-decoration: none;color:#FFFFFF;" href="${ctx['base_url']}/meeting_invitation/decline?db=${ctx['dbname']}&token=${ctx['att_obj'].access_token}&action=${ctx['action_id']}&id=${object.id}">Decline</a>
</div>
<div style="padding-top:10px;">
-- </br> Sent by ${object.user_id.name} from ${object.user_id.company_id.name}. View this meeting detail <a href="${ctx['base_url']}/meeting_invitation/view?db=${ctx['dbname']}&token=${ctx['att_obj'].access_token}&action=${ctx['action_id']}&id=${object.id}">directly in OpenERP.</a>
</div>
</div>
</body>
</html>
]]></field>
</record>
<record id="crm_email_template_meeting_reminder" model="email.template">
<field name="name">Meeting Invitation</field>
<field name="email_from">${object.user_id.email or ''}</field>

View File

@ -137,9 +137,9 @@
<field name="state" />
<field name="email" widget="email"/>
<button name="do_attendee_maybe" states="needs-action,declined,accepted" string="Uncertain" type="object" icon="terp-crm" />
<button name="do_attendee_accept" string="Accept" states="needs-action,tentative,declined" type="object" icon="gtk-apply"/>
<button name="do_attendee_decline" string="Decline" states="needs-action,tentative,accepted" type="object" icon="gtk-cancel"/>
<button name="do_tentative" states="needs-action,declined,accepted" string="Uncertain" type="object" icon="terp-crm" />
<button name="do_accept" string="Accept" states="needs-action,tentative,declined" type="object" icon="gtk-apply"/>
<button name="do_decline" string="Decline" states="needs-action,tentative,accepted" type="object" icon="gtk-cancel"/>
</tree>
</field>
</page>
@ -212,7 +212,7 @@
<field name="arch" type="xml">
<calendar string="Meetings" date_start="date" date_stop="date_deadline" date_delay="duration"
display="[name]" color="color_partner_id" attendee="partner_ids"
use_contacts="True" quick_add="True" all_day="allday" event_open_popup="base_calendar.action_crm_meeting_popup">
use_contacts="True" quick_add="True" all_day="allday" event_open_popup="%(base_calendar.view_crm_meeting_form_popup)s">
<field name="name"/>
<field name="user_id"/>
@ -311,14 +311,7 @@
<field name="view_mode">form,calendar,tree,gantt</field>
<field name="view_id" ref="action_view_crm_meeting_form"/>
</record>
<record id="action_crm_meeting_popup" model="ir.actions.act_window">
<field name="name">Meetings</field>
<field name="res_model">crm.meeting</field>
<field name="view_mode">form</field>
<field name="view_id" ref="view_crm_meeting_form_popup"/>
</record>
</data>
</openerp>

View File

@ -4,7 +4,7 @@ access_calendar_alarm,calendar.alarm,model_calendar_alarm,base.group_user,1,1,1,
access_calendar_attendee_survey_user,calendar.attendee,model_calendar_attendee,base.group_survey_user,1,0,0,0
access_crm_meeting_manager,crm.meeting.manager,model_crm_meeting,base.group_sale_manager,1,1,1,1
access_crm_meeting,crm.meeting,model_crm_meeting,base.group_sale_salesman,1,1,1,0
access_crm_meeting_all,crm.meeting_allll,model_crm_meeting,base.group_user,1,1,0,0
access_crm_meeting_all,crm.meeting_all,model_crm_meeting,base.group_user,1,1,1,1
access_crm_meeting_partner_manager,crm.meeting.partner.manager,model_crm_meeting,base.group_partner_manager,1,1,1,1
access_crm_meeting_type_sale_manager,crm.meeting.type.manager,model_crm_meeting_type,base.group_sale_manager,1,1,1,0
access_crm_meeting_type_sale_user,crm.meeting.type.user,model_crm_meeting_type,base.group_user,1,0,0,0

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
4 access_calendar_attendee_survey_user calendar.attendee model_calendar_attendee base.group_survey_user 1 0 0 0
5 access_crm_meeting_manager crm.meeting.manager model_crm_meeting base.group_sale_manager 1 1 1 1
6 access_crm_meeting crm.meeting model_crm_meeting base.group_sale_salesman 1 1 1 0
7 access_crm_meeting_all crm.meeting_allll crm.meeting_all model_crm_meeting base.group_user 1 1 0 1 0 1
8 access_crm_meeting_partner_manager crm.meeting.partner.manager model_crm_meeting base.group_partner_manager 1 1 1 1
9 access_crm_meeting_type_sale_manager crm.meeting.type.manager model_crm_meeting_type base.group_sale_manager 1 1 1 0
10 access_crm_meeting_type_sale_user crm.meeting.type.user model_crm_meeting_type base.group_user 1 0 0 0