1 # -*- coding: utf-8 -*-
2 ##############################################################################
4 # OpenERP, Open Source Management Solution
5 # Copyright (C) 2004-today OpenERP SA (<http://www.openerp.com>)
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU Affero General Public License as
9 # published by the Free Software Foundation, either version 3 of the
10 # License, or (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU Affero General Public License for more details.
17 # You should have received a copy of the GNU Affero General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
20 ##############################################################################
22 from base_calendar import base_calendar
23 from base_status.base_state import base_state
24 from base_status.base_stage import base_stage
26 from osv import fields, osv
28 from tools.translate import _
30 class crm_lead(base_stage, osv.osv):
34 class crm_meeting(base_state, osv.Model):
35 """ Model for CRM meetings """
37 _description = "Meeting"
39 _inherit = ["calendar.event", 'ir.needaction_mixin', "mail.thread"]
41 # base_state required fields
42 'partner_id': fields.many2one('res.partner', 'Partner', states={'done': [('readonly', True)]}),
43 'section_id': fields.many2one('crm.case.section', 'Sales Team', states={'done': [('readonly', True)]}, \
44 select=True, help='Sales team to which Case belongs to.'),
45 'email_from': fields.char('Email', size=128, states={'done': [('readonly', True)]}, help="These people will receive email."),
46 'create_date': fields.datetime('Creation Date' , readonly=True),
47 'write_date': fields.datetime('Write Date' , readonly=True),
48 'date_action_last': fields.datetime('Last Action', readonly=1),
49 'date_action_next': fields.datetime('Next Action', readonly=1),
51 'name': fields.char('Summary', size=124, required=True, states={'done': [('readonly', True)]}),
52 'categ_id': fields.many2one('crm.case.categ', 'Meeting Type', \
53 domain="[('object_id.model', '=', 'crm.meeting')]", \
55 'phonecall_id': fields.many2one ('crm.phonecall', 'Phonecall'),
56 'opportunity_id': fields.many2one ('crm.lead', 'Opportunity', domain="[('type', '=', 'opportunity')]"),
57 'attendee_ids': fields.many2many('calendar.attendee', 'meeting_attendee_rel',\
58 'event_id', 'attendee_id', 'Attendees', states={'done': [('readonly', True)]}),
59 'date_closed': fields.datetime('Closed', readonly=True),
60 'date_deadline': fields.datetime('Deadline', states={'done': [('readonly', True)]}),
61 'state': fields.selection([ ('draft', 'Unconfirmed'),
62 ('open', 'Confirmed'),
63 ('cancel', 'Cancelled'),
65 string='Status', size=16, readonly=True),
70 'user_id': lambda self, cr, uid, ctx: uid,
73 def create(self, cr, uid, vals, context=None):
74 obj_id = super(crm_meeting, self).create(cr, uid, vals, context=context)
75 self.create_send_note(cr, uid, [obj_id], context=context)
78 def get_needaction_user_ids(self, cr, uid, ids, context=None):
79 result = dict.fromkeys(ids, [])
80 for obj in self.browse(cr, uid, ids, context=context):
81 if (obj.state == 'draft' and obj.user_id):
82 result[obj.id] = [obj.user_id.id]
85 def case_open(self, cr, uid, ids, context=None):
86 """ Confirms meeting """
87 res = super(crm_meeting, self).case_open(cr, uid, ids, context)
88 for (id, name) in self.name_get(cr, uid, ids):
89 id=base_calendar.base_calendar_id2real_id(id)
92 # ----------------------------------------
94 # ----------------------------------------
96 def case_get_note_msg_prefix(self, cr, uid, id, context=None):
99 def create_send_note(self, cr, uid, ids, context=None):
102 # update context: if come from phonecall, default state values can make the message_append_note crash
103 context.pop('default_state', False)
104 for meeting in self.browse(cr, uid, ids, context=context):
105 # convert datetime field to a datetime, using server format, then
106 # convert it to the user TZ and re-render it with %Z to add the timezone
107 meeting_datetime = fields.DT.datetime.strptime(meeting.date, tools.DEFAULT_SERVER_DATETIME_FORMAT)
108 meeting_date_str = fields.datetime.context_timestamp(cr, uid, meeting_datetime, context=context).strftime(tools.DATETIME_FORMATS_MAP['%+'] + " (%Z)")
109 message = _("A meeting has been <b>scheduled</b> on <em>%s</em>.") % (meeting_date_str)
110 if meeting.opportunity_id: # meeting can be create from phonecalls or opportunities, therefore checking for the parent
111 lead = meeting.opportunity_id
112 parent_message = _("Meeting linked to the opportunity <em>%s</em> has been <b>created</b> and <b>cscheduled</b> on <em>%s</em>.") % (lead.name, meeting.date)
113 lead.message_append_note(_('System Notification'), message)
114 elif meeting.phonecall_id:
115 phonecall = meeting.phonecall_id
116 parent_message = _("Meeting linked to the phonecall <em>%s</em> has been <b>created</b> and <b>cscheduled</b> on <em>%s</em>.") % (phonecall.name, meeting.date)
117 phonecall.message_append_note(body=message)
119 parent_message = message
121 meeting.message_append_note(body=parent_message)
124 def case_open_send_note(self, cr, uid, ids, context=None):
125 return self.message_append_note(cr, uid, ids, body=_("Meeting has been <b>confirmed</b>."), context=context)
127 def case_close_send_note(self, cr, uid, ids, context=None):
128 return self.message_append_note(cr, uid, ids, body=_("Meeting has been <b>done</b>."), context=context)
131 class calendar_attendee(osv.osv):
132 """ Calendar Attendee """
134 _inherit = 'calendar.attendee'
135 _description = 'Calendar Attendee'
137 def _compute_data(self, cr, uid, ids, name, arg, context=None):
139 @param self: The object pointer
140 @param cr: the current row, from the database cursor,
141 @param uid: the current user’s ID for security checks,
142 @param ids: List of compute data’s IDs
143 @param context: A standard dictionary for contextual values
146 result = super(calendar_attendee, self)._compute_data(cr, uid, ids, name, arg, context=context)
148 for attdata in self.browse(cr, uid, ids, context=context):
151 if name == 'categ_id':
152 if attdata.ref and 'categ_id' in attdata.ref._columns:
153 result[id][name] = (attdata.ref.categ_id.id, attdata.ref.categ_id.name,)
155 result[id][name] = False
159 'categ_id': fields.function(_compute_data, \
160 string='Event Type', type="many2one", \
161 relation="crm.case.categ", multi='categ_id'),
166 class res_users(osv.osv):
168 _inherit = 'res.users'
170 def create(self, cr, uid, data, context=None):
171 user_id = super(res_users, self).create(cr, uid, data, context=context)
173 # add shortcut unless 'noshortcut' is True in context
174 if not(context and context.get('noshortcut', False)):
175 data_obj = self.pool.get('ir.model.data')
177 data_id = data_obj._get_id(cr, uid, 'crm', 'ir_ui_view_sc_calendar0')
178 view_id = data_obj.browse(cr, uid, data_id, context=context).res_id
179 self.pool.get('ir.ui.view_sc').copy(cr, uid, view_id, default = {
180 'user_id': user_id}, context=context)
182 # Tolerate a missing shortcut. See product/product.py for similar code.
183 logging.getLogger('orm').debug('Skipped meetings shortcut for user "%s"', data.get('name','<new'))
189 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: