[ADD] base_action_rule: new module to define diffrent actions for any objects

bzr revid: hmo@tinyerp.com-20100215144224-o4sztjze8yksfsdz
This commit is contained in:
Harry (Open ERP) 2010-02-15 20:12:24 +05:30
commit ee87ba0a2b
24 changed files with 755 additions and 468 deletions

View File

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
import base_action_rule
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
{
'name': 'Action Rule',
'version': '1.0',
'category': 'Generic Modules/Others',
'description': "This module allows to implement action rules for any object.",
'author': 'Tiny',
'website': 'http://www.openerp.com',
'depends': ['base'],
'init_xml': [],
'update_xml': [
'base_action_rule_view.xml',
'security/ir.model.access.csv',
],
'demo_xml': [],
'installable': True,
'active': False,
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,305 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
import time
import mx.DateTime
import re
import tools
from osv import fields, osv, orm
from osv.orm import except_orm
from tools.translate import _
class base_action_rule(osv.osv):
_name = 'base.action.rule'
_description = 'Action Rules'
_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')
}
_defaults = {
'active': lambda *a: True,
'max_level': lambda *a: 15,
}
def format_body(self, body):
return body and tools.ustr(body) or ''
def format_mail(self, obj, body):
data = {
'object_id': obj.id,
'object_subject': hasattr(obj, 'name') and obj.name or False,
'object_date': hasattr(obj, 'date') and obj.date or False,
'object_description': hasattr(obj, 'description') and obj.description or False,
'object_user': hasattr(obj, 'user_id') and (obj.user_id and obj.user_id.name) or '/',
'object_user_email': hasattr(obj, 'user_id') and (obj.user_id and obj.user_id.address_id and obj.user_id.address_id.email) or '/',
'object_user_phone': hasattr(obj, 'user_id') and (obj.user_id and obj.user_id.address_id and obj.user_id.address_id.phone) or '/',
'partner': hasattr(obj, 'partner_id') and (obj.partner_id and obj.partner_id.name) or '/',
'partner_email': hasattr(obj, 'partner_address_id') and (obj.partner_address_id and obj.partner_address_id.email) or '/',
}
return format_body(body % data)
def email_send(self, cr, uid, obj, emails, body, emailfrom=tools.config.get('email_from',False), context={}):
body = self.format_mail(obj, body)
if not emailfrom:
if hasattr(obj, 'user_id') and obj.user_id and obj.user_id.address_id and obj.user_id.address_id.email:
emailfrom = obj.user_id.address_id.email
name = '[%d] %s' % (obj.id, tools.ustr(obj.name))
emailfrom = tools.ustr(emailfrom)
reply_to = emailfrom
if not emailfrom:
raise osv.except_osv(_('Error!'),
_("No E-Mail ID Found for your Company address!"))
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={}):
ok = True
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'):
ok = ok and (not action.trg_partner_id.id or action.trg_partner_id.id==obj.partner_id.id)
ok = ok and (
not action.trg_partner_categ_id.id or
(
obj.partner_id.id and
(action.trg_partner_categ_id.id in map(lambda x: x.id, obj.partner_id.category_id or []))
)
)
state_to = context.get('state_to', False)
if hasattr(obj, 'state'):
ok = ok and (not action.trg_state_from or action.trg_state_from==obj.state)
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:
ptrn = re.compile(str(reg_name))
_result = ptrn.search(str(obj.name))
if not _result:
result_name = False
regex_n = not reg_name or result_name
ok = ok and regex_n
return ok
def do_action(self, cr, uid, action, model_obj, obj, context={}):
if action.server_action_id:
context.update({'active_id':obj.id,'active_ids':[obj.id]})
self.pool.get('ir.actions.server').run(cr, uid, [action.server_action_id.id], context)
write = {}
if hasattr(obj, 'user_id') and action.act_user_id:
obj.user_id = action.act_user_id
write['user_id'] = action.act_user_id.id
if hasattr(obj, 'date_action_last'):
write['date_action_last'] = time.strftime('%Y-%m-%d %H:%M:%S')
if hasattr(obj, 'state') and action.act_state:
obj.state = action.act_state
write['state'] = action.act_state
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:
model_obj.remind_user(cr, uid, [obj.id], context, attach=action.act_remind_attach)
if hasattr(model_obj, 'remind_partner') and action.act_remind_partner:
model_obj.remind_partner(cr, uid, [obj.id], context, attach=action.act_remind_attach)
if action.act_method:
getattr(model_obj, 'act_method')(cr, uid, [obj.id], action, context)
emails = []
if hasattr(obj, 'user_id') and action.act_mail_to_user:
if obj.user_id and obj.user_id.address_id:
emails.append(obj.user_id.address_id.email)
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, obj, emails, action.act_mail_body)
return True
def _action(self, cr, uid, ids, objects, scrit=None, context={}):
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
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)
for obj in objects:
for action in actions:
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)
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={}):
return self.state_get(cr, uid, context=context)
def _priority_get(self, cr, uid, context={}):
return self.priority_get(cr, uid, context=context)
def state_get(self, cr, uid, context={}):
return [('','')]
def priority_get(self, cr, uid, context={}):
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'),
], '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):
empty = orm.browse_null()
rule_obj = self.pool.get('base.action.rule')
for rule in self.browse(cr, uid, ids):
if rule.act_mail_body:
try:
rule_obj.format_mail(empty, 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']),
]
base_action_rule_line()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,130 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<menuitem id="menu_base_action_rule" name="Action Rule" parent="base.menu_base_config" sequence="0"/>
<!--
Action Rule
-->
<record id="view_base_action_rule_form" model="ir.ui.view">
<field name="name">base.action.rule.form</field>
<field name="model">base.action.rule</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Action Rule">
<field name="name"/>
<field name="active"/>
<field name="max_level" />
<separator colspan="4" string="Rule lines"/>
<field name="rule_lines" colspan="4" nolabel="1"/>
</form>
</field>
</record>
<record id="view_base_action_rule_tree" model="ir.ui.view">
<field name="name">base.action.rule.tree</field>
<field name="model">base.action.rule</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Action Rule">
<field name="name"/>
<field name="max_level"/>
</tree>
</field>
</record>
<record id="base_action_rule_act" model="ir.actions.act_window">
<field name="name">Action Rules</field>
<field name="res_model">base.action.rule</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="view_base_action_rule_tree"/>
</record>
<menuitem id="menu_base_action_rule_form" parent="menu_base_action_rule" action="base_action_rule_act"/>
<!--
Action Rule Lines
-->
<record id="view_base_action_rule_line_form" model="ir.ui.view">
<field name="name">base.action.rule.line.form</field>
<field name="model">base.action.rule.line</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Action Rule Line">
<field name="name" select="1"/>
<field name="active" select="2"/>
<notebook colspan="4">
<page string="Conditions">
<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 Model Partner"/>
<field name="trg_partner_id"/>
<field name="trg_partner_categ_id"/>
<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 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="Note"/>
<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"/>
<field name="act_user_id"/>
<field name="act_state"/>
<field name="act_priority"/>
<separator colspan="4" string="E-Mail Reminders (includes the content of the object)"/>
<field name="act_remind_partner"/>
<field name="act_remind_attach"/>
<field name="act_remind_user"/>
<group col="2" colspan="2" attrs="{'invisible': [('act_remind_user','=',False)]}">
<field name="act_reply_to" attrs="{'required':[('act_remind_user','=',True)]}"/>
</group>
<field colspan="4" name="act_email_cc"/>
<separator colspan="4" string="Server Action to be Triggered"/>
<field name="server_action_id"/>
</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_watchers"/>
<field colspan="4" name="act_mail_to_email"/>
<field colspan="4" name="act_mail_body" attrs="{'required':[('act_remind_user','=',True)]}"/>
<separator colspan="4" string="Special Keywords to Be Used in The Body"/>
<label align="0.0" string="%%(object_id)s = Object ID" colspan="2"/>
<label align="0.0" string="%%(object_subject)s = Object subject" colspan="2"/>
<label align="0.0" string="%%(object_description)s = Object description" colspan="2"/>
<label align="0.0" string="%%(object_date)s = Creation date" 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="%%(object_user)s = Responsible name" colspan="2"/>
<label align="0.0" string="%%(object_user_email)s = Responsible email" colspan="2"/>
<label align="0.0" string="%%(object_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="view_base_action_rule_line_tree" model="ir.ui.view">
<field name="name">base.action.rule.line.tree</field>
<field name="model">base.action.rule.line</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Action Rule Lines">
<field name="name"/>
<field name="active"/>
</tree>
</field>
</record>
</data>
</openerp>

View File

@ -0,0 +1,3 @@
"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
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_base_action_rule base.action.rule model_base_action_rule 1 1 1 1
3 access_base_action_rule_line base.action.rule.line model_base_action_rule_line 1 1 1 1

View File

@ -240,12 +240,12 @@
<!-- Available alarms-->
<menuitem id="menu_calendar_configuration" name="Calendar"
<menuitem id="base.menu_calendar_configuration" name="Calendar"
parent="base.menu_base_config" sequence="10" />
<menuitem name="Available Alarms" id="menu_crm_meeting_avail_alarm"
action="base_calendar.action_res_alarm_view"
parent="menu_calendar_configuration" />
parent="base.menu_calendar_configuration" />
</data>

View File

@ -24,7 +24,7 @@
"name" : "Share Calendar using Caldav",
"version" : "1.0",
"depends" : [
"base_calendar",
"base",
],
'description': """
Contains basic functionality for caldav system like:

View File

@ -50,10 +50,11 @@
<field name="view_mode">tree,form</field>
</record>
<menuitem id="base.menu_calendar_configuration" name="Calendar"
parent="base.menu_base_config" sequence="10" />
<menuitem id="menu_calendar"
name="Calendar" parent="base_calendar.menu_calendar_configuration"
name="Calendar" parent="base.menu_calendar_configuration"
sequence="5" action="action_view_calendar" />
</data>

View File

@ -21,6 +21,7 @@
import crm
import crm_mailgate
import crm_action_rule
import crm_segmentation
import crm_meeting
import crm_lead

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',
'process',
'mail_gateway',
'base_calendar',
@ -63,6 +63,7 @@ between mails and Open ERP.""",
'update_xml': [
'crm_wizard.xml',
'crm_view.xml',
'crm_action_rule_view.xml',
'crm_lead_wizard.xml',
'crm_lead_view.xml',
'crm_lead_menu.xml',

View File

@ -163,108 +163,6 @@ class crm_case_stage(osv.osv):
crm_case_stage()
class crm_case_rule(osv.osv):
_name = "crm.case.rule"
_description = "Case Rule"
_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_date_type': fields.selection([
('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 " \
"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()
def _links_get(self, cr, uid, context={}):
obj = self.pool.get('res.request.link')
ids = obj.search(cr, uid, [])
@ -335,9 +233,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 +322,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) 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:
@ -615,50 +352,6 @@ class crm_case(osv.osv):
self._action(cr,uid, cases, 'draft')
return res
def remind_partner(self, cr, uid, ids, context={}, attach=False):
return self.remind_user(cr, uid, ids, context, attach,
destination=False)
def remind_user(self, cr, uid, ids, context={}, attach=False,
destination=True):
for case in self.browse(cr, uid, ids):
if not case.section_id.reply_to:
raise osv.except_osv(_('Error!'), ("Reply To is not specified in Section"))
if not case.email_from:
raise osv.except_osv(_('Error!'), ("Partner Email is not specified in Case"))
if case.section_id.reply_to and case.email_from:
src = case.email_from
dest = case.section_id.reply_to
body = case.email_last or case.description
if not destination:
src, dest = dest, src
if case.user_id.signature:
body += '\n\n%s' % (case.user_id.signature or '')
dest = [dest]
attach_to_send = None
if attach:
attach_ids = self.pool.get('ir.attachment').search(cr, uid, [('res_model', '=', 'crm.case'), ('res_id', '=', case.id)])
attach_to_send = self.pool.get('ir.attachment').read(cr, uid, attach_ids, ['datas_fname','datas'])
attach_to_send = map(lambda x: (x['datas_fname'], base64.decodestring(x['datas'])), attach_to_send)
# Send an email
flag = tools.email_send(
src,
dest,
"Reminder: [%s] %s" % (str(case.id), case.name, ),
self.format_body(body),
reply_to=case.section_id.reply_to,
openobject_id=str(case.id),
attach=attach_to_send
)
if flag:
raise osv.except_osv(_('Email!'),("Email Successfully Sent"))
else:
raise osv.except_osv(_('Email Fail!'),("Email is not sent successfully"))
return True
def add_reply(self, cursor, user, ids, context=None):
for case in self.browse(cursor, user, ids, context=context):
if case.email_last:
@ -757,7 +450,7 @@ 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')
self._action(cr,uid, cases, 'escalate')
return True
@ -794,8 +487,9 @@ 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')
return True
self._action(cr,uid, cases, 'draft')
return True
crm_case()
@ -893,13 +587,6 @@ class crm_email_add_cc_wizard(osv.osv_memory):
crm_email_add_cc_wizard()
def _section_get(self, cr, uid, context={}):
obj = self.pool.get('crm.case.section')
ids = obj.search(cr, uid, [])
res = obj.read(cr, uid, ids, ['id','name'], context)
res = [(str(r['id']),r['name']) for r in res]
return res
class users(osv.osv):
_inherit = 'res.users'
_description = "Users"
@ -907,6 +594,3 @@ class users(osv.osv):
'context_section_id': fields.many2one('crm.case.section', 'Sales Section'),
}
users()

View File

@ -0,0 +1,193 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
import time
import re
import os
import base64
import tools
import mx.DateTime
from tools.translate import _
from osv import fields
from osv import osv
from osv import orm
from osv.orm import except_orm
import crm
class case(osv.osv):
_inherit = 'crm.case'
_columns = {
'date_action_last': fields.datetime('Last Action', readonly=1),
'date_action_next': fields.datetime('Next Action', readonly=1),
}
def remind_partner(self, cr, uid, ids, context={}, attach=False):
return self.remind_user(cr, uid, ids, context, attach,
destination=False)
def remind_user(self, cr, uid, ids, context={}, attach=False,
destination=True):
for case in self.browse(cr, uid, ids):
if not case.section_id.reply_to:
raise osv.except_osv(_('Error!'), ("Reply To is not specified in Section"))
if not case.email_from:
raise osv.except_osv(_('Error!'), ("Partner Email is not specified in Case"))
if case.section_id.reply_to and case.email_from:
src = case.email_from
dest = case.section_id.reply_to
body = case.email_last or case.description
if not destination:
src, dest = dest, src
if case.user_id.signature:
body += '\n\n%s' % (case.user_id.signature or '')
dest = [dest]
attach_to_send = None
if attach:
attach_ids = self.pool.get('ir.attachment').search(cr, uid, [('res_model', '=', 'crm.case'), ('res_id', '=', case.id)])
attach_to_send = self.pool.get('ir.attachment').read(cr, uid, attach_ids, ['datas_fname','datas'])
attach_to_send = map(lambda x: (x['datas_fname'], base64.decodestring(x['datas'])), attach_to_send)
# Send an email
flag = tools.email_send(
src,
dest,
"Reminder: [%s] %s" % (str(case.id), case.name, ),
self.format_body(body),
reply_to=case.section_id.reply_to,
openobject_id=str(case.id),
attach=attach_to_send
)
if flag:
raise osv.except_osv(_('Email!'),("Email Successfully Sent"))
else:
raise osv.except_osv(_('Email Fail!'),("Email is not sent successfully"))
return True
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 [])
cases = self.browse(cr, uid, ids2, context)
return self._action(cr, uid, cases, False, context=context)
def _action(self, cr, uid, cases, state_to, scrit=None, context={}):
if not context:
context = {}
context['state_to'] = state_to
rule_obj = self.pool.get('base.action.rule')
model_obj = self.pool.get('ir.model')
model_ids = model_obj.search(cr, uid, [('model','=',self._name)])
rule_ids = rule_obj.search(cr, uid, [('name','=',model_ids[0])])
return rule_obj._action(cr, uid, rule_ids, cases, scrit=scrit, context=context)
def format_body(self, body):
return self.pool.get('base.action.rule').format_body(body)
def format_mail(self, obj, body):
return self.pool.get('base.action.rule').format_mail(obj, body)
case()
class base_action_rule(osv.osv):
_inherit = 'base.action.rule'
_description = 'Action Rules'
def do_check(self, cr, uid, action, obj, context={}):
ok = super(base_action_rule, self).do_check(cr, uid, action, obj, context=context)
if hasattr(obj, 'section_id'):
ok = ok and (not action.trg_section_id or action.trg_section_id.id==obj.section_id.id)
if hasattr(obj, 'categ_id'):
ok = ok and (not action.trg_categ_id or action.trg_categ_id.id==obj.categ_id.id)
if hasattr(obj, 'history_line'):
ok = ok and (not action.trg_max_history or action.trg_max_history<=(len(obj.history_line)+1))
reg_history = action.regex_history
result_history = True
if reg_history:
ptrn = re.compile(str(reg_history))
if obj.history_line:
_result = ptrn.search(str(obj.history_line[0].description))
if not _result:
result_history = False
regex_h = not reg_history or result_history
ok = ok and regex_h
return ok
def do_action(self, cr, uid, action, model_obj, obj, context={}):
res = super(base_action_rule, self).do_action(cr, uid, action, model_obj, obj, context=context)
write = {}
if action.act_section_id:
obj.section_id = action.act_section_id
write['section_id'] = action.act_section_id.id
if hasattr(obj, 'email_cc') and action.act_email_cc:
if '@' in (obj.email_cc or ''):
emails = obj.email_cc.split(",")
if obj.act_email_cc not in emails:# and '<'+str(action.act_email_cc)+">" not in emails:
write['email_cc'] = obj.email_cc+','+obj.act_email_cc
else:
write['email_cc'] = obj.act_email_cc
model_obj.write(cr, uid, [obj.id], write, context)
if hasattr(obj, 'email_from') and action.act_mail_to_partner:
emails.append(obj.email_from)
emails = filter(None, emails)
if len(emails) and action.act_mail_body:
emails = list(set(emails))
self.email_send(cr, uid, obj, emails, action.act_mail_body)
return True
base_action_rule()
class base_action_rule_line(osv.osv):
_inherit = 'base.action.rule.line'
def state_get(self, cr, uid, context={}):
res = super(base_action_rule_line, self).state_get(cr, uid, context=context)
return res + [('escalate','Escalate')] + crm.AVAILABLE_STATES
def priority_get(self, cr, uid, context={}):
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', 'Section'),
'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 section 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()

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!-- Case rules -->
<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">
<field name="trg_partner_categ_id" 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">
<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_user_id" position="after">
<field name="act_section_id"/>
<field name="act_mail_to_partner"/>
</field>
</field>
</record>
</data>
</openerp>

View File

@ -110,8 +110,6 @@
<separator colspan="4" string="Dates"/>
<field name="create_date"/>
<field name="date_closed"/>
<field name="date_action_last"/>
<field name="date_action_next"/>
<field name="log_ids" nolabel="1" colspan="4">
<form string="Actions">
<separator string="Action Information" colspan="4"/>

View File

@ -66,7 +66,7 @@
<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="'crm.case'" name="model"/>
<field eval="'_check'" name="function"/>
<field eval="'()'" name="args"/>
</record>

View File

@ -109,8 +109,6 @@
<separator colspan="4" string="Dates"/>
<field name="create_date"/>
<field name="date_closed"/>
<field name="date_action_last"/>
<field name="date_action_next"/>
<separator colspan="4" string="References"/>
<field name="ref" colspan="4"/>
<field name="ref2" colspan="4"/>

View File

@ -70,8 +70,6 @@
<separator colspan="4" string="Dates"/>
<field name="create_date"/>
<field name="date_closed"/>
<field name="date_action_last"/>
<field name="date_action_next"/>
<separator colspan="4" string="Estimates"/>
<field name="planned_revenue"/>
<field name="planned_cost"/>

View File

@ -99,8 +99,6 @@
<separator colspan="4" string="Dates"/>
<field name="create_date"/>
<field name="date_closed"/>
<field name="date_action_last"/>
<field name="date_action_next"/>
<separator colspan="4" string="References"/>
<field name="ref" colspan="4"/>
<field name="ref2" colspan="4"/>

View File

@ -129,109 +129,8 @@
<field name="view_id" ref="crm_case_section_view_tree"/>
</record>
<!-- <menuitem action="crm_case_section_act_tree" id="menu_crm_case_section_act_tree" parent="next_id_52"/>-->
<!-- 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>
<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="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"/>
<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 +276,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

View File

@ -19,22 +19,9 @@
#
##############################################################################
import time
import re
import os
import mx.DateTime
import base64
from tools.translate import _
import tools
from osv import fields,osv,orm
from osv.orm import except_orm
from crm import crm
class crm_job(osv.osv):
_name = "crm.job"
_description = "Job Cases"
@ -63,13 +50,6 @@ class crm_job(osv.osv):
"the partner mentality in relation to our services.The scale has" \
"to be created with a factor for each level from 0 (Very dissatisfied) to 10 (Extremely satisfied)."),
'phonecall_id':fields.many2one ('crm.phonecall', 'Phonecall'),
}
def onchange_categ_id(self, cr, uid, ids, categ, context={}):
if not categ:
return {'value':{}}
cat = self.pool.get('crm.case.categ').browse(cr, uid, categ, context).probability
return {'value':{'probability':cat}}
crm_job()

View File

@ -127,8 +127,6 @@
<separator colspan="4" string="Dates"/>
<field name="create_date"/>
<field name="date_closed"/>
<field name="date_action_last"/>
<field name="date_action_next"/>
<separator colspan="4" string="References"/>
<field name="ref" colspan="4"/>
<field name="ref2" colspan="4"/>

View File

@ -80,8 +80,6 @@
<separator colspan="4" string="Dates"/>
<field name="create_date"/>
<field name="date_closed"/>
<field name="date_action_last"/>
<field name="date_action_next"/>
<separator colspan="4" string="Estimates"/>
<field name="planned_revenue"/>
<field name="planned_cost"/>

View File

@ -216,8 +216,6 @@
<separator colspan="4" string="Dates"/>
<field name="create_date"/>
<field name="date_closed"/>
<field name="date_action_last"/>
<field name="date_action_next"/>
<separator colspan="4" string="References"/>
<field name="ref" colspan="4"/>
<field name="ref2" colspan="4"/>