[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:
commit
ee87ba0a2b
|
@ -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:
|
|
@ -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:
|
|
@ -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:
|
|
@ -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 '%%' 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>
|
|
@ -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
|
|
|
@ -240,12 +240,12 @@
|
||||||
|
|
||||||
|
|
||||||
<!-- Available alarms-->
|
<!-- Available alarms-->
|
||||||
<menuitem id="menu_calendar_configuration" name="Calendar"
|
<menuitem id="base.menu_calendar_configuration" name="Calendar"
|
||||||
parent="base.menu_base_config" sequence="10" />
|
parent="base.menu_base_config" sequence="10" />
|
||||||
|
|
||||||
<menuitem name="Available Alarms" id="menu_crm_meeting_avail_alarm"
|
<menuitem name="Available Alarms" id="menu_crm_meeting_avail_alarm"
|
||||||
action="base_calendar.action_res_alarm_view"
|
action="base_calendar.action_res_alarm_view"
|
||||||
parent="menu_calendar_configuration" />
|
parent="base.menu_calendar_configuration" />
|
||||||
|
|
||||||
|
|
||||||
</data>
|
</data>
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
"name" : "Share Calendar using Caldav",
|
"name" : "Share Calendar using Caldav",
|
||||||
"version" : "1.0",
|
"version" : "1.0",
|
||||||
"depends" : [
|
"depends" : [
|
||||||
"base_calendar",
|
"base",
|
||||||
],
|
],
|
||||||
'description': """
|
'description': """
|
||||||
Contains basic functionality for caldav system like:
|
Contains basic functionality for caldav system like:
|
||||||
|
|
|
@ -50,10 +50,11 @@
|
||||||
<field name="view_mode">tree,form</field>
|
<field name="view_mode">tree,form</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
<menuitem id="base.menu_calendar_configuration" name="Calendar"
|
||||||
|
parent="base.menu_base_config" sequence="10" />
|
||||||
|
|
||||||
<menuitem id="menu_calendar"
|
<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" />
|
sequence="5" action="action_view_calendar" />
|
||||||
|
|
||||||
</data>
|
</data>
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
import crm
|
import crm
|
||||||
import crm_mailgate
|
import crm_mailgate
|
||||||
|
import crm_action_rule
|
||||||
import crm_segmentation
|
import crm_segmentation
|
||||||
import crm_meeting
|
import crm_meeting
|
||||||
import crm_lead
|
import crm_lead
|
||||||
|
|
|
@ -44,7 +44,7 @@ The CRM module has a email gateway for the synchronisation interface
|
||||||
between mails and Open ERP.""",
|
between mails and Open ERP.""",
|
||||||
'author': 'Tiny',
|
'author': 'Tiny',
|
||||||
'website': 'http://www.openerp.com',
|
'website': 'http://www.openerp.com',
|
||||||
'depends': ['base',
|
'depends': ['base', 'base_action_rule',
|
||||||
'process',
|
'process',
|
||||||
'mail_gateway',
|
'mail_gateway',
|
||||||
'base_calendar',
|
'base_calendar',
|
||||||
|
@ -63,6 +63,7 @@ between mails and Open ERP.""",
|
||||||
'update_xml': [
|
'update_xml': [
|
||||||
'crm_wizard.xml',
|
'crm_wizard.xml',
|
||||||
'crm_view.xml',
|
'crm_view.xml',
|
||||||
|
'crm_action_rule_view.xml',
|
||||||
'crm_lead_wizard.xml',
|
'crm_lead_wizard.xml',
|
||||||
'crm_lead_view.xml',
|
'crm_lead_view.xml',
|
||||||
'crm_lead_menu.xml',
|
'crm_lead_menu.xml',
|
||||||
|
|
|
@ -163,108 +163,6 @@ class crm_case_stage(osv.osv):
|
||||||
|
|
||||||
crm_case_stage()
|
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={}):
|
def _links_get(self, cr, uid, context={}):
|
||||||
obj = self.pool.get('res.request.link')
|
obj = self.pool.get('res.request.link')
|
||||||
ids = obj.search(cr, uid, [])
|
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\'.\
|
\nIf the case is in progress the state is set to \'Open\'.\
|
||||||
\nWhen the case is over, the state is set to \'Done\'.\
|
\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\'.'),
|
\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'),
|
'company_id': fields.many2one('res.company','Company'),
|
||||||
}
|
}
|
||||||
def _get_default_partner_address(self, cr, uid, context):
|
def _get_default_partner_address(self, cr, uid, context):
|
||||||
|
@ -427,164 +322,6 @@ class crm_case(osv.osv):
|
||||||
value['email_from'] = case.email_from
|
value['email_from'] = case.email_from
|
||||||
return {'value': value}
|
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={}):
|
def __history(self, cr, uid, cases, keyword, history=False, email=False, details=None, context={}):
|
||||||
model_obj = self.pool.get('ir.model')
|
model_obj = self.pool.get('ir.model')
|
||||||
for case in cases:
|
for case in cases:
|
||||||
|
@ -615,50 +352,6 @@ class crm_case(osv.osv):
|
||||||
self._action(cr,uid, cases, 'draft')
|
self._action(cr,uid, cases, 'draft')
|
||||||
return res
|
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):
|
def add_reply(self, cursor, user, ids, context=None):
|
||||||
for case in self.browse(cursor, user, ids, context=context):
|
for case in self.browse(cursor, user, ids, context=context):
|
||||||
if case.email_last:
|
if case.email_last:
|
||||||
|
@ -757,7 +450,7 @@ class crm_case(osv.osv):
|
||||||
self.write(cr, uid, ids, data)
|
self.write(cr, uid, ids, data)
|
||||||
cases = self.browse(cr, uid, ids)
|
cases = self.browse(cr, uid, ids)
|
||||||
self.__history(cr, uid, cases, _('Escalate'))
|
self.__history(cr, uid, cases, _('Escalate'))
|
||||||
self._action(cr, uid, cases, 'escalate')
|
self._action(cr,uid, cases, 'escalate')
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@ -794,8 +487,9 @@ class crm_case(osv.osv):
|
||||||
cases[0].state # to fill the browse record cache
|
cases[0].state # to fill the browse record cache
|
||||||
self.__history(cr, uid, cases, _('Draft'))
|
self.__history(cr, uid, cases, _('Draft'))
|
||||||
self.write(cr, uid, ids, {'state':'draft', 'active':True})
|
self.write(cr, uid, ids, {'state':'draft', 'active':True})
|
||||||
self._action(cr, uid, cases, 'draft')
|
self._action(cr,uid, cases, 'draft')
|
||||||
return True
|
return True
|
||||||
|
|
||||||
crm_case()
|
crm_case()
|
||||||
|
|
||||||
|
|
||||||
|
@ -893,13 +587,6 @@ class crm_email_add_cc_wizard(osv.osv_memory):
|
||||||
|
|
||||||
crm_email_add_cc_wizard()
|
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):
|
class users(osv.osv):
|
||||||
_inherit = 'res.users'
|
_inherit = 'res.users'
|
||||||
_description = "Users"
|
_description = "Users"
|
||||||
|
@ -907,6 +594,3 @@ class users(osv.osv):
|
||||||
'context_section_id': fields.many2one('crm.case.section', 'Sales Section'),
|
'context_section_id': fields.many2one('crm.case.section', 'Sales Section'),
|
||||||
}
|
}
|
||||||
users()
|
users()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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()
|
|
@ -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>
|
|
@ -110,8 +110,6 @@
|
||||||
<separator colspan="4" string="Dates"/>
|
<separator colspan="4" string="Dates"/>
|
||||||
<field name="create_date"/>
|
<field name="create_date"/>
|
||||||
<field name="date_closed"/>
|
<field name="date_closed"/>
|
||||||
<field name="date_action_last"/>
|
|
||||||
<field name="date_action_next"/>
|
|
||||||
<field name="log_ids" nolabel="1" colspan="4">
|
<field name="log_ids" nolabel="1" colspan="4">
|
||||||
<form string="Actions">
|
<form string="Actions">
|
||||||
<separator string="Action Information" colspan="4"/>
|
<separator string="Action Information" colspan="4"/>
|
||||||
|
|
|
@ -66,7 +66,7 @@
|
||||||
<field name="interval_type">hours</field>
|
<field name="interval_type">hours</field>
|
||||||
<field name="numbercall">-1</field>
|
<field name="numbercall">-1</field>
|
||||||
<field eval="False" name="doall"/>
|
<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="'_check'" name="function"/>
|
||||||
<field eval="'()'" name="args"/>
|
<field eval="'()'" name="args"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
|
@ -109,8 +109,6 @@
|
||||||
<separator colspan="4" string="Dates"/>
|
<separator colspan="4" string="Dates"/>
|
||||||
<field name="create_date"/>
|
<field name="create_date"/>
|
||||||
<field name="date_closed"/>
|
<field name="date_closed"/>
|
||||||
<field name="date_action_last"/>
|
|
||||||
<field name="date_action_next"/>
|
|
||||||
<separator colspan="4" string="References"/>
|
<separator colspan="4" string="References"/>
|
||||||
<field name="ref" colspan="4"/>
|
<field name="ref" colspan="4"/>
|
||||||
<field name="ref2" colspan="4"/>
|
<field name="ref2" colspan="4"/>
|
||||||
|
|
|
@ -70,8 +70,6 @@
|
||||||
<separator colspan="4" string="Dates"/>
|
<separator colspan="4" string="Dates"/>
|
||||||
<field name="create_date"/>
|
<field name="create_date"/>
|
||||||
<field name="date_closed"/>
|
<field name="date_closed"/>
|
||||||
<field name="date_action_last"/>
|
|
||||||
<field name="date_action_next"/>
|
|
||||||
<separator colspan="4" string="Estimates"/>
|
<separator colspan="4" string="Estimates"/>
|
||||||
<field name="planned_revenue"/>
|
<field name="planned_revenue"/>
|
||||||
<field name="planned_cost"/>
|
<field name="planned_cost"/>
|
||||||
|
|
|
@ -99,8 +99,6 @@
|
||||||
<separator colspan="4" string="Dates"/>
|
<separator colspan="4" string="Dates"/>
|
||||||
<field name="create_date"/>
|
<field name="create_date"/>
|
||||||
<field name="date_closed"/>
|
<field name="date_closed"/>
|
||||||
<field name="date_action_last"/>
|
|
||||||
<field name="date_action_next"/>
|
|
||||||
<separator colspan="4" string="References"/>
|
<separator colspan="4" string="References"/>
|
||||||
<field name="ref" colspan="4"/>
|
<field name="ref" colspan="4"/>
|
||||||
<field name="ref2" colspan="4"/>
|
<field name="ref2" colspan="4"/>
|
||||||
|
|
|
@ -131,107 +131,6 @@
|
||||||
<!-- <menuitem action="crm_case_section_act_tree" id="menu_crm_case_section_act_tree" parent="next_id_52"/>-->
|
<!-- <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 '%%' 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">
|
<record id="view_crm_email_add_cc_wizard" model="ir.ui.view">
|
||||||
<field name="name">Add CC</field>
|
<field name="name">Add CC</field>
|
||||||
<field name="model">crm.email.add.cc</field>
|
<field name="model">crm.email.add.cc</field>
|
||||||
|
@ -377,8 +276,6 @@
|
||||||
<field name="active" select="2"/>
|
<field name="active" select="2"/>
|
||||||
<separator colspan="4" string="Dates"/>
|
<separator colspan="4" string="Dates"/>
|
||||||
<field name="create_date"/>
|
<field name="create_date"/>
|
||||||
<field name="date_action_last"/>
|
|
||||||
<field name="date_action_next"/>
|
|
||||||
<field colspan="4" name="log_ids" nolabel="1">
|
<field colspan="4" name="log_ids" nolabel="1">
|
||||||
<form string="Actions">
|
<form string="Actions">
|
||||||
<separator colspan="4" string="Action Information"/>
|
<separator colspan="4" string="Action Information"/>
|
||||||
|
|
|
@ -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_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_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_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_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_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
|
"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_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_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_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_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_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
|
"access_crm_email_add_cc_manager","crm.email.add.cc","model_crm_email_add_cc","crm.group_crm_manager",1,1,1,1
|
||||||
|
|
|
|
@ -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 import fields,osv,orm
|
||||||
from osv.orm import except_orm
|
|
||||||
|
|
||||||
from crm import crm
|
from crm import crm
|
||||||
|
|
||||||
|
|
||||||
class crm_job(osv.osv):
|
class crm_job(osv.osv):
|
||||||
_name = "crm.job"
|
_name = "crm.job"
|
||||||
_description = "Job Cases"
|
_description = "Job Cases"
|
||||||
|
@ -63,13 +50,6 @@ class crm_job(osv.osv):
|
||||||
"the partner mentality in relation to our services.The scale has" \
|
"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)."),
|
"to be created with a factor for each level from 0 (Very dissatisfied) to 10 (Extremely satisfied)."),
|
||||||
'phonecall_id':fields.many2one ('crm.phonecall', 'Phonecall'),
|
'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()
|
crm_job()
|
||||||
|
|
|
@ -127,8 +127,6 @@
|
||||||
<separator colspan="4" string="Dates"/>
|
<separator colspan="4" string="Dates"/>
|
||||||
<field name="create_date"/>
|
<field name="create_date"/>
|
||||||
<field name="date_closed"/>
|
<field name="date_closed"/>
|
||||||
<field name="date_action_last"/>
|
|
||||||
<field name="date_action_next"/>
|
|
||||||
<separator colspan="4" string="References"/>
|
<separator colspan="4" string="References"/>
|
||||||
<field name="ref" colspan="4"/>
|
<field name="ref" colspan="4"/>
|
||||||
<field name="ref2" colspan="4"/>
|
<field name="ref2" colspan="4"/>
|
||||||
|
|
|
@ -80,8 +80,6 @@
|
||||||
<separator colspan="4" string="Dates"/>
|
<separator colspan="4" string="Dates"/>
|
||||||
<field name="create_date"/>
|
<field name="create_date"/>
|
||||||
<field name="date_closed"/>
|
<field name="date_closed"/>
|
||||||
<field name="date_action_last"/>
|
|
||||||
<field name="date_action_next"/>
|
|
||||||
<separator colspan="4" string="Estimates"/>
|
<separator colspan="4" string="Estimates"/>
|
||||||
<field name="planned_revenue"/>
|
<field name="planned_revenue"/>
|
||||||
<field name="planned_cost"/>
|
<field name="planned_cost"/>
|
||||||
|
|
|
@ -216,8 +216,6 @@
|
||||||
<separator colspan="4" string="Dates"/>
|
<separator colspan="4" string="Dates"/>
|
||||||
<field name="create_date"/>
|
<field name="create_date"/>
|
||||||
<field name="date_closed"/>
|
<field name="date_closed"/>
|
||||||
<field name="date_action_last"/>
|
|
||||||
<field name="date_action_next"/>
|
|
||||||
<separator colspan="4" string="References"/>
|
<separator colspan="4" string="References"/>
|
||||||
<field name="ref" colspan="4"/>
|
<field name="ref" colspan="4"/>
|
||||||
<field name="ref2" colspan="4"/>
|
<field name="ref2" colspan="4"/>
|
||||||
|
|
Loading…
Reference in New Issue