1
##############################################################################
3
# OpenERP, Open Source Management Solution
4
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
6
# This program is free software: you can redistribute it and/or modify
7
# it under the terms of the GNU Affero General Public License as
8
# published by the Free Software Foundation, either version 3 of the
9
# License, or (at your option) any later version.
11
# This program is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
# GNU Affero General Public License for more details.
16
# You should have received a copy of the GNU Affero General Public License
17
# along with this program. If not, see <http://www.gnu.org/licenses/>.
19
##############################################################################
21
from osv import fields, osv
22
from datetime import datetime
25
from tools.translate import _
26
from crm.crm import crm_case
34
('cancel', 'Cancelled'),
36
('pending', 'Pending'),
37
('ready', 'Intake OK'),
38
('planned', 'Planned'),
42
class crm_case_stage(osv.osv):
44
_inherit = "crm.case.stage"
46
def _get_type_value(self, cr, user, context):
47
return [('lead','Lead'),('opportunity','Opportunity'),('activity','Activity')]
50
'type': fields.selection(_get_type_value, 'Type'),
55
class crm_activities(crm_case, osv.osv):
56
""" CRM Activity Case """
57
_name = "crm.activities"
58
_description = "Case Driven Activities"
59
_order = "date_action, priority, id desc"
60
_inherit = ['mailgate.thread','res.partner.address','crm.lead']
62
def _get_stage_id(self, cr, uid, context={}):
65
stage_pool = self.pool.get('crm.case.stage')
66
stage_type = context and context.get('stage_type','')
67
logging.getLogger('crm_enhancements').warning("Stage Type %s", stage_type)
70
domain = [('type', '=', stage_type)]
71
stages = stage_pool.search(cr, uid, domain, order='sequence')
74
def action_makeMeeting(self, cr, uid, ids, context=None):
75
logging.getLogger('crm_activities').warning("Context %s", context)
77
This opens Meeting's calendar view to schedule meeting on current Opportunity
78
@param self: The object pointer
80
@param cr: the current row, from the database cursor,
81
@param uid: the current user's ID for security checks,
82
@param ids: List of Opportunity to Meeting IDs
83
@param context: A standard dictionary for contextual values
85
@return : Dictionary value for created Meeting view
88
for opp in self.browse(cr, uid, ids, context=context):
89
data_obj = self.pool.get('ir.model.data')
92
result = data_obj._get_id(cr, uid, 'crm', 'view_crm_case_meetings_filter')
93
res = data_obj.read(cr, uid, result, ['res_id'])
94
id1 = data_obj._get_id(cr, uid, 'crm_activities', 'crm_case_calendar_view_meet')
95
id2 = data_obj._get_id(cr, uid, 'crm_activities', 'crm_case_form_view_meet')
96
id3 = data_obj._get_id(cr, uid, 'crm_activities', 'crm_case_tree_view_meet')
98
id1 = data_obj.browse(cr, uid, id1, context=context).res_id
100
id2 = data_obj.browse(cr, uid, id2, context=context).res_id
102
id3 = data_obj.browse(cr, uid, id3, context=context).res_id
105
'default_opportunity_id': opp.id,
106
'default_partner_id': opp.partner_id and opp.partner_id.id or False,
107
'default_user_id': context['uid'],
108
'default_section_id': opp.section_id and opp.section_id.id or False,
109
'default_email_from': opp.email_from,
110
'default_state': 'open',
111
'default_name': opp.name
113
logging.getLogger('crm_activities').warning("Context 2: %s", context)
115
'name': _('Meetings'),
118
'view_mode': 'calendar,form,tree',
119
'res_model': 'crm.meeting.activities',
121
'views': [(id1, 'calendar'), (id2, 'form'), (id3, 'tree')],
122
'type': 'ir.actions.act_window',
123
'search_view_id': res['res_id'],
128
def _compute_day(self, cr, uid, ids, fields, args, context=None):
130
@param cr: the current row, from the database cursor,
131
@param uid: the current user's ID for security checks,
132
@param ids: List of Openday's IDs
133
@return: difference between current date and log date
134
@param context: A standard dictionary for contextual values
136
cal_obj = self.pool.get('resource.calendar')
137
res_obj = self.pool.get('resource.resource')
140
for lead in self.browse(cr, uid, ids, context=context):
145
if field == 'day_open':
147
date_create = datetime.strptime(lead.create_date, "%Y-%m-%d %H:%M:%S")
148
date_open = datetime.strptime(lead.date_open, "%Y-%m-%d %H:%M:%S")
149
ans = date_open - date_create
150
date_until = lead.date_open
151
elif field == 'day_close':
153
date_create = datetime.strptime(lead.create_date, "%Y-%m-%d %H:%M:%S")
154
date_close = datetime.strptime(lead.date_closed, "%Y-%m-%d %H:%M:%S")
155
date_until = lead.date_closed
156
ans = date_close - date_create
160
resource_ids = res_obj.search(cr, uid, [('user_id','=',lead.user_id.id)])
161
if len(resource_ids):
162
resource_id = resource_ids[0]
164
duration = float(ans.days)
165
if lead.section_id and lead.section_id.resource_calendar_id:
166
duration = float(ans.days) * 24
167
new_dates = cal_obj.interval_get(cr,
169
lead.section_id.resource_calendar_id and lead.section_id.resource_calendar_id.id or False,
170
datetime.strptime(lead.create_date, '%Y-%m-%d %H:%M:%S'),
175
date_until = datetime.strptime(date_until, '%Y-%m-%d %H:%M:%S')
176
for in_time, out_time in new_dates:
177
if in_time.date not in no_days:
178
no_days.append(in_time.date)
179
if out_time > date_until:
181
duration = len(no_days)
182
res[lead.id][field] = abs(int(duration))
185
def onchange_section_id(self, cr, uid, ids, section_id, context={}):
187
logging.getLogger('crm_enhancements').warning("Value sent %s", section_id)
189
sid = self.pool.get('crm.case.section').browse(cr,uid,section_id)
190
v = { 'user_id':sid.user_id.id }
193
def _get_attach_ids(self, cr, uid, ids, field_name, arg, context={}):
195
for record in self.browse(cr, uid, ids, context=context):
196
if record.message_ids:
198
for msgid in record.message_ids:
199
for attachid in msgid.attachment_ids:
200
result[record.id].append(attachid.id)
202
result[record.id]= False
205
def _get_comms_ids(self, cr, uid, ids, field_name, arg, context={}):
207
for record in self.browse(cr, uid, ids, context=context):
208
if record.message_ids:
210
for msgid in record.message_ids:
211
if ( msgid.history or msgid.name.upper() == "NOTE" ) :
212
if ( field_name=='communication_ids'):
213
result[record.id].append(msgid.id)
214
elif ( field_name=='history_ids'):
215
result[record.id].append(msgid.id)
217
result[record.id]= False
220
def case_ready(self, cr, uid, ids, *args):
222
@param self: The object pointer
223
@param cr: the current row, from the database cursor,
224
@param uid: the current user's ID for security checks,
225
@param ids: List of case Ids
226
@param *args: Tuple Value for additional Params
228
cases = self.browse(cr, uid, ids)
229
cases[0].state # to fill the browse record cache
230
self._history(cr, uid, cases, _('Ready'))
231
self.write(cr, uid, ids, {'state': 'ready'})
233
# We use the cache of cases to keep the old case state
235
self._action(cr, uid, cases, 'ready')
238
def case_planned(self, cr, uid, ids, *args):
239
"""Case is effectively planned
240
@param self: The object pointer
241
@param cr: the current row, from the database cursor,
242
@param uid: the current user's ID for security checks,
243
@param ids: List of case Ids
244
@param *args: Tuple Value for additional Params
246
cases = self.browse(cr, uid, ids)
247
cases[0].state # to fill the browse record cache
248
self._history(cr, uid, cases, _('Planned'))
249
self.write(cr, uid, ids, {'state': 'planned'})
251
# We use the cache of cases to keep the old case state
253
self._action(cr, uid, cases, 'planned')
257
# Overridden from res.partner.address:
258
'partner_id': fields.many2one('res.partner', 'Partner', ondelete='set null',
259
select=True, help="Optional linked partner, usually after conversion of the lead"),
260
'partner_address_id': fields.many2one('res.partner.address', 'Partner Contact', \
261
domain="[('partner_id','=',partner_id)]"),
264
'id': fields.integer('ID'),
265
'name': fields.char('Name', size=64),
266
'active': fields.boolean('Active', required=False),
267
'date_action_last': fields.datetime('Last Action', readonly=1),
268
'date_action_next': fields.datetime('Next Action', readonly=1),
269
'email_from': fields.char('Email', size=128, help="E-mail address of the contact"),
270
'section_id': fields.many2one('crm.case.section', 'Section', \
271
select=True, help='Sales team to which this case belongs to. Defines responsible user and e-mail address for the mail gateway.'),
272
'create_date': fields.datetime('Creation Date' , readonly=True),
273
'email_cc': fields.text('Global CC', size=252 , help="These email addresses will be added to the CC field of all inbound and outbound emails for this record before being sent. Separate multiple email addresses with a comma"),
274
'description': fields.text('Notes'),
275
'write_date': fields.datetime('Update Date' , readonly=True),
278
'categ_id': fields.many2one('crm.case.categ', 'Category', \
279
domain="['|',('section_id','=',section_id),('section_id','=',False), ('object_id.model', '=', 'crm.lead')]"),
280
'type_id': fields.many2one('crm.case.resource.type', 'Campaign', \
281
domain="['|',('section_id','=',section_id),('section_id','=',False)]"),
282
'channel_id': fields.many2one('res.partner.canal', 'Channel'),
284
'contact_name': fields.char('Contact Name', size=64),
285
'partner_name': fields.char("Customer Name", size=64,help='The name of the future partner that will be created while converting the into opportunity'),
286
'optin': fields.boolean('Opt-In', help="If opt-in is checked, this contact has accepted to receive emails."),
287
'optout': fields.boolean('Opt-Out', help="If opt-out is checked, this contact has refused to receive emails or unsubscribed to a campaign."),
288
'type':fields.selection([
289
('activity','Activity'),
290
],'Type', help="Type is used to separate different types of production entities"),
291
'priority': fields.selection(crm.crm.AVAILABLE_PRIORITIES, 'Priority'),
292
'date_closed': fields.datetime('Closed', readonly=True),
293
'stage_id': fields.many2one('crm.case.stage', 'Stage', domain="[('type','=','lead')]"),
294
'user_id': fields.many2one('res.users', 'Responsible',help='By Default Salesman is Administrator when create New User'),
295
'engineer_id': fields.many2one('res.users', 'Planned for',help='The appointed engineer to execute the call'),
296
'referred': fields.char('Referred By', size=64),
297
'date_open': fields.datetime('Opened', readonly=True),
298
'day_open': fields.function(_compute_day, string='Days to Open', \
299
method=True, multi='day_open', type="float", store=True),
300
'day_close': fields.function(_compute_day, string='Days to Close', \
301
method=True, multi='day_close', type="float", store=True),
302
'state': fields.selection(AVAILABLE_STATES, 'State', size=16, readonly=True,
303
help='The state is set to \'Draft\', when a case is created.\
304
\nIf the case is in progress the state is set to \'Open\'.\
305
\nWhen the case is over, the state is set to \'Done\'.\
306
\nIf the case needs to be reviewed then the state is set to \'Pending\'.'),
307
'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('model','=',_name)]),
310
'probability': fields.float('Probability (%)',group_operator="avg"),
311
'planned_revenue': fields.float('Expected Revenue'),
312
'ref': fields.reference('Reference', selection=crm.crm._links_get, size=128),
313
'ref2': fields.reference('Reference 2', selection=crm.crm._links_get, size=128),
314
'phone': fields.char("Phone", size=64),
315
'date_deadline': fields.date('Expected Closing'),
316
'date_action': fields.date('Next Action Date'),
317
'title_action': fields.char('Next Action', size=64),
319
# CRM enhancements fields
320
'attachment_ids' : fields.function(_get_attach_ids,method=True,type="many2many",string="Attachments",relation="ir.attachment"),
321
'communication_ids' : fields.function(_get_comms_ids,method=True,type="many2many",string="Communication Items",relation="mailgate.message"),
322
'history_ids' : fields.function(_get_comms_ids,method=True,type="many2many",string="History Items",relation="mailgate.message"),
328
'active': lambda *a: 1,
329
'user_id': crm_case._get_default_user,
330
'email_from': crm_case._get_default_email,
331
'state': lambda *a: 'open',
332
'type': lambda *a: 'activity',
333
'section_id': crm_case._get_section,
334
'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'crm.lead', context=c),
335
'priority': lambda *a: crm.crm.AVAILABLE_PRIORITIES[2][0],
336
'stage_id': _get_stage_id,
339
def message_new(self, cr, uid, msg, context=None):
341
Automatically calls when new email message arrives
343
@param self: The object pointer
344
@param cr: the current row, from the database cursor,
345
@param uid: the current user's ID for security checks
347
mailgate_pool = self.pool.get('email.server.tools')
348
subject = msg.get('subject')
349
body = msg.get('body')
350
msg_from = msg.get('from')
351
priority = msg.get('priority')
355
'email_from': msg_from,
356
'email_cc': msg.get('cc'),
360
if msg.get('priority', False):
361
vals['priority'] = priority
363
res = mailgate_pool.get_partner(cr, uid, msg.get('from') or msg.get_unixfrom())
366
res = self.create(cr, uid, vals, context)
367
attachments = msg.get('attachments', [])
368
for attachment in attachments or []:
371
'datas':binascii.b2a_base64(str(attachments.get(attachment))),
372
'datas_fname': attachment,
373
'description': 'Mail attachment',
374
'res_model': self._name,
377
self.pool.get('ir.attachment').create(cr, uid, data_attach)
383
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
1
##############################################################################
3
# OpenERP, Open Source Management Solution
4
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
6
# This program is free software: you can redistribute it and/or modify
7
# it under the terms of the GNU Affero General Public License as
8
# published by the Free Software Foundation, either version 3 of the
9
# License, or (at your option) any later version.
11
# This program is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
# GNU Affero General Public License for more details.
16
# You should have received a copy of the GNU Affero General Public License
17
# along with this program. If not, see <http://www.gnu.org/licenses/>.
19
##############################################################################
21
from osv import fields, osv
22
from datetime import datetime
25
from tools.translate import _
26
from crm.crm import crm_case
34
('cancel', 'Cancelled'),
36
('pending', 'Pending'),
37
('ready', 'Intake OK'),
38
('planned', 'Planned'),
42
class crm_case_stage(osv.osv):
44
_inherit = "crm.case.stage"
46
def _get_type_value(self, cr, user, context):
47
return [('lead','Lead'),('opportunity','Opportunity'),('activity','Activity')]
50
'type': fields.selection(_get_type_value, 'Type'),
55
class crm_activities(crm_case, osv.osv):
56
""" CRM Activity Case """
57
_name = "crm.activities"
58
_description = "Case Driven Activities"
59
_order = "date_action, priority, id desc"
60
_inherit = ['mailgate.thread','res.partner.address','crm.lead']
62
def _get_stage_id(self, cr, uid, context={}):
65
stage_pool = self.pool.get('crm.case.stage')
66
stage_type = context and context.get('stage_type','')
67
logging.getLogger('crm_enhancements').warning("Stage Type %s", stage_type)
70
domain = [('type', '=', stage_type)]
71
stages = stage_pool.search(cr, uid, domain, order='sequence')
74
def action_makeMeeting(self, cr, uid, ids, context=None):
75
logging.getLogger('crm_activities').warning("Context %s", context)
77
This opens Meeting's calendar view to schedule meeting on current Opportunity
78
@param self: The object pointer
80
@param cr: the current row, from the database cursor,
81
@param uid: the current user's ID for security checks,
82
@param ids: List of Opportunity to Meeting IDs
83
@param context: A standard dictionary for contextual values
85
@return : Dictionary value for created Meeting view
88
for opp in self.browse(cr, uid, ids, context=context):
89
data_obj = self.pool.get('ir.model.data')
92
result = data_obj._get_id(cr, uid, 'crm', 'view_crm_case_meetings_filter')
93
res = data_obj.read(cr, uid, result, ['res_id'])
94
id1 = data_obj._get_id(cr, uid, 'crm_activities', 'crm_case_calendar_view_meet')
95
id2 = data_obj._get_id(cr, uid, 'crm_activities', 'crm_case_form_view_meet')
96
id3 = data_obj._get_id(cr, uid, 'crm_activities', 'crm_case_tree_view_meet')
98
id1 = data_obj.browse(cr, uid, id1, context=context).res_id
100
id2 = data_obj.browse(cr, uid, id2, context=context).res_id
102
id3 = data_obj.browse(cr, uid, id3, context=context).res_id
105
'default_opportunity_id': opp.id,
106
'default_partner_id': opp.partner_id and opp.partner_id.id or False,
107
'default_user_id': context['uid'],
108
'default_section_id': opp.section_id and opp.section_id.id or False,
109
'default_email_from': opp.email_from,
110
'default_state': 'open',
111
'default_name': opp.name
113
logging.getLogger('crm_activities').warning("Context 2: %s", context)
115
'name': _('Meetings'),
118
'view_mode': 'calendar,form,tree',
119
'res_model': 'crm.meeting.activities',
121
'views': [(id1, 'calendar'), (id2, 'form'), (id3, 'tree')],
122
'type': 'ir.actions.act_window',
123
'search_view_id': res['res_id'],
128
def _compute_day(self, cr, uid, ids, fields, args, context=None):
130
@param cr: the current row, from the database cursor,
131
@param uid: the current user's ID for security checks,
132
@param ids: List of Openday's IDs
133
@return: difference between current date and log date
134
@param context: A standard dictionary for contextual values
136
cal_obj = self.pool.get('resource.calendar')
137
res_obj = self.pool.get('resource.resource')
140
for lead in self.browse(cr, uid, ids, context=context):
145
if field == 'day_open':
147
date_create = datetime.strptime(lead.create_date, "%Y-%m-%d %H:%M:%S")
148
date_open = datetime.strptime(lead.date_open, "%Y-%m-%d %H:%M:%S")
149
ans = date_open - date_create
150
date_until = lead.date_open
151
elif field == 'day_close':
153
date_create = datetime.strptime(lead.create_date, "%Y-%m-%d %H:%M:%S")
154
date_close = datetime.strptime(lead.date_closed, "%Y-%m-%d %H:%M:%S")
155
date_until = lead.date_closed
156
ans = date_close - date_create
160
resource_ids = res_obj.search(cr, uid, [('user_id','=',lead.user_id.id)])
161
if len(resource_ids):
162
resource_id = resource_ids[0]
164
duration = float(ans.days)
165
if lead.section_id and lead.section_id.resource_calendar_id:
166
duration = float(ans.days) * 24
167
new_dates = cal_obj.interval_get(cr,
169
lead.section_id.resource_calendar_id and lead.section_id.resource_calendar_id.id or False,
170
datetime.strptime(lead.create_date, '%Y-%m-%d %H:%M:%S'),
175
date_until = datetime.strptime(date_until, '%Y-%m-%d %H:%M:%S')
176
for in_time, out_time in new_dates:
177
if in_time.date not in no_days:
178
no_days.append(in_time.date)
179
if out_time > date_until:
181
duration = len(no_days)
182
res[lead.id][field] = abs(int(duration))
185
def onchange_section_id(self, cr, uid, ids, section_id, context={}):
187
logging.getLogger('crm_enhancements').warning("Value sent %s", section_id)
189
sid = self.pool.get('crm.case.section').browse(cr,uid,section_id)
190
v = { 'user_id':sid.user_id.id }
193
def _get_attach_ids(self, cr, uid, ids, field_name, arg, context={}):
195
for record in self.browse(cr, uid, ids, context=context):
196
if record.message_ids:
198
for msgid in record.message_ids:
199
for attachid in msgid.attachment_ids:
200
result[record.id].append(attachid.id)
202
result[record.id]= False
205
def _get_comms_ids(self, cr, uid, ids, field_name, arg, context={}):
207
for record in self.browse(cr, uid, ids, context=context):
208
if record.message_ids:
210
for msgid in record.message_ids:
211
if ( msgid.history or msgid.name.upper() == "NOTE" ) :
212
if ( field_name=='communication_ids'):
213
result[record.id].append(msgid.id)
214
elif ( field_name=='history_ids'):
215
result[record.id].append(msgid.id)
217
result[record.id]= False
220
def case_ready(self, cr, uid, ids, *args):
222
@param self: The object pointer
223
@param cr: the current row, from the database cursor,
224
@param uid: the current user's ID for security checks,
225
@param ids: List of case Ids
226
@param *args: Tuple Value for additional Params
228
cases = self.browse(cr, uid, ids)
229
cases[0].state # to fill the browse record cache
230
self._history(cr, uid, cases, _('Ready'))
231
self.write(cr, uid, ids, {'state': 'ready'})
233
# We use the cache of cases to keep the old case state
235
self._action(cr, uid, cases, 'ready')
238
def case_planned(self, cr, uid, ids, *args):
239
"""Case is effectively planned
240
@param self: The object pointer
241
@param cr: the current row, from the database cursor,
242
@param uid: the current user's ID for security checks,
243
@param ids: List of case Ids
244
@param *args: Tuple Value for additional Params
246
cases = self.browse(cr, uid, ids)
247
cases[0].state # to fill the browse record cache
248
self._history(cr, uid, cases, _('Planned'))
249
self.write(cr, uid, ids, {'state': 'planned'})
251
# We use the cache of cases to keep the old case state
253
self._action(cr, uid, cases, 'planned')
257
# Overridden from res.partner.address:
258
'partner_id': fields.many2one('res.partner', 'Partner', ondelete='set null',
259
select=True, help="Optional linked partner, usually after conversion of the lead"),
260
'partner_address_id': fields.many2one('res.partner.address', 'Partner Contact', \
261
domain="[('partner_id','=',partner_id)]"),
264
'id': fields.integer('ID'),
265
'name': fields.char('Name', size=64),
266
'active': fields.boolean('Active', required=False),
267
'date_action_last': fields.datetime('Last Action', readonly=1),
268
'date_action_next': fields.datetime('Next Action', readonly=1),
269
'email_from': fields.char('Email', size=128, help="E-mail address of the contact"),
270
'section_id': fields.many2one('crm.case.section', 'Section', \
271
select=True, help='Sales team to which this case belongs to. Defines responsible user and e-mail address for the mail gateway.'),
272
'create_date': fields.datetime('Creation Date' , readonly=True),
273
'email_cc': fields.text('Global CC', size=252 , help="These email addresses will be added to the CC field of all inbound and outbound emails for this record before being sent. Separate multiple email addresses with a comma"),
274
'description': fields.text('Notes'),
275
'write_date': fields.datetime('Update Date' , readonly=True),
278
'categ_id': fields.many2one('crm.case.categ', 'Category', \
279
domain="['|',('section_id','=',section_id),('section_id','=',False), ('object_id.model', '=', 'crm.lead')]"),
280
'type_id': fields.many2one('crm.case.resource.type', 'Campaign', \
281
domain="['|',('section_id','=',section_id),('section_id','=',False)]"),
282
'channel_id': fields.many2one('res.partner.canal', 'Channel'),
284
'contact_name': fields.char('Contact Name', size=64),
285
'partner_name': fields.char("Customer Name", size=64,help='The name of the future partner that will be created while converting the into opportunity'),
286
'optin': fields.boolean('Opt-In', help="If opt-in is checked, this contact has accepted to receive emails."),
287
'optout': fields.boolean('Opt-Out', help="If opt-out is checked, this contact has refused to receive emails or unsubscribed to a campaign."),
288
'type':fields.selection([
289
('activity','Activity'),
290
],'Type', help="Type is used to separate different types of production entities"),
291
'priority': fields.selection(crm.crm.AVAILABLE_PRIORITIES, 'Priority'),
292
'date_closed': fields.datetime('Closed', readonly=True),
293
'stage_id': fields.many2one('crm.case.stage', 'Stage', domain="[('type','=','activity')]"),
294
'user_id': fields.many2one('res.users', 'Responsible',help='By Default Salesman is Administrator when create New User'),
295
'engineer_id': fields.many2one('res.users', 'Planned for',help='The appointed engineer to execute the call'),
296
'referred': fields.char('Referred By', size=64),
297
'date_open': fields.datetime('Opened', readonly=True),
298
'day_open': fields.function(_compute_day, string='Days to Open', \
299
method=True, multi='day_open', type="float", store=True),
300
'day_close': fields.function(_compute_day, string='Days to Close', \
301
method=True, multi='day_close', type="float", store=True),
302
'state': fields.selection(AVAILABLE_STATES, 'State', size=16, readonly=True,
303
help='The state is set to \'Draft\', when a case is created.\
304
\nIf the case is in progress the state is set to \'Open\'.\
305
\nWhen the case is over, the state is set to \'Done\'.\
306
\nIf the case needs to be reviewed then the state is set to \'Pending\'.'),
307
'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('model','=',_name)]),
310
'probability': fields.float('Probability (%)',group_operator="avg"),
311
'planned_revenue': fields.float('Expected Revenue'),
312
'ref': fields.reference('Reference', selection=crm.crm._links_get, size=128),
313
'ref2': fields.reference('Reference 2', selection=crm.crm._links_get, size=128),
314
'phone': fields.char("Phone", size=64),
315
'date_deadline': fields.date('Expected Closing'),
316
'date_action': fields.date('Next Action Date'),
317
'title_action': fields.char('Next Action', size=64),
319
# CRM enhancements fields
320
'attachment_ids' : fields.function(_get_attach_ids,method=True,type="many2many",string="Attachments",relation="ir.attachment"),
321
'communication_ids' : fields.function(_get_comms_ids,method=True,type="many2many",string="Communication Items",relation="mailgate.message"),
322
'history_ids' : fields.function(_get_comms_ids,method=True,type="many2many",string="History Items",relation="mailgate.message"),
328
'active': lambda *a: 1,
329
'user_id': crm_case._get_default_user,
330
'email_from': crm_case._get_default_email,
331
'state': lambda *a: 'open',
332
'type': lambda *a: 'activity',
333
'section_id': crm_case._get_section,
334
'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'crm.lead', context=c),
335
'priority': lambda *a: crm.crm.AVAILABLE_PRIORITIES[2][0],
336
'stage_id': _get_stage_id,
339
def message_new(self, cr, uid, msg, context=None):
341
Automatically calls when new email message arrives
343
@param self: The object pointer
344
@param cr: the current row, from the database cursor,
345
@param uid: the current user's ID for security checks
347
mailgate_pool = self.pool.get('email.server.tools')
348
subject = msg.get('subject')
349
body = msg.get('body')
350
msg_from = msg.get('from')
351
priority = msg.get('priority')
355
'email_from': msg_from,
356
'email_cc': msg.get('cc'),
360
if msg.get('priority', False):
361
vals['priority'] = priority
363
res = mailgate_pool.get_partner(cr, uid, msg.get('from') or msg.get_unixfrom())
366
res = self.create(cr, uid, vals, context)
367
attachments = msg.get('attachments', [])
368
for attachment in attachments or []:
371
'datas':binascii.b2a_base64(str(attachments.get(attachment))),
372
'datas_fname': attachment,
373
'description': 'Mail attachment',
374
'res_model': self._name,
377
self.pool.get('ir.attachment').create(cr, uid, data_attach)
383
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: