[IMP] base_action_rule, crm: Improved base_action_rule. Removed crm.case.rule from crm and added objects of base.actio.rule.

bzr revid: uco@tinyerp.co.in-20100203102809-h622irvspyflvw0e
This commit is contained in:
uco (OpenERP) 2010-02-03 15:58:09 +05:30
parent b527df9a9c
commit 904c896e0c
7 changed files with 333 additions and 415 deletions

View File

@ -1,6 +1,7 @@
import time
import mx.DateTime
import tools
from osv import fields, osv, orm
from osv.orm import except_orm
@ -44,45 +45,91 @@ class base_action_rule(osv.osv):
scrit = []
history = []
history_obj = self.pool.get('base.action.rule.history')
cr.execute("select nextcall from ir_cron where model='base.action.rule'")
action_next = cr.fetchone()[0]
if rules:
cr.execute('select * from base_action_rule_history where rule_id in (%s)' %(','.join(map(lambda x: "'"+str(x.id)+"'",rules))))
history = cr.fetchall()
checkids = map(lambda x: x[0], history or [])
if not len(history) or len(history) < len(rules):
for rule in rules:
if rule.id not in checkids:
lastDate = mx.DateTime.strptime(rule.create_date[:19], '%Y-%m-%d %H:%M:%S')
history_obj.create(cr, uid, {'rule_id': rule.id, 'res_id': rule.name.id, 'date_action_last': lastDate})
history_obj.create(cr, uid, {'rule_id': rule.id, 'res_id': rule.name.id, 'date_action_last': lastDate, 'date_action_next': action_next})
for rule in rules:
obj = self.pool.get(rule.name.model)
rec_ids = obj.search(cr, uid, [])
for action in rule.rule_lines:
if action.trg_date_type=='create':
base = mx.DateTime.strptime(rule.create_date[:19], '%Y-%m-%d %H:%M:%S')
elif action.trg_date_type=='action_last':
for hist in history:
if hist[6]:
base = mx.DateTime.strptime(hist[6][:19], '%Y-%m-%d %H:%M:%S')
else:
base = mx.DateTime.strptime(rule.create_date[:19], '%Y-%m-%d %H:%M:%S')
history_obj.write(cr, uid, [hist[0]], {'date_action_last': base})
elif action.trg_date_type=='deadline' and rule.name.date_deadline:
base = mx.DateTime.strptime(rule.name.date_deadline, '%Y-%m-%d %H:%M:%S')
elif action.trg_date_type=='date' and rule.name.date:
base = mx.DateTime.strptime(rule.name.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')
for hist in history:
if not hist[8] or dt < hist[8]:
history_obj.write(cr, uid, [hist[0]], {'date_action_next': dt}, context)
for data in obj.browse(cr, uid, rec_ids):
ok = True
ok = ok and (not action.trg_state_from or action.trg_state_from==data.state)
ok = ok and (not action.trg_state_to or action.trg_state_to==state_to)
ok = ok and (not action.trg_user_id.id or action.trg_user_id.id==data.user_id.id)
ok = ok and (not action.trg_partner_id.id or action.trg_partner_id.id==data.partner_id.id)
ok = ok and (
not action.trg_partner_categ_id.id or
(
data.partner_id.id and
(action.trg_partner_categ_id.id in map(lambda x: x.id, data.partner_id.category_id or []))
)
)
ok = ok and (not action.trg_priority_from or action.trg_priority_from>=data.priority)
ok = ok and (not action.trg_priority_to or action.trg_priority_to<=data.priority)
reg_name = action.regex_name
result_name = True
if reg_name:
ptrn = re.compile(str(reg_name))
_result = ptrn.search(str(data.name))
if not _result:
result_name = False
regex_n = not reg_name or result_name
ok = ok and regex_n
if not ok:
continue
base = False
if action.trg_date_type=='create':
base = mx.DateTime.strptime(data.create_date[:19], '%Y-%m-%d %H:%M:%S')
elif action.trg_date_type=='action_last':
for hist in history:
if hist[6]:
base = hist[8]
else:
base = mx.DateTime.strptime(data.create_date[:19], '%Y-%m-%d %H:%M:%S')
elif action.trg_date_type=='date' and data.date:
base = mx.DateTime.strptime(data.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')
for hist in history:
ok = (dt <= time.strftime('%Y-%m-%d %H:%M:%S')) and \
((not hist[8]) or \
(dt >= hist[8] and \
hist[6] < hist[8]))
if not ok:
if not hist[8] or dt < hist[8]:
history_obj.write(cr, uid, [hist[0]], {'date_action_next': dt}, context)
else:
ok = action.trg_date_type=='none'
if ok:
if action.server_action_id:
context.update({'active_id':case.id,'active_ids':[case.id]})
self.pool.get('ir.actions.server').run(cr, uid, [action.server_action_id.id], context)
for hist in history:
if hist[6]:
base = hist[8]
history_obj.write(cr, uid, [hist[0]], {'date_action_last': base, 'date_action_next': action_next})
return True
base_action_rule()
@ -103,7 +150,6 @@ class base_action_rule_line(osv.osv):
('none','None'),
('create','Creation Date'),
('action_last','Last Action Date'),
('deadline','Deadline'),
('date','Date'),
], '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 " \
@ -135,10 +181,9 @@ class base_action_rule_line(osv.osv):
'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 Case Name', size=128),
'regex_history': fields.char('Regular Expression on Case History', size=128),
'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 ation to be taken on basis of which condition"),
"eg:on which object which action to be taken on basis of which condition"),
}
_defaults = {
@ -154,13 +199,32 @@ class base_action_rule_line(osv.osv):
_order = 'sequence'
def format_body(self, body):
return body and tools.ustr(body.encode('ascii', 'replace')) or ''
def format_mail(self, case, body):
data = {
'case_id': case.id,
'case_subject': case.name,
'case_date': case.date,
'case_description': case.description,
'case_user': (case.user_id and case.user_id.name) or '/',
'case_user_email': (case.user_id and case.user_id.address_id and case.user_id.address_id.email) or '/',
'case_user_phone': (case.user_id and case.user_id.address_id and case.user_id.address_id.phone) or '/',
'email_from': case.email_from,
'partner': (case.partner_id and case.partner_id.name) or '/',
'partner_email': (case.partner_address_id and case.partner_address_id.email) or '/',
}
return self.format_body(body % data)
def _check_mail(self, cr, uid, ids, context=None):
emptycase = orm.browse_null()
for rule in self.browse(cr, uid, ids):
if rule.act_mail_body:
try:
obj = self.pool.get(rule.rule_id.name.model)
obj.format_mail(emptycase, rule.act_mail_body)
self.format_mail(emptycase, rule.act_mail_body)
except (ValueError, KeyError, TypeError):
return False
return True

View File

@ -57,10 +57,10 @@
<separator colspan="4" string="Conditions on States"/>
<field name="trg_state_from" select="2"/>
<field name="trg_state_to" select="2"/>
<separator colspan="4" string="Conditions on Case Fields"/>
<field name="regex_name" string="Regex on Case Name" colspan="2"/>
<separator colspan="4" string="Conditions on Model Fields"/>
<field name="regex_name" string="Regex on Model Name" colspan="2"/>
<field name="trg_user_id" select="2"/>
<separator colspan="4" string="Conditions on Case Partner"/>
<separator colspan="4" string="Conditions on Model Partner"/>
<field name="trg_partner_id"/>
<field name="trg_partner_categ_id"/>
<separator colspan="4" string="Conditions on Priority Range"/>
@ -73,10 +73,8 @@
<field name="trg_date_range" nolabel="1"/>
<field name="trg_date_range_type" nolabel="1"/>
</group>
<separator colspan="4" string="Condition on Communication History"/>
<field name="regex_history" string="Regex on Communication History"/>
<separator colspan="4" string="Note"/>
<label align="0.0" string="The rule use a AND operator. The case must match all non empty fields so that the rule execute the action described in the 'Actions' tab." colspan="4"/>
<label align="0.0" string="The rule use a AND operator. The model must match all non empty fields so that the rule execute the action described in the 'Actions' tab." colspan="4"/>
</page>
<page string="Actions">
<separator colspan="4" string="Fields to Change"/>

View File

@ -44,7 +44,7 @@ The CRM module has a email gateway for the synchronisation interface
between mails and Open ERP.""",
'author': 'Tiny',
'website': 'http://www.openerp.com',
'depends': ['base',
'depends': ['base', 'base_action_rule',
'caldav',
'process',
'mail_gateway',

View File

@ -163,18 +163,185 @@ class crm_case_stage(osv.osv):
crm_case_stage()
class base_action_rule(osv.osv):
_inherit = 'base.action.rule'
_description = 'Action Rules'
def _check(self, cr, uid, ids=False, context={}):
'''
Function called by the scheduler to process cases for date actions
Only works on not done and cancelled cases
'''
obj = self.pool.get('base.action.rule')
ids2 = obj.search(cr, uid, [('name.model','=','crm.case')])
cases = obj.browse(cr, uid, ids2, context)
return obj._action(cr, uid, cases, False, context=context)
class crm_case_rule(osv.osv):
_name = "crm.case.rule"
_description = "Case Rule"
def _action(self, cr, uid, cases, state_to, scrit=None, context={}):
if not scrit:
scrit = []
history = []
history_obj = self.pool.get('base.action.rule.history')
cr.execute("select nextcall from ir_cron where model='base.action.rule'")
action_next = cr.fetchone()[0]
action_ids = self.pool.get('base.action.rule').search(cr, uid, scrit)
level = MAX_LEVEL
if cases and action_ids:
cr.execute('select * from base_action_rule_history where rule_id in (%s)' %(','.join(map(lambda x: "'"+str(x.id)+"'",cases))))
history = cr.fetchall()
checkids = map(lambda x: x[0], history or [])
if not len(history) or len(history) < len(cases):
for case in cases:
if case.id not in checkids:
lastDate = mx.DateTime.strptime(case.create_date[:19], '%Y-%m-%d %H:%M:%S')
history_obj.create(cr, uid, {'rule_id': case.id, 'res_id': case.name.id, 'date_action_last': lastDate, 'date_action_next': action_next})
caseobj = self.pool.get('crm.case')
case_ids = caseobj.search(cr, uid, [('state', 'not in', ('cancel','done'))])
while len(action_ids) and level:
newactions = []
actions = self.pool.get('base.action.rule').browse(cr, uid, action_ids, context)
for case in cases:
for line in actions:
for action in line.rule_lines:
for cs in caseobj.browse(cr, uid, case_ids):
ok = True
ok = ok and (not action.trg_state_from or action.trg_state_from==cs.state)
ok = ok and (not action.trg_state_to or action.trg_state_to==state_to)
ok = ok and (not action.trg_section_id or action.trg_section_id.id==cs.section_id.id)
ok = ok and (not action.trg_categ_id or action.trg_categ_id.id==cs.categ_id.id)
ok = ok and (not action.trg_user_id.id or action.trg_user_id.id==cs.user_id.id)
ok = ok and (not action.trg_partner_id.id or action.trg_partner_id.id==cs.partner_id.id)
ok = ok and (not action.trg_max_history or action.trg_max_history<=(len(cs.history_line)+1))
ok = ok and (
not action.trg_partner_categ_id.id or
(
cs.partner_id.id and
(action.trg_partner_categ_id.id in map(lambda x: x.id, cs.partner_id.category_id or []))
)
)
ok = ok and (not action.trg_priority_from or action.trg_priority_from>=case.priority)
ok = ok and (not action.trg_priority_to or action.trg_priority_to<=case.priority)
reg_name = action.regex_name
result_name = True
if reg_name:
ptrn = re.compile(str(reg_name))
_result = ptrn.search(str(cs.name))
if not _result:
result_name = False
regex_n = not reg_name or result_name
ok = ok and regex_n
reg_history = action.regex_history
result_history = True
if reg_history:
ptrn = re.compile(str(reg_history))
if cs.history_line:
_result = ptrn.search(str(cs.history_line[0].description))
if not _result:
result_history = False
regex_h = not reg_history or result_history
ok = ok and regex_h
if not ok:
continue
base = False
if action.trg_date_type=='create':
base = mx.DateTime.strptime(case.create_date[:19], '%Y-%m-%d %H:%M:%S')
elif action.trg_date_type=='action_last':
for hist in history:
if hist[6]:
base = mx.DateTime.strptime(hist[6], '%Y-%m-%d %H:%M:%S')
else:
base = mx.DateTime.strptime(cs.create_date[:19], '%Y-%m-%d %H:%M:%S')
elif action.trg_date_type=='deadline' and cs.date_deadline:
base = mx.DateTime.strptime(cs.date_deadline, '%Y-%m-%d %H:%M:%S')
elif action.trg_date_type=='date' and cs.date:
base = mx.DateTime.strptime(cs.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')
for hist in history:
ok = (dt <= time.strftime('%Y-%m-%d %H:%M:%S')) and \
((not hist[8]) or \
(dt >= hist[8] and \
hist[6] < hist[8]))
if not ok:
if not hist[8] or dt < hist[8]:
history_obj.write(cr, uid, [hist[0]], {'date_action_next': dt}, context)
else:
ok = action.trg_date_type=='none'
if ok:
if action.server_action_id:
context.update({'active_id':cs.id,'active_ids':[cs.id]})
self.pool.get('ir.actions.server').run(cr, uid, [action.server_action_id.id], context)
write = {}
if action.act_state:
cs.state = action.act_state
write['state'] = action.act_state
if action.act_section_id:
cs.section_id = action.act_section_id
write['section_id'] = action.act_section_id.id
if action.act_user_id:
cs.user_id = action.act_user_id
write['user_id'] = action.act_user_id.id
if action.act_priority:
cs.priority = action.act_priority
write['priority'] = action.act_priority
if action.act_email_cc:
if '@' in (cs.email_cc or ''):
emails = cs.email_cc.split(",")
if action.act_email_cc not in emails:# and '<'+str(action.act_email_cc)+">" not in emails:
write['email_cc'] = cs.email_cc+','+action.act_email_cc
else:
write['email_cc'] = action.act_email_cc
caseobj.write(cr, uid, [cs.id], write, context)
if action.act_remind_user:
caseobj.remind_user(cr, uid, [cs.id], context, attach=action.act_remind_attach)
if action.act_remind_partner:
caseobj.remind_partner(cr, uid, [cs.id], context, attach=action.act_remind_attach)
if action.act_method:
getattr(caseobj, 'act_method')(cr, uid, [cs.id], action, context)
emails = []
if action.act_mail_to_user:
if cs.user_id and cs.user_id.address_id:
emails.append(cs.user_id.address_id.email)
if action.act_mail_to_partner:
emails.append(cs.email_from)
if action.act_mail_to_watchers:
emails += (action.act_email_cc or '').split(',')
if action.act_mail_to_email:
emails += (action.act_mail_to_email or '').split(',')
emails = filter(None, emails)
if len(emails) and action.act_mail_body:
emails = list(set(emails))
caseobj.email_send(cr, uid, cs, emails, action.act_mail_body)
break
action_ids = newactions
level -= 1
return True
base_action_rule()
class base_action_rule_line(osv.osv):
_inherit = 'base.action.rule.line'
_columns = {
'name': fields.char('Rule Name',size=64, required=True),
'active': fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the case rule without removing it."),
'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of case rules."),
'trg_state_from': fields.selection([('',''),('escalate','Escalate')]+AVAILABLE_STATES, 'Case State', size=16),
'trg_state_to': fields.selection([('',''),('escalate','Escalate')]+AVAILABLE_STATES, 'Button Pressed', size=16),
'trg_section_id': fields.many2one('crm.case.section', 'Section'),
'trg_max_history': fields.integer('Maximum Communication History'),
'trg_categ_id': fields.many2one('crm.case.categ', 'Category', domain="[('section_id','=',trg_section_id)]"),
'regex_history' : fields.char('Regular Expression on Case History', size=128),
'act_section_id': fields.many2one('crm.case.section', 'Set section to'),
'trg_date_type': fields.selection([
('none','None'),
('create','Creation Date'),
@ -182,88 +349,9 @@ class crm_case_rule(osv.osv):
('deadline','Deadline'),
('date','Date'),
], '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_section_id': fields.many2one('crm.case.section', 'Section'),
}
#'trg_categ_id': fields.many2one('crm.case.categ', 'Category', domain="[('section_id','=',trg_section_id)]"),
'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_priority_from': fields.selection([('','')] + AVAILABLE_PRIORITIES, 'Minimum Priority'),
'trg_priority_to': fields.selection([('','')] + AVAILABLE_PRIORITIES, 'Maximim Priority'),
'trg_max_history': fields.integer('Maximum Communication History'),
'act_method': fields.char('Call Object Method', size=64),
'act_state': fields.selection([('','')]+AVAILABLE_STATES, 'Set state to', size=16),
'act_section_id': fields.many2one('crm.case.section', 'Set section to'),
'act_user_id': fields.many2one('res.users', 'Set responsible to'),
'act_priority': fields.selection([('','')] + AVAILABLE_PRIORITIES, '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_remind_attach': fields.boolean('Remind with attachment', help="Check this if you want that all documents attached to the case 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_partner': fields.boolean('Mail to partner',help="Check this if you want the rule to send an email to the partner."),
'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 Case Name', size=128),
'regex_history' : fields.char('Regular Expression on Case History', size=128),
'server_action_id' : fields.many2one('ir.actions.server','Server Action',help="Describes the action name." \
"eg:on which object which ation 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_partner': lambda *a: 0,
'act_mail_to_watchers': lambda *a: 0,
}
_order = 'sequence'
def _check(self, cr, uid, ids=False, context={}):
'''
Function called by the scheduler to process cases for date actions
Only works on not done and cancelled cases
'''
cr.execute('select * from crm_case \
where (date_action_last<%s or date_action_last is null) \
and (date_action_next<=%s or date_action_next is null) \
and state not in (\'cancel\',\'done\')',
(time.strftime("%Y-%m-%d %H:%M:%S"),
time.strftime('%Y-%m-%d %H:%M:%S')))
ids2 = map(lambda x: x[0], cr.fetchall() or [])
case_obj = self.pool.get('crm.case')
cases = case_obj.browse(cr, uid, ids2, context)
return case_obj._action(cr, uid, cases, False, context=context)
def _check_mail(self, cr, uid, ids, context=None):
caseobj = self.pool.get('crm.case')
emptycase = orm.browse_null()
for rule in self.browse(cr, uid, ids):
if rule.act_mail_body:
try:
caseobj.format_mail(emptycase, rule.act_mail_body)
except (ValueError, KeyError, TypeError):
return False
return True
_constraints = [
(_check_mail, 'Error: The mail is not well formated', ['act_mail_body']),
]
crm_case_rule()
base_action_rule_line()
def _links_get(self, cr, uid, context={}):
obj = self.pool.get('res.request.link')
@ -335,9 +423,6 @@ class crm_case(osv.osv):
\nIf the case is in progress the state is set to \'Open\'.\
\nWhen the case is over, the state is set to \'Done\'.\
\nIf the case needs to be reviewed then the state is set to \'Pending\'.'),
'date_action_last': fields.datetime('Last Action', readonly=1),
'date_action_next': fields.datetime('Next Action', readonly=1),
'company_id': fields.many2one('res.company','Company'),
}
def _get_default_partner_address(self, cr, uid, context):
@ -427,164 +512,6 @@ class crm_case(osv.osv):
value['email_from'] = case.email_from
return {'value': value}
def _action(self, cr, uid, cases, state_to, scrit=None, context={}):
if not scrit:
scrit = []
action_ids = self.pool.get('crm.case.rule').search(cr, uid, scrit)
level = MAX_LEVEL
while len(action_ids) and level:
newactions = []
actions = self.pool.get('crm.case.rule').browse(cr, uid, action_ids, context)
for case in cases:
for action in actions:
ok = True
ok = ok and (not action.trg_state_from or action.trg_state_from==case.state)
ok = ok and (not action.trg_state_to or action.trg_state_to==state_to)
ok = ok and (not action.trg_section_id or action.trg_section_id.id==case.section_id.id)
ok = ok and (not action.trg_categ_id or action.trg_categ_id.id==case.categ_id.id)
ok = ok and (not action.trg_user_id.id or action.trg_user_id.id==case.user_id.id)
ok = ok and (not action.trg_partner_id.id or action.trg_partner_id.id==case.partner_id.id)
ok = ok and (not action.trg_max_history or action.trg_max_history<=(len(case.history_line)+1))
ok = ok and (
not action.trg_partner_categ_id.id or
(
case.partner_id.id and
(action.trg_partner_categ_id.id in map(lambda x: x.id, case.partner_id.category_id or []))
)
)
ok = ok and (not action.trg_priority_from or action.trg_priority_from>=case.priority)
ok = ok and (not action.trg_priority_to or action.trg_priority_to<=case.priority)
reg_name = action.regex_name
result_name = True
if reg_name:
ptrn = re.compile(str(reg_name))
_result = ptrn.search(str(case.name))
if not _result:
result_name = False
regex_n = not reg_name or result_name
ok = ok and regex_n
reg_history = action.regex_history
result_history = True
if reg_history:
ptrn = re.compile(str(reg_history))
if case.history_line:
_result = ptrn.search(str(case.history_line[0].description))
if not _result:
result_history = False
regex_h = not reg_history or result_history
ok = ok and regex_h
if not ok:
continue
base = False
if action.trg_date_type=='create':
base = mx.DateTime.strptime(case.create_date[:19], '%Y-%m-%d %H:%M:%S')
elif action.trg_date_type=='action_last':
if case.date_action_last:
base = mx.DateTime.strptime(case.date_action_last, '%Y-%m-%d %H:%M:%S')
else:
base = mx.DateTime.strptime(case.create_date[:19], '%Y-%m-%d %H:%M:%S')
elif action.trg_date_type=='deadline' and case.date_deadline:
base = mx.DateTime.strptime(case.date_deadline, '%Y-%m-%d %H:%M:%S')
elif action.trg_date_type=='date' and case.date:
base = mx.DateTime.strptime(case.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 = (dt <= time.strftime('%Y-%m-%d %H:%M:%S')) and \
((not case.date_action_next) or \
(dt >= case.date_action_next and \
case.date_action_last < case.date_action_next))
if not ok:
if not case.date_action_next or dt < case.date_action_next:
case.date_action_next = dt
self.write(cr, uid, [case.id], {'date_action_next': dt}, context)
else:
ok = action.trg_date_type=='none'
if ok:
if action.server_action_id:
context.update({'active_id':case.id,'active_ids':[case.id]})
self.pool.get('ir.actions.server').run(cr, uid, [action.server_action_id.id], context)
write = {}
if action.act_state:
case.state = action.act_state
write['state'] = action.act_state
if action.act_section_id:
case.section_id = action.act_section_id
write['section_id'] = action.act_section_id.id
if action.act_user_id:
case.user_id = action.act_user_id
write['user_id'] = action.act_user_id.id
if action.act_priority:
case.priority = action.act_priority
write['priority'] = action.act_priority
if action.act_email_cc:
if '@' in (case.email_cc or ''):
emails = case.email_cc.split(",")
if action.act_email_cc not in emails:# and '<'+str(action.act_email_cc)+">" not in emails:
write['email_cc'] = case.email_cc+','+action.act_email_cc
else:
write['email_cc'] = action.act_email_cc
write['date_action_last'] = time.strftime('%Y-%m-%d %H:%M:%S')
self.write(cr, uid, [case.id], write, context)
caseobj = self.pool.get('crm.case')
if action.act_remind_user:
caseobj.remind_user(cr, uid, [case.id], context, attach=action.act_remind_attach)
if action.act_remind_partner:
caseobj.remind_partner(cr, uid, [case.id], context, attach=action.act_remind_attach)
if action.act_method:
getattr(caseobj, 'act_method')(cr, uid, [case.id], action, context)
emails = []
if action.act_mail_to_user:
if case.user_id and case.user_id.address_id:
emails.append(case.user_id.address_id.email)
if action.act_mail_to_partner:
emails.append(case.email_from)
if action.act_mail_to_watchers:
emails += (action.act_email_cc or '').split(',')
if action.act_mail_to_email:
emails += (action.act_mail_to_email or '').split(',')
emails = filter(None, emails)
if len(emails) and action.act_mail_body:
emails = list(set(emails))
self.email_send(cr, uid, case, emails, action.act_mail_body)
break
action_ids = newactions
level -= 1
return True
def format_body(self, body):
return body and tools.ustr(body.encode('ascii', 'replace')) or ''
def format_mail(self, case, body):
data = {
'case_id': case.id,
'case_subject': case.name,
'case_date': case.date,
'case_description': case.description,
'case_user': (case.user_id and case.user_id.name) or '/',
'case_user_email': (case.user_id and case.user_id.address_id and case.user_id.address_id.email) or '/',
'case_user_phone': (case.user_id and case.user_id.address_id and case.user_id.address_id.phone) or '/',
'email_from': case.email_from,
'partner': (case.partner_id and case.partner_id.name) or '/',
'partner_email': (case.partner_address_id and case.partner_address_id.email) or '/',
}
return self.format_body(body % data)
def __history(self, cr, uid, cases, keyword, history=False, email=False, details=None, context={}):
model_obj = self.pool.get('ir.model')
for case in cases:
@ -612,7 +539,8 @@ class crm_case(osv.osv):
res = super(crm_case, self).create(cr, uid, *args, **argv)
cases = self.browse(cr, uid, [res])
cases[0].state # to fill the browse record cache
self._action(cr,uid, cases, 'draft')
obj = self.pool.get('base.action.rule')
obj._action(cr,uid, cases, 'draft')
return res
def remind_partner(self, cr, uid, ids, context={}, attach=False):
@ -745,7 +673,8 @@ class crm_case(osv.osv):
#
# We use the cache of cases to keep the old case state
#
self._action(cr,uid, cases, 'done')
obj = self.pool.get('base.action.rule')
obj._action(cr,uid, cases, 'done')
return True
def case_escalate(self, cr, uid, ids, *args):
@ -761,7 +690,8 @@ class crm_case(osv.osv):
self.write(cr, uid, ids, data)
cases = self.browse(cr, uid, ids)
self.__history(cr, uid, cases, _('Escalate'))
self._action(cr, uid, cases, 'escalate')
obj = self.pool.get('base.action.rule')
obj._action(cr, uid, cases, 'escalate')
return True
@ -773,7 +703,8 @@ class crm_case(osv.osv):
if not case.user_id:
data['user_id'] = uid
self.write(cr, uid, ids, data)
self._action(cr,uid, cases, 'open')
obj = self.pool.get('base.action.rule')
obj._action(cr,uid, cases, 'open')
return True
@ -782,7 +713,8 @@ class crm_case(osv.osv):
cases[0].state # to fill the browse record cache
self.__history(cr, uid, cases, _('Cancel'))
self.write(cr, uid, ids, {'state':'cancel', 'active':True})
self._action(cr,uid, cases, 'cancel')
obj = self.pool.get('base.action.rule')
obj._action(cr,uid, cases, 'cancel')
return True
def case_pending(self, cr, uid, ids, *args):
@ -790,7 +722,8 @@ class crm_case(osv.osv):
cases[0].state # to fill the browse record cache
self.__history(cr, uid, cases, _('Pending'))
self.write(cr, uid, ids, {'state':'pending', 'active':True})
self._action(cr,uid, cases, 'pending')
obj = self.pool.get('base.action.rule')
obj._action(cr,uid, cases, 'pending')
return True
def case_reset(self, cr, uid, ids, *args):
@ -798,7 +731,8 @@ class crm_case(osv.osv):
cases[0].state # to fill the browse record cache
self.__history(cr, uid, cases, _('Draft'))
self.write(cr, uid, ids, {'state':'draft', 'active':True})
self._action(cr, uid, cases, 'draft')
obj = self.pool.get('base.action.rule')
obj._action(cr, uid, cases, 'draft')
return True
crm_case()
@ -909,6 +843,3 @@ class users(osv.osv):
'context_section_id': fields.selection(_section_get, 'Sales Section'),
}
users()

View File

@ -59,17 +59,6 @@
<record id="event_type_case_cancel" model="res.partner.event.type">
<field eval="False" name="active"/>
</record>
<record id="ir_cron_crm_action" model="ir.cron">
<field name="name">Check cases rules</field>
<field name="interval_number">4</field>
<field name="interval_type">hours</field>
<field name="numbercall">-1</field>
<field eval="False" name="doall"/>
<field eval="'crm.case.rule'" name="model"/>
<field eval="'_check'" name="function"/>
<field eval="'()'" name="args"/>
</record>
</data>
</openerp>

View File

@ -133,105 +133,45 @@
<!-- Case rules -->
<record id="crm_case_rule-view" model="ir.ui.view">
<field name="name">crm.case.rule.form</field>
<field name="model">crm.case.rule</field>
<record id="view_base_action_rule_line_form1" model="ir.ui.view">
<field name="name">base.action.rule.line.form.inherit</field>
<field name="model">base.action.rule.line</field>
<field name="inherit_id" ref="base_action_rule.view_base_action_rule_line_form"/>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Case Rule">
<field name="name" select="1"/>
<field name="active" select="2"/>
<notebook colspan="4">
<page string="Conditions">
<separator colspan="4" string="Conditions on States"/>
<field name="trg_state_from" select="2"/>
<field name="trg_state_to" select="2"/>
<separator colspan="4" string="Conditions on Case Fields"/>
<field name="regex_name" string="Regex on Case Name" colspan="2"/>
<field name="trg_section_id" select="1" widget="selection"/>
<!--<field name="trg_categ_id"/>-->
<field name="trg_user_id" select="2"/>
<separator colspan="4" string="Conditions on Case Partner"/>
<field name="trg_partner_id"/>
<field name="trg_partner_categ_id"/>
<separator colspan="4" string="Conditions on Priority Range"/>
<field name="trg_priority_from"/>
<field name="trg_priority_to"/>
<separator colspan="4" string="Conditions on Timing"/>
<field name="trg_date_type"/>
<label align="1.0" string="Delay After Trigger Date:"/>
<group col="2" colspan="1">
<field name="trg_date_range" nolabel="1"/>
<field name="trg_date_range_type" nolabel="1"/>
</group>
<separator colspan="4" string="Condition on Communication History"/>
<field name="regex_history" string="Regex on Communication History"/>
<field name="trg_max_history"/>
<separator colspan="4" string="Note"/>
<label align="0.0" string="The rule use a AND operator. The case must match all non empty fields so that the rule execute the action described in the 'Actions' tab." colspan="4"/>
</page>
<page string="Actions">
<separator colspan="4" string="Fields to Change"/>
<field name="act_state"/>
<field name="act_section_id"/>
<field name="act_user_id"/>
<field name="act_priority"/>
<separator colspan="4" string="E-Mail Reminders (includes the content of the case)"/>
<field name="act_remind_user"/>
<field name="act_remind_partner"/>
<field name="act_remind_attach"/>
<field colspan="4" name="act_email_cc"/>
<separator colspan="4" string="Server Action to be Triggered"/>
<field name="server_action_id"/>
<!--
<field name="act_method" colspan="4" readonly="1"/>
-->
</page>
<page string="E-Mail Actions">
<separator colspan="4" string="Template of Email to Send"/>
<field name="act_mail_to_user"/>
<field name="act_mail_to_partner"/>
<field name="act_mail_to_watchers"/>
<field colspan="4" name="act_mail_to_email"/>
<field colspan="4" name="act_mail_body"/>
<separator colspan="4" string="Special Keywords to Be Used in The Body"/>
<label align="0.0" string="%%(case_id)s = Case ID" colspan="2"/>
<label align="0.0" string="%%(case_subject)s = Case subject" colspan="2"/>
<label align="0.0" string="%%(case_description)s = Case description" colspan="2"/>
<label align="0.0" string="%%(case_date)s = Creation date" colspan="2"/>
<label align="0.0" string="%%(email_from)s = Partner email" colspan="2"/>
<label align="0.0" string="%%(partner)s = Partner name" colspan="2"/>
<label align="0.0" string="%%(partner_email)s = Partner email" colspan="2"/>
<label align="0.0" string="%%(case_user)s = Responsible name" colspan="2"/>
<label align="0.0" string="%%(case_user_email)s = Responsible email" colspan="2"/>
<label align="0.0" string="%%(case_user_phone)s = Responsible phone" colspan="2"/>
<label align="0.0" string="%% = The &apos;%%&apos; Character" colspan="2"/>
</page>
</notebook>
</form>
</field>
</record>
<record id="crm_case_rule_tree-view" model="ir.ui.view">
<field name="name">crm.case.rule.tree</field>
<field name="model">crm.case.rule</field>
<field name="type">tree</field>
<field name="trg_priority_to" position="after">
<separator colspan="4" string="Condition on Communication History"/>
<field name="regex_history"/>
<field name="trg_max_history"/>
</field>
</field>
</record>
<record id="view_base_action_rule_line_form2" model="ir.ui.view">
<field name="name">base.action.rule.line.form2.inherit</field>
<field name="model">base.action.rule.line</field>
<field name="inherit_id" ref="base_action_rule.view_base_action_rule_line_form"/>
<field name="type">form</field>
<field name="arch" type="xml">
<tree string="Case Rule">
<field name="name"/>
<field name="active"/>
</tree>
</field>
</record>
<record id="crm_case_rule-act" model="ir.actions.act_window">
<field name="name">Rules</field>
<field name="res_model">crm.case.rule</field>
<field name="view_type">form</field>
<field name="view_id" ref="crm_case_rule_tree-view"/>
</record>
<menuitem action="crm_case_rule-act" id="menu_crm_case_rule-act" parent="crm.menu_crm_configuration"/>
<field name="regex_name" position="after">
<field name="trg_section_id" select="1" widget="selection"/>
<field name="trg_categ_id"/>
</field>
</field>
</record>
<record id="view_base_action_rule_line_form3" model="ir.ui.view">
<field name="name">base.action.rule.line.form3.inherit</field>
<field name="model">base.action.rule.line</field>
<field name="inherit_id" ref="base_action_rule.view_base_action_rule_line_form"/>
<field name="type">form</field>
<field name="arch" type="xml">
<field name="act_state" position="after">
<field name="act_section_id"/>
</field>
</field>
</record>
<record id="view_crm_email_add_cc_wizard" model="ir.ui.view">
<field name="name">Add CC</field>
<field name="model">crm.email.add.cc</field>
@ -377,8 +317,6 @@
<field name="active" select="2"/>
<separator colspan="4" string="Dates"/>
<field name="create_date"/>
<field name="date_action_last"/>
<field name="date_action_next"/>
<field colspan="4" name="log_ids" nolabel="1">
<form string="Actions">
<separator colspan="4" string="Action Information"/>

View File

@ -3,7 +3,6 @@
"access_crm_segmentation_line","crm.segmentation.line","model_crm_segmentation_line","crm.group_crm_manager",1,1,1,1
"access_crm_case_section","crm.case.section","model_crm_case_section","crm.group_crm_user",1,0,0,0
"access_crm_case_categ","crm.case.categ","model_crm_case_categ","crm.group_crm_user",1,0,0,0
"access_crm_case_rule","crm.case.rule","model_crm_case_rule","crm.group_crm_user",1,0,0,0
"access_crm_case_manger","crm.case manager","model_crm_case","crm.group_crm_user",1,1,1,1
"access_crm_case","crm.case","model_crm_case","crm.group_crm_manager",1,1,1,1
"access_crm_claim","crm.claim","model_crm_claim","crm.group_crm_manager",1,1,1,1
@ -17,7 +16,6 @@
"access_crm_case_history","crm.case.history","model_crm_case_history","crm.group_crm_user",1,1,1,1
"access_crm_case_section_manager","crm.case.section.manager","model_crm_case_section","crm.group_crm_manager",1,1,1,1
"access_crm_case_categ_manager","crm.case.categ.manager","model_crm_case_categ","crm.group_crm_manager",1,1,1,1
"access_crm_case_rule_manager","crm.case.rule.manager","model_crm_case_rule","crm.group_crm_manager",1,1,1,1
"access_crm_case_log_manager","crm.case.log manager","model_crm_case_log","crm.group_crm_manager",1,1,1,1
"access_crm_case_history_manager","crm.case.history manager","model_crm_case_history","crm.group_crm_manager",1,1,1,1
"access_crm_email_add_cc_manager","crm.email.add.cc","model_crm_email_add_cc","crm.group_crm_manager",1,1,1,1

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
3 access_crm_segmentation_line crm.segmentation.line model_crm_segmentation_line crm.group_crm_manager 1 1 1 1
4 access_crm_case_section crm.case.section model_crm_case_section crm.group_crm_user 1 0 0 0
5 access_crm_case_categ crm.case.categ model_crm_case_categ crm.group_crm_user 1 0 0 0
access_crm_case_rule crm.case.rule model_crm_case_rule crm.group_crm_user 1 0 0 0
6 access_crm_case_manger crm.case manager model_crm_case crm.group_crm_user 1 1 1 1
7 access_crm_case crm.case model_crm_case crm.group_crm_manager 1 1 1 1
8 access_crm_claim crm.claim model_crm_claim crm.group_crm_manager 1 1 1 1
16 access_crm_case_history crm.case.history model_crm_case_history crm.group_crm_user 1 1 1 1
17 access_crm_case_section_manager crm.case.section.manager model_crm_case_section crm.group_crm_manager 1 1 1 1
18 access_crm_case_categ_manager crm.case.categ.manager model_crm_case_categ crm.group_crm_manager 1 1 1 1
access_crm_case_rule_manager crm.case.rule.manager model_crm_case_rule crm.group_crm_manager 1 1 1 1
19 access_crm_case_log_manager crm.case.log manager model_crm_case_log crm.group_crm_manager 1 1 1 1
20 access_crm_case_history_manager crm.case.history manager model_crm_case_history crm.group_crm_manager 1 1 1 1
21 access_crm_email_add_cc_manager crm.email.add.cc model_crm_email_add_cc crm.group_crm_manager 1 1 1 1