diff --git a/addons/base_action_rule/base_action_rule.py b/addons/base_action_rule/base_action_rule.py index df2d43d3a53..77446c633ee 100644 --- a/addons/base_action_rule/base_action_rule.py +++ b/addons/base_action_rule/base_action_rule.py @@ -33,20 +33,99 @@ class base_action_rule(osv.osv): _name = 'base.action.rule' _description = 'Action Rules' + + def _state_get(self, cr, uid, context={}): + """ Get State + @param self: The object pointer + @param cr: the current row, from the database cursor, + @param uid: the current user’s ID for security checks, + @param context: A standard dictionary for contextual values """ + return self.state_get(cr, uid, context=context) + + + def state_get(self, cr, uid, context={}): + """ Get State + @param self: The object pointer + @param cr: the current row, from the database cursor, + @param uid: the current user’s ID for security checks, + @param context: A standard dictionary for contextual values """ + + return [('','')] + _columns = { 'name': fields.many2one('ir.model', 'Model', required=True), 'max_level': fields.integer('Max Level', help='Specifies maximum level.'), - 'rule_lines': fields.one2many('base.action.rule.line','rule_id','Rule Lines'), 'create_date': fields.datetime('Create Date', readonly=1), - 'active': fields.boolean('Active') + 'active': fields.boolean('Active', help="If the active field is set to true,\ + it will allow you to hide the rule without removing it."), + 'sequence': fields.integer('Sequence', help="Gives the sequence order when\ + displaying a list of rules."), + 'trg_date_type': fields.selection([ + ('none','None'), + ('create','Creation Date'), + ('action_last','Last Action Date'), + ('date','Date'), + ('deadline', 'Deadline'), + ], 'Trigger Date', size=16), + 'trg_date_range': fields.integer('Delay after trigger date',help="Delay After Trigger Date,\ + specifies you can put a negative number " \ + "if you need a delay before the trigger date, like sending a reminder 15 minutes before a meeting."), + 'trg_date_range_type': fields.selection([('minutes', 'Minutes'),('hour','Hours'),\ + ('day','Days'),('month','Months')], 'Delay type'), + + + 'trg_user_id': fields.many2one('res.users', 'Responsible'), + + 'trg_partner_id': fields.many2one('res.partner', 'Partner'), + 'trg_partner_categ_id': fields.many2one('res.partner.category', 'Partner Category'), + 'trg_state_from': fields.selection(_state_get, 'State', size=16), + 'trg_state_to': fields.selection(_state_get, 'Button Pressed', size=16), + + 'act_method': fields.char('Call Object Method', size=64), + 'act_user_id': fields.many2one('res.users', 'Set responsible to'), + 'act_state': fields.selection(_state_get, 'Set state to', size=16), + 'act_email_cc': fields.char('Add watchers (Cc)', size=250, help="These people\ + will receive a copy of the future communication between partner and users by email"), + + 'act_remind_partner': fields.boolean('Remind Partner', help="Check this if\ + you want the rule to send a reminder by email to the partner."), + 'act_remind_user': fields.boolean('Remind responsible', help="Check this if \ + you want the rule to send a reminder by email to the user."), + 'act_reply_to': fields.char('Reply-To', size=64), + 'act_remind_attach': fields.boolean('Remind with attachment', help="Check this if\ + you want that all documents attached to the object be attached \ + to the reminder email sent."), + + 'act_mail_to_user': fields.boolean('Mail to responsible',help="Check this if \ + you want the rule to send an email to the responsible person."), + 'act_mail_to_watchers': fields.boolean('Mail to watchers (CC)',help="Check this\ + if you want the rule to mark CC(mail to any other person\ + defined in actions)."), + 'act_mail_to_email': fields.char('Mail to these emails', size=128,help="Email-id \ + of the persons whom mail is to be sent"), + 'act_mail_body': fields.text('Mail body',help="Content of mail"), + 'regex_name': fields.char('Regular Expression on Model Name', size=128), + 'server_action_id': fields.many2one('ir.actions.server','Server Action',help="Describes the\ + action name." \ + "eg:on which object which action to be taken on basis of which condition"), + 'domain':fields.char('Domain', size=124, required=False, readonly=False), } _defaults = { 'active': lambda *a: True, 'max_level': lambda *a: 15, + 'trg_date_type': lambda *a: 'none', + 'trg_date_range_type': lambda *a: 'day', + 'act_mail_to_user': lambda *a: 0, + 'act_remind_partner': lambda *a: 0, + 'act_remind_user': lambda *a: 0, + 'act_mail_to_watchers': lambda *a: 0, + 'domain': lambda *a: '[]' } - + + _order = 'sequence' + def format_body(self, body): """ Foramat Action rule's body @param self: The object pointer """ @@ -56,7 +135,6 @@ class base_action_rule(osv.osv): def format_mail(self, obj, body): """ Foramat Mail @param self: The object pointer """ - data = { 'object_id': obj.id, 'object_subject': hasattr(obj, 'name') and obj.name or False, @@ -105,6 +183,10 @@ class base_action_rule(osv.osv): @param context: A standard dictionary for contextual values """ ok = True + if eval(action.domain): + obj_ids = obj._table.search(cr, uid, eval(action.domain), context=context) + if not obj.id in obj_ids: + ok = False if hasattr(obj, 'user_id'): ok = ok and (not action.trg_user_id.id or action.trg_user_id.id==obj.user_id.id) if hasattr(obj, 'partner_id'): @@ -122,10 +204,6 @@ class base_action_rule(osv.osv): if state_to: ok = ok and (not action.trg_state_to or action.trg_state_to==state_to) - if hasattr(obj, 'priority'): - ok = ok and (not action.trg_priority_from or action.trg_priority_from>=obj.priority) - ok = ok and (not action.trg_priority_to or action.trg_priority_to<=obj.priority) - reg_name = action.regex_name result_name = True if reg_name: @@ -163,10 +241,6 @@ class base_action_rule(osv.osv): obj.categ_id = action.act_categ_id write['categ_id'] = action.act_categ_id.id - if hasattr(obj, 'priority') and action.act_priority: - obj.priority = action.act_priority - write['priority'] = action.act_priority - model_obj.write(cr, uid, [obj.id], write, context) if hasattr(model_obj, 'remind_user') and action.act_remind_user: @@ -198,178 +272,59 @@ class base_action_rule(osv.osv): @param ids: List of Basic Action Rule’s IDs, @param objects: pass objects @param context: A standard dictionary for contextual values """ - if not scrit: scrit = [] - rule_line_obj = self.pool.get('base.action.rule.line') - for rule in self.browse(cr, uid, ids): - level = rule.max_level + cr.execute("select id from base_action_rule order by sequence") + rule_ids = map(lambda x: x[0], cr.fetchall()) + for action in self.browse(cr, uid, rule_ids): + level = action.max_level if not level: break - newactions = [] - scrit += [('rule_id','=',rule.id)] - line_ids = rule_line_obj.search(cr, uid, scrit) - actions = rule_line_obj.browse(cr, uid, line_ids, context=context) - model_obj = self.pool.get(rule.name.model) + model_obj = self.pool.get(action.name.model) for obj in objects: - for action in actions: - ok = self.do_check(cr, uid, action, obj, context=context) - if not ok: - continue + ok = self.do_check(cr, uid, action, obj, context=context) + if not ok: + continue - base = False - if hasattr(obj, 'create_date') and action.trg_date_type=='create': - base = mx.DateTime.strptime(obj.create_date[:19], '%Y-%m-%d %H:%M:%S') - elif hasattr(obj, 'create_date') and action.trg_date_type=='action_last': - if hasattr(obj, 'date_action_last') and obj.date_action_last: - base = mx.DateTime.strptime(obj.date_action_last, '%Y-%m-%d %H:%M:%S') - else: - base = mx.DateTime.strptime(obj.create_date[:19], '%Y-%m-%d %H:%M:%S') - elif hasattr(obj, 'date_deadline') and action.trg_date_type=='deadline' \ - and obj.date_deadline: - base = mx.DateTime.strptime(obj.date_deadline, '%Y-%m-%d %H:%M:%S') - elif hasattr(obj, 'date') and action.trg_date_type=='date' and obj.date: - base = mx.DateTime.strptime(obj.date, '%Y-%m-%d %H:%M:%S') - if base: - fnct = { - 'minutes': lambda interval: mx.DateTime.RelativeDateTime(minutes=interval), - 'day': lambda interval: mx.DateTime.RelativeDateTime(days=interval), - 'hour': lambda interval: mx.DateTime.RelativeDateTime(hours=interval), - 'month': lambda interval: mx.DateTime.RelativeDateTime(months=interval), - } - d = base + fnct[action.trg_date_range_type](action.trg_date_range) - dt = d.strftime('%Y-%m-%d %H:%M:%S') - ok = False - if hasattr(obj, 'date_action_last') and hasattr(obj, 'date_action_next'): - ok = (dt <= time.strftime('%Y-%m-%d %H:%M:%S')) and \ - ((not obj.date_action_next) or \ - (dt >= obj.date_action_next and \ - obj.date_action_last < obj.date_action_next)) - if not ok: - if not obj.date_action_next or dt < obj.date_action_next: - obj.date_action_next = dt - model_obj.write(cr, uid, [obj.id], {'date_action_next': dt}, context) + base = False + if hasattr(obj, 'create_date') and action.trg_date_type=='create': + base = mx.DateTime.strptime(obj.create_date[:19], '%Y-%m-%d %H:%M:%S') + elif hasattr(obj, 'create_date') and action.trg_date_type=='action_last': + if hasattr(obj, 'date_action_last') and obj.date_action_last: + base = mx.DateTime.strptime(obj.date_action_last, '%Y-%m-%d %H:%M:%S') else: - ok = action.trg_date_type=='none' - - if ok: - self.do_action(cr, uid, action, model_obj, obj, context) - break + base = mx.DateTime.strptime(obj.create_date[:19], '%Y-%m-%d %H:%M:%S') + elif hasattr(obj, 'date_deadline') and action.trg_date_type=='deadline' \ + and obj.date_deadline: + base = mx.DateTime.strptime(obj.date_deadline, '%Y-%m-%d %H:%M:%S') + elif hasattr(obj, 'date') and action.trg_date_type=='date' and obj.date: + base = mx.DateTime.strptime(obj.date, '%Y-%m-%d %H:%M:%S') + if base: + fnct = { + 'minutes': lambda interval: mx.DateTime.RelativeDateTime(minutes=interval), + 'day': lambda interval: mx.DateTime.RelativeDateTime(days=interval), + 'hour': lambda interval: mx.DateTime.RelativeDateTime(hours=interval), + 'month': lambda interval: mx.DateTime.RelativeDateTime(months=interval), + } + d = base + fnct[action.trg_date_range_type](action.trg_date_range) + dt = d.strftime('%Y-%m-%d %H:%M:%S') + ok = False + if hasattr(obj, 'date_action_last') and hasattr(obj, 'date_action_next'): + ok = (dt <= time.strftime('%Y-%m-%d %H:%M:%S')) and \ + ((not obj.date_action_next) or \ + (dt >= obj.date_action_next and \ + obj.date_action_last < obj.date_action_next)) + if not ok: + if not obj.date_action_next or dt < obj.date_action_next: + obj.date_action_next = dt + model_obj.write(cr, uid, [obj.id], {'date_action_next': dt}, context) + else: + ok = action.trg_date_type=='none' + if ok: + self.do_action(cr, uid, action, model_obj, obj, context) + break level -= 1 return True -base_action_rule() - -class base_action_rule_line(osv.osv): - _name = 'base.action.rule.line' - _description = 'Action Rule Lines' - - def _state_get(self, cr, uid, context={}): - """ Get State - @param self: The object pointer - @param cr: the current row, from the database cursor, - @param uid: the current user’s ID for security checks, - @param context: A standard dictionary for contextual values """ - - return self.state_get(cr, uid, context=context) - def _priority_get(self, cr, uid, context={}): - """ Get Priority - @param self: The object pointer - @param cr: the current row, from the database cursor, - @param uid: the current user’s ID for security checks, - @param context: A standard dictionary for contextual values """ - - return self.priority_get(cr, uid, context=context) - - def state_get(self, cr, uid, context={}): - """ Get State - @param self: The object pointer - @param cr: the current row, from the database cursor, - @param uid: the current user’s ID for security checks, - @param context: A standard dictionary for contextual values """ - - return [('','')] - def priority_get(self, cr, uid, context={}): - """ Get Priority - @param self: The object pointer - @param cr: the current row, from the database cursor, - @param uid: the current user’s ID for security checks, - @param context: A standard dictionary for contextual values """ - - return [('','')] - - _columns = { - 'name': fields.char('Rule Name',size=64, required=True), - 'rule_id': fields.many2one('base.action.rule','Rule'), - 'active': fields.boolean('Active', help="If the active field is set to true,\ - it will allow you to hide the rule without removing it."), - 'sequence': fields.integer('Sequence', help="Gives the sequence order when\ - displaying a list of rules."), - - 'trg_date_type': fields.selection([ - ('none','None'), - ('create','Creation Date'), - ('action_last','Last Action Date'), - ('date','Date'), - ('deadline', 'Deadline'), - ], 'Trigger Date', size=16), - 'trg_date_range': fields.integer('Delay after trigger date',help="Delay After Trigger Date,\ - specifies you can put a negative number " \ - "if you need a delay before the trigger date, like sending a reminder 15 minutes before a meeting."), - 'trg_date_range_type': fields.selection([('minutes', 'Minutes'),('hour','Hours'),\ - ('day','Days'),('month','Months')], 'Delay type'), - - - 'trg_user_id': fields.many2one('res.users', 'Responsible'), - - 'trg_partner_id': fields.many2one('res.partner', 'Partner'), - 'trg_partner_categ_id': fields.many2one('res.partner.category', 'Partner Category'), - 'trg_state_from': fields.selection(_state_get, 'State', size=16), - 'trg_state_to': fields.selection(_state_get, 'Button Pressed', size=16), - 'trg_priority_from': fields.selection(_priority_get, 'Minimum Priority'), - 'trg_priority_to': fields.selection(_priority_get, 'Maximum Priority'), - - 'act_method': fields.char('Call Object Method', size=64), - 'act_user_id': fields.many2one('res.users', 'Set responsible to'), - 'act_state': fields.selection(_state_get, 'Set state to', size=16), - 'act_priority': fields.selection(_priority_get, 'Set priority to'), - 'act_email_cc': fields.char('Add watchers (Cc)', size=250, help="These people\ - will receive a copy of the future communication between partner and users by email"), - - 'act_remind_partner': fields.boolean('Remind Partner', help="Check this if\ - you want the rule to send a reminder by email to the partner."), - 'act_remind_user': fields.boolean('Remind responsible', help="Check this if \ - you want the rule to send a reminder by email to the user."), - 'act_reply_to': fields.char('Reply-To', size=64), - 'act_remind_attach': fields.boolean('Remind with attachment', help="Check this if\ - you want that all documents attached to the object be attached \ - to the reminder email sent."), - - 'act_mail_to_user': fields.boolean('Mail to responsible',help="Check this if \ - you want the rule to send an email to the responsible person."), - 'act_mail_to_watchers': fields.boolean('Mail to watchers (CC)',help="Check this\ - if you want the rule to mark CC(mail to any other person\ - defined in actions)."), - 'act_mail_to_email': fields.char('Mail to these emails', size=128,help="Email-id \ - of the persons whom mail is to be sent"), - 'act_mail_body': fields.text('Mail body',help="Content of mail"), - 'regex_name': fields.char('Regular Expression on Model Name', size=128), - 'server_action_id': fields.many2one('ir.actions.server','Server Action',help="Describes the\ - action name." \ - "eg:on which object which action to be taken on basis of which condition"), - } - - _defaults = { - 'active': lambda *a: 1, - 'trg_date_type': lambda *a: 'none', - 'trg_date_range_type': lambda *a: 'day', - 'act_mail_to_user': lambda *a: 0, - 'act_remind_partner': lambda *a: 0, - 'act_remind_user': lambda *a: 0, - 'act_mail_to_watchers': lambda *a: 0, - } - - _order = 'sequence' - def _check_mail(self, cr, uid, ids, context=None): """ Check Mail @@ -393,6 +348,6 @@ class base_action_rule_line(osv.osv): (_check_mail, 'Error: The mail is not well formated', ['act_mail_body']), ] -base_action_rule_line() +base_action_rule() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/base_action_rule/base_action_rule_view.xml b/addons/base_action_rule/base_action_rule_view.xml index 09bbb2e2f5f..f7a476fd09e 100644 --- a/addons/base_action_rule/base_action_rule_view.xml +++ b/addons/base_action_rule/base_action_rule_view.xml @@ -16,52 +16,9 @@
+ - - - - - - - - - - base.action.rule.tree - base.action.rule - tree - - - - - - - - - - - - - Action Rules - base.action.rule - form - tree,form - - - - - - - - base.action.rule.line.form - base.action.rule.line - form - -
- - + @@ -79,11 +36,6 @@ - - - - - @@ -100,7 +52,6 @@ - @@ -117,7 +68,9 @@ - + + -
+ - + - - base.action.rule.line.tree - base.action.rule.line + + base.action.rule.tree + base.action.rule tree - - - + + + + + + + + + + + Action Rules + base.action.rule + form + tree,form + - + + diff --git a/addons/base_action_rule/security/ir.model.access.csv b/addons/base_action_rule/security/ir.model.access.csv index 982dfdebfb5..99e4fc07c4b 100644 --- a/addons/base_action_rule/security/ir.model.access.csv +++ b/addons/base_action_rule/security/ir.model.access.csv @@ -1,3 +1,2 @@ "id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" "access_base_action_rule","base.action.rule","model_base_action_rule",,1,1,1,1 -"access_base_action_rule_line","base.action.rule.line","model_base_action_rule_line",,1,1,1,1 diff --git a/addons/base_calendar/base_calendar.py b/addons/base_calendar/base_calendar.py index f4f1e68a269..372218b8088 100644 --- a/addons/base_calendar/base_calendar.py +++ b/addons/base_calendar/base_calendar.py @@ -29,6 +29,7 @@ import pytz import re import time import tools +from caldav import caldav months = { 1: "January", 2: "February", 3: "March", 4: "April", \ @@ -1213,7 +1214,52 @@ e.g.: Every other month on the last Sunday of the month for 10 occurrences:\ if isinstance(select, (str, int, long)): return ids and ids[0] or False return ids - + + def check_import(self, cr, uid, vals, context={}): + """ + @param self: The object pointer + @param cr: the current row, from the database cursor, + @param uid: the current user’s ID for security checks, + @param vals: Get Values + @param context: A standard dictionary for contextual values + """ + ids = [] + model_obj = self.pool.get(context.get('model')) + recur_pool = {} + try: + for val in vals: + exists, r_id = caldav.uid2openobjectid(cr, val['id'], context.get('model'), \ + val.get('recurrent_id')) + if val.has_key('create_date'): val.pop('create_date') + u_id = val.get('id', None) + val.pop('id') + if exists and r_id: + val.update({'recurrent_uid': exists}) + model_obj.write(cr, uid, [r_id], val) + ids.append(r_id) + elif exists: + # Compute value of duration + if 'date_deadline' in val and 'duration' not in val: + start = datetime.strptime(val['date'], '%Y-%m-%d %H:%M:%S') + end = datetime.strptime(val['date_deadline'], '%Y-%m-%d %H:%M:%S') + diff = end - start + val['duration'] = (diff.seconds/float(86400) + diff.days) * 24 + model_obj.write(cr, uid, [exists], val) + ids.append(exists) + else: + if u_id in recur_pool and val.get('recurrent_id'): + val.update({'recurrent_uid': recur_pool[u_id]}) + revent_id = model_obj.create(cr, uid, val) + ids.append(revent_id) + else: + event_id = model_obj.create(cr, uid, val) + recur_pool[u_id] = event_id + ids.append(event_id) + except Exception, e: + raise osv.except_osv(('Error !'), (str(e))) + return ids + + def compute_rule_string(self, cr, uid, datas, context=None, *args): """ Compute rule string. diff --git a/addons/base_calendar/base_calendar_view.xml b/addons/base_calendar/base_calendar_view.xml index 2a48c0be32f..d9acae67a9e 100755 --- a/addons/base_calendar/base_calendar_view.xml +++ b/addons/base_calendar/base_calendar_view.xml @@ -190,7 +190,7 @@ + on_change="onchange_dates(date,duration,False,allday)" attrs="{'invisible': [('allday', '=', True)]}"/> diff --git a/addons/crm/__init__.py b/addons/crm/__init__.py index 4931c46b328..e4b80da6ff2 100644 --- a/addons/crm/__init__.py +++ b/addons/crm/__init__.py @@ -24,8 +24,9 @@ import crm_mailgate import crm_action_rule import crm_segmentation import crm_meeting +import crm_opportunity +import crm_lead import crm_phonecall -import crm_claim import crm_fundraising import crm_helpdesk @@ -34,6 +35,5 @@ import wizard - # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/crm/__openerp__.py b/addons/crm/__openerp__.py index 9c5702c800b..ecf7d33261b 100644 --- a/addons/crm/__openerp__.py +++ b/addons/crm/__openerp__.py @@ -26,7 +26,7 @@ 'category': 'Generic Modules/CRM & SRM', 'description': """The generic Open ERP Customer Relationship Management system enables a group of people to intelligently and efficiently manage -leads, opportunities, claims, meeting, phonecall etc. +leads, opportunities, meeting, phonecall etc. It manages key tasks such as communication, identification, prioritization, assignment, resolution and notification. @@ -54,33 +54,61 @@ between mails and Open ERP.""", ], 'init_xml': [ 'crm_data.xml', + 'crm_meeting_data.xml', + 'crm_lead_data.xml', + 'crm_meeting_data.xml', + 'crm_opportunity_data.xml', + 'crm_phonecall_data.xml', ], 'update_xml': [ + 'wizard/crm_lead_to_partner_view.xml', + 'wizard/crm_lead_to_opportunity_view.xml', + + 'wizard/crm_phonecall_to_phonecall_view.xml', + 'wizard/crm_phonecall_to_partner_view.xml', + 'wizard/crm_phonecall_to_opportunity_view.xml', + + 'wizard/crm_opportunity_to_phonecall_view.xml', + 'wizard/crm_partner_to_opportunity_view.xml', + 'wizard/crm_send_email_view.xml', 'wizard/crm_email_add_cc_view.xml', 'crm_view.xml', + 'crm_action_rule_view.xml', + 'crm_lead_view.xml', + 'crm_lead_menu.xml', + 'crm_meeting_view.xml', + 'crm_meeting_menu.xml', + 'crm_phonecall_view.xml', + 'crm_phonecall_menu.xml', + 'crm_opportunity_view.xml', + 'crm_opportunity_menu.xml', 'security/crm_security.xml', 'security/ir.model.access.csv', 'report/crm_report_view.xml', - + 'report/crm_lead_report_view.xml', + 'report/crm_opportunity_report_view.xml' , + 'report/crm_phonecall_report_view.xml', + 'process/crm_configuration_process.xml', ], 'demo_xml': [ 'crm_demo.xml', - + 'crm_lead_demo.xml', + 'crm_meeting_demo.xml', + 'crm_opportunity_demo.xml', + 'crm_phonecall_demo.xml' ], -# 'test': [#'test/test_crm_lead.yml', -# 'test/test_crm_opportunity.yml', -# 'test/test_crm_phonecall.yml', -# 'test/test_crm_fund.yml', -# 'test/test_crm_claim.yml', -# 'test/test_crm_helpdesk.yml', -# 'test/test_crm_meeting.yml', -# ], + 'test': [ + 'test/test_crm_meeting.yml', + 'test/test_crm_lead.yml', + 'test/test_crm_opportunity.yml', + 'test/test_crm_phonecall.yml', + ], 'installable': True, 'active': False, 'certificate': '0079056041421', diff --git a/addons/crm/crm_action_rule.py b/addons/crm/crm_action_rule.py index 718b12bb9c3..53062f4045b 100644 --- a/addons/crm/crm_action_rule.py +++ b/addons/crm/crm_action_rule.py @@ -152,6 +152,18 @@ class base_action_rule(osv.osv): """ Base Action Rule """ _inherit = 'base.action.rule' _description = 'Action Rules' + + _columns = { + 'trg_section_id': fields.many2one('crm.case.section', 'Sales Team'), + 'trg_max_history': fields.integer('Maximum Communication History'), + 'trg_categ_id': fields.many2one('crm.case.categ', 'Category'), + 'regex_history' : fields.char('Regular Expression on Case History', size=128), + 'act_section_id': fields.many2one('crm.case.section', 'Set Team to'), + 'act_categ_id': fields.many2one('crm.case.categ', 'Set Category to'), + 'act_mail_to_partner': fields.boolean('Mail to partner',help="Check this \ + if you want the rule to send an email to the partner."), + } + def email_send(self, cr, uid, obj, emails, body, emailfrom=tools.config.get('email_from',False), context={}): body = self.format_mail(obj, body) @@ -168,6 +180,17 @@ class base_action_rule(osv.osv): if not emailfrom: raise osv.except_osv(_('Error!'), _("No E-Mail ID Found for your Company address!")) + if hasattr(obj, 'section_id'): + smtp_pool = self.pool.get('email.smtpclient') + if obj.section_id and obj.section_id.server_id: + flag = smtp_pool.send_email( + cr=cr, + uid=uid, + server_id=obj.section_id.server_id.id, + emailto=emails, + subject=name, + body="
%s
" % body, + ) return tools.email_send(emailfrom, emails, name, body, reply_to=reply_to, openobject_id=str(obj.id)) def do_check(self, cr, uid, action, obj, context={}): @@ -207,7 +230,7 @@ class base_action_rule(osv.osv): res = super(base_action_rule, self).do_action(cr, uid, action, model_obj, obj, context=context) write = {} - if hasattr(action, act_section_id) and action.act_section_id: + if hasattr(action, 'act_section_id') and action.act_section_id: obj.section_id = action.act_section_id write['section_id'] = action.act_section_id.id @@ -231,13 +254,6 @@ class base_action_rule(osv.osv): return True -base_action_rule() - -class base_action_rule_line(osv.osv): - """ Base Action Rule Line """ - _inherit = 'base.action.rule.line' - _description = 'Base Action Rule Line' - def state_get(self, cr, uid, context={}): """@param self: The object pointer @@ -245,28 +261,8 @@ class base_action_rule_line(osv.osv): @param uid: the current user’s ID for security checks, @param context: A standard dictionary for contextual values """ - res = super(base_action_rule_line, self).state_get(cr, uid, context=context) - return res + [('escalate','Escalate')] + crm.AVAILABLE_STATES + res = super(base_action_rule, self).state_get(cr, uid, context=context) + return res + [('escalate', 'Escalate')] + crm.AVAILABLE_STATES - def priority_get(self, cr, uid, context={}): - """@param self: The object pointer - @param cr: the current row, from the database cursor, - @param uid: the current user’s ID for security checks, - @param context: A standard dictionary for contextual values """ - - res = super(base_action_rule_line, self).priority_get(cr, uid, context=context) - return res + crm.AVAILABLE_PRIORITIES - - _columns = { - 'trg_section_id': fields.many2one('crm.case.section', 'Sales Team'), - 'trg_max_history': fields.integer('Maximum Communication History'), - 'trg_categ_id': fields.many2one('crm.case.categ', 'Category'), - 'regex_history' : fields.char('Regular Expression on Case History', size=128), - 'act_section_id': fields.many2one('crm.case.section', 'Set Team to'), - 'act_categ_id': fields.many2one('crm.case.categ', 'Set Category to'), - 'act_mail_to_partner': fields.boolean('Mail to partner',help="Check this \ - if you want the rule to send an email to the partner."), - } - -base_action_rule_line() +base_action_rule() diff --git a/addons/crm/crm_action_rule_view.xml b/addons/crm/crm_action_rule_view.xml index 78767a2f795..6211714232c 100644 --- a/addons/crm/crm_action_rule_view.xml +++ b/addons/crm/crm_action_rule_view.xml @@ -3,9 +3,9 @@ - base.action.rule.line.form.inherit - base.action.rule.line - + base.action.rule.form.inherit + base.action.rule + form @@ -19,9 +19,9 @@ - base.action.rule.line.form2.inherit - base.action.rule.line - + base.action.rule.form2.inherit + base.action.rule + form @@ -35,9 +35,9 @@ - base.action.rule.line.form3.inherit - base.action.rule.line - + base.action.rule.form3.inherit + base.action.rule + form diff --git a/addons/crm/crm_lead.py.moved b/addons/crm/crm_lead.py.moved new file mode 100644 index 00000000000..9c4c38875c5 --- /dev/null +++ b/addons/crm/crm_lead.py.moved @@ -0,0 +1,198 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2010 Tiny SPRL (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from osv import fields, osv, orm +from datetime import datetime, timedelta +import crm +import math +import time +import mx.DateTime +from tools.translate import _ + +class crm_lead(osv.osv): + """ CRM Lead Case """ + + _name = "crm.lead" + _description = "Leads Cases" + _order = "priority, id desc" + _inherit = ['res.partner.address', 'crm.case'] + + def case_open(self, cr, uid, ids, *args): + """ + @param self: The object pointer + @param cr: the current row, from the database cursor, + @param uid: the current user’s ID for security checks, + @param ids: List of case's Ids + @param *args: Give Tuple Value + """ + + res = super(crm_lead, self).case_open(cr, uid, ids, *args) + self.write(cr, uid, ids, {'date_open': time.strftime('%Y-%m-%d %H:%M:%S')}) + return res + + def _compute_day(self, cr, uid, ids, fields, args, context={}): + """ + @param cr: the current row, from the database cursor, + @param uid: the current user’s ID for security checks, + @param ids: List of Openday’s IDs + @return: difference between current date and log date + @param context: A standard dictionary for contextual values + """ + cal_obj = self.pool.get('resource.calendar') + res_obj = self.pool.get('resource.resource') + + res = {} + for lead in self.browse(cr, uid, ids , context): + for field in fields: + res[lead.id] = {} + duration = 0 + ans = False + if field == 'day_open': + if lead.date_open: + date_create = datetime.strptime(lead.create_date, "%Y-%m-%d %H:%M:%S") + date_open = datetime.strptime(lead.date_open, "%Y-%m-%d %H:%M:%S") + ans = date_open - date_create + date_until = lead.date_open + elif field == 'day_close': + if lead.date_closed: + date_create = datetime.strptime(lead.create_date, "%Y-%m-%d %H:%M:%S") + date_close = datetime.strptime(lead.date_closed, "%Y-%m-%d %H:%M:%S") + date_until = lead.date_closed + ans = date_close - date_create + if ans: + resource_id = False + if lead.user_id: + resource_ids = res_obj.search(cr, uid, [('user_id','=',lead.user_id.id)]) + if len(resource_ids): + resource_id = resource_ids[0] + + duration = float(ans.days) + if lead.section_id.resource_calendar_id: + duration = float(ans.days) * 24 + new_dates = cal_obj.interval_get(cr, + uid, + lead.section_id.resource_calendar_id and lead.section_id.resource_calendar_id.id or False, + mx.DateTime.strptime(lead.create_date, '%Y-%m-%d %H:%M:%S'), + duration, + resource=resource_id + ) + no_days = [] + date_until = mx.DateTime.strptime(date_until, '%Y-%m-%d %H:%M:%S') + for in_time, out_time in new_dates: + if in_time.date not in no_days: + no_days.append(in_time.date) + if out_time > date_until: + break + duration = len(no_days) + res[lead.id][field] = abs(int(duration)) + return res + + _columns = { + + 'categ_id': fields.many2one('crm.case.categ', 'Lead Source', \ + domain="[('section_id','=',section_id),\ + ('object_id.model', '=', 'crm.opportunity')]"), + 'type_id': fields.many2one('crm.case.resource.type', 'Lead Type', \ + domain="[('section_id','=',section_id),\ + ('object_id.model', '=', 'crm.lead')]"), + 'partner_name': fields.char("Contact Name", size=64), + + 'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority'), + 'date_closed': fields.datetime('Closed', readonly=True), + 'stage_id': fields.many2one('crm.case.stage', 'Stage', \ + domain="[('section_id','=',section_id),\ + ('object_id.model', '=', 'crm.lead')]"), + 'opportunity_id': fields.many2one('crm.opportunity', 'Opportunity'), + + 'user_id': fields.many2one('res.users', 'Salesman'), + 'referred': fields.char('Referred By', size=64), + 'date_open': fields.datetime('Opened', readonly=True), + 'day_open': fields.function(_compute_day, string='Days to Open', \ + method=True, multi='day_open', type="float", store=True), + 'day_close': fields.function(_compute_day, string='Days to Close', \ + method=True, multi='day_close', type="float", store=True), + 'function_name': fields.char('Function', size=64), + } + + _defaults = { + 'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'crm.lead', context=c), + 'priority': lambda *a: crm.AVAILABLE_PRIORITIES[2][0], + } + + + def convert_opportunity(self, cr, uid, ids, context=None): + """ Precomputation for converting lead to opportunity + @param cr: the current row, from the database cursor, + @param uid: the current user’s ID for security checks, + @param ids: List of closeday’s IDs + @param context: A standard dictionary for contextual values + @return: Value of action in dict + """ + if not context: + context = {} + context.update({'active_ids': ids}) + + data_obj = self.pool.get('ir.model.data') + data_id = data_obj._get_id(cr, uid, 'crm', 'view_crm_lead2opportunity_create') + value = {} + + view_id = False + if data_id: + view_id = data_obj.browse(cr, uid, data_id, context=context).res_id + for case in self.browse(cr, uid, ids): + context.update({'opportunity_id': case.id}) + context.update({'active_id': case.id}) + if not case.partner_id: + data_id = data_obj._get_id(cr, uid, 'crm', 'view_crm_lead2opportunity_partner') + view_id1 = False + if data_id: + view_id1 = data_obj.browse(cr, uid, data_id, context=context).res_id + value = { + 'name': _('Create Partner'), + 'view_type': 'form', + 'view_mode': 'form,tree', + 'res_model': 'crm.lead2opportunity.partner', + 'view_id': False, + 'context': context, + 'views': [(view_id1, 'form')], + 'type': 'ir.actions.act_window', + 'target': 'new', + 'nodestroy': True + } + break + else: + value = { + 'name': _('Create Opportunity'), + 'view_type': 'form', + 'view_mode': 'form,tree', + 'res_model': 'crm.lead2opportunity', + 'view_id': False, + 'context': context, + 'views': [(view_id, 'form')], + 'type': 'ir.actions.act_window', + 'target': 'new', + 'nodestroy': True + } + return value + +crm_lead() + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/crm/crm_lead_data.xml.moved b/addons/crm/crm_lead_data.xml.moved new file mode 100644 index 00000000000..17211a9ef66 --- /dev/null +++ b/addons/crm/crm_lead_data.xml.moved @@ -0,0 +1,81 @@ + + + + + + + + New + + + + + Assigned + + + + + In Process + + + + + Converted + + + + + Recycled + + + + + Dead + + + + + + + Telesales + + + + + Mail + + + + + Email + + + + + Print + + + + + Web + + + + + Radio + + + + + Television + + + + + Newsletter + + + + + + diff --git a/addons/crm/crm_lead_demo.xml.moved b/addons/crm/crm_lead_demo.xml.moved new file mode 100644 index 00000000000..bc6638601c2 --- /dev/null +++ b/addons/crm/crm_lead_demo.xml.moved @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/addons/crm/crm_lead_menu.xml.moved b/addons/crm/crm_lead_menu.xml.moved new file mode 100644 index 00000000000..4d752ca8a9b --- /dev/null +++ b/addons/crm/crm_lead_menu.xml.moved @@ -0,0 +1,33 @@ + + + + + + Leads + crm.lead + tree,form + + + + + + tree + + + + + + form + + + + + + + + + diff --git a/addons/crm/crm_lead_view.xml.moved b/addons/crm/crm_lead_view.xml.moved new file mode 100644 index 00000000000..03318270e9b --- /dev/null +++ b/addons/crm/crm_lead_view.xml.moved @@ -0,0 +1,331 @@ + + + + + + + + Lead Stages + crm.case.stage + form + + [('object_id.model', '=', 'crm.lead')] + {'object_id':'crm.lead'} + + + + + + + Lead Resource Type + crm.case.resource.type + form + + [('object_id.model', '=', 'crm.lead')] + {'object_id':'crm.lead'} + + + + + + + CRM - Leads Form + crm.lead + form + +
+ + + + +