跟踪状态基础数据:
kl_qingjd/kl_qingjd_data.xml
<?xml version="1.0"?>
<openerp>
<data
noupdate="1">
<!-- kl_qingjd-related subtypes
for messaging / Chatter -->
<record id="mt_qingjd_confirm"
model="mail.message.subtype">
<field
name="name">已提交</field>
<field
name="res_model">kl.qingjd</field>
<field
name="description">请假申请已提交</field>
</record>
<record
id="mt_qingjd_validate"
model="mail.message.subtype">
<field
name="name">已批准</field>
<field
name="res_model">kl.qingjd</field>
<field
name="description">请假申请已批准</field>
</record>
<record
id="mt_qingjd_refuse"
model="mail.message.subtype">
<field
name="name">已拒绝</field>
<field
name="res_model">kl.qingjd</field>
<field name="default" eval="True"/> <!-- 订阅时,默认激活 -->
<field
name="description">请假申请已拒绝</field>
</record>
</data>
</openerp>
跟踪状态,记录日志,发送消息后台代码:
kl_qingjd/kl_qingjd.py
# -*- encoding: utf-8 -*-
import pooler
import logging
import
netsvc
import tools
logger = netsvc.Logger()
import datetime
import
time
import math
from osv import fields,osv
from
openerp.tools.translate import _ #用于翻译代码中的静态字符串
#假期类型对象
class kl_qingjd_type(osv.osv):
_name =
"kl.qingjd.type"
_description =
u"假期类型"
_order = "num asc, id asc"
#对象字段
_columns =
{
'num':
fields.integer(u'序号'),
'name':
fields.char(u'假期类型', size=64, required=True,
translate=True),
'notes':
fields.char(u'说明', size=200),
}
#数据库约束
_sql_constraints =
[
('name_check', "unique(name)",
u"假期类型已经存在且不允许重复."),
]
kl_qingjd_type()#对象定义结束
#请假单对象
class kl_qingjd(osv.osv):
_name =
'kl.qingjd'
_description = u'kl 请假单'
_order = "date_from asc, type_id asc"
_inherit =
['mail.thread'] #继承消息模块,用于发消息
_track =
{
'state':
{
'kl_qingjd.mt_qingjd_validate': lambda self, cr, uid, obj, ctx=None:
obj['state'] ==
'validate',
'kl_qingjd.mt_qingjd_refuse': lambda self, cr, uid, obj, ctx=None: obj['state']
==
'refuse',
'kl_qingjd.mt_qingjd_confirm': lambda self, cr, uid, obj, ctx=None: obj['state']
== 'confirm',
},
#自动发送系统消息,可用于记录日志或在邮件中显示,在邮件中显示时需要定义消息的子类型(kl_qingjd_data.xml)和指定消息相关用户(self.message_subscribe_users)
}
#获取当前用户所属的员工
def _employee_get(self, cr, uid,
context=None):
ids =
self.pool.get('hr.employee').search(cr, uid, [('user_id', '=', uid)],
context=context)
if
ids:
return ids[0]
return
False
#获取当前用户所属部门的id和名称
def _get_user_department(self, cr, uid,
context={}):
obj =
self.pool.get('hr.employee')
ids
= obj.search(cr, uid, [('user_id','=',uid)])
res = obj.read(cr, uid, ids,
['id','department_id'], context)
return res and res[0]['department_id'] or 0
#检测同一时间段内是否存在相同的请假单,False 是存在,不允许创建
def _check_date(self, cr, uid,
ids):
for rec in self.browse(cr,
uid, ids):
search_ids = self.search(cr, uid, [('date_from', '<=', rec.date_to),
('date_to', '>=', rec.date_from), ('employee_id', '=', rec.employee_id.id),
('id', '<>',
rec.id)])
if
search_ids:
return False
return
True
# TODO: can be improved using
resource calendar method
#计算日期间隔对应的天数
def _get_number_of_days(self, date_from,
date_to):
"""Returns a float
equals to the timedelta between two dates given as string."""
DATETIME_FORMAT = "%Y-%m-%d
%H:%M:%S"
from_dt =
datetime.datetime.strptime(date_from,
DATETIME_FORMAT)
to_dt =
datetime.datetime.strptime(date_to,
DATETIME_FORMAT)
timedelta = to_dt
- from_dt
diff_day =
timedelta.days + float(timedelta.seconds) /
86400
return
diff_day
#对象字段
_columns =
{
'employee_id': fields.many2one('hr.employee', u"申请人",required=True, select=True,
invisible=False, readonly=True,
states={'draft':[('readonly',False)]}),
'department_id':fields.many2one('hr.department', u'申请部门', invisible=False,
readonly=True, states={'draft':[('readonly',False)]}),
#修改职员所属部门后显示原部门
#'department_id':fields.related('employee_id', 'department_id', string=u'申请部门',
type='many2one', relation='hr.department', readonly=True, store=True),
#修改职员所属部门后显示新部门
'type_id': fields.many2one("kl.qingjd.type", u"假期类型",
required=True,readonly=True,
states={'draft':[('readonly',False)]}),
'date_from': fields.datetime(u'起始日期',required=True, readonly=True,
states={'draft':[('readonly',False)]},
select=True),
'date_to': fields.datetime(u'结束日期', readonly=True,
states={'draft':[('readonly',False)]}),
'days': fields.float(u'天数', digits=(8, 2), readonly=True,
states={'draft':[('readonly',False)]}),
'notes': fields.text(u'请假原因',readonly=True,
states={'draft':[('readonly',False)]}),
'manager_id': fields.many2one('hr.employee', u'审批人', invisible=False,
readonly=True,
help=u'审批和拒绝时自动记录审批人'),
'refuse_notes': fields.char(u'拒绝原因', size=200, invisible=False, readonly=True,
states={'confirm':[('readonly',False)],
'validate':[('readonly',False)]}),
'state': fields.selection([('draft', u'草稿'), ('cancel', u'已作废'),('confirm',
u'待审批'), ('refuse', u'已拒绝'), ('validate', u'已审批')], u'状态', readonly=True,
track_visibility='onchange'),
'create_uid': fields.many2one('res.users', u"创建用户", invisible=False,
readonly=True),
#需要在记录中读取该字段或者在视图、打印中显示该字段时,对象中必须包含
'create_date': fields.datetime(u"创建日期", invisible=True, readonly=True),
#需要在记录中读取该字段或者在视图、打印中显示该字段时,对象中必须包含
}
#字段默认值
_defaults = {
'state':
'draft',
'employee_id':
_employee_get,
'department_id': lambda self,cr,uid,context:
self._get_user_department(cr,uid,context),
}
#对象约束
_constraints =
[
(_check_date, u'您在相同的时间段内不允许创建多张请假单!',
[u'起始日期',u'结束日期']),
]
#数据库约束
_sql_constraints = [
('date_check', "CHECK (date_from <= date_to)",
u"开始日期必须小于结束日期."),
('days_check',
"CHECK (days > 0 )", u"请假天数必须大于 0 ."),
]
#创建,此处取消自动记录创建
def create(self, cr, uid, values,
context=None):
""" Override to
avoid automatic logging of creation
"""
if context is
None:
context = {}
context =
dict(context,
mail_create_nolog=True)
return super(kl_qingjd, self).create(cr, uid, values, context=context)
#复制(未知用途)
def copy(self, cr, uid,
id, default=None, context=None):
#if default is None:
# default = {}
#if context is None:
# context = {}
#default = default.copy()
#default['date_from'] = False
#default['date_to'] = False
raise
osv.except_osv(_(u'警告!'),_(u'请假单暂不支持复制功能.'))
return super(kl_qingjd, self).copy(cr, uid, id, default,
context=context)
#写入,可用于校验写入和更改数据的合法性
def write(self, cr, uid, ids, vals,
context=None):
return
super(kl_qingjd, self).write(cr, uid, ids, vals,
context=context)
#删除当前请假单,需要验证请假单的状态
def unlink(self, cr, uid, ids,
context=None):
for rec in
self.browse(cr, uid, ids,
context=context):
if rec.state not in ['draft', 'cancel', 'confirm',
'refuse']:
raise osv.except_osv(_(u'警告!'),_(u'您不能删除以下状态的请假单 %s
.')%(rec.state))
#当请假单不是自己创建的时,不能删除
if (rec.create_uid.id != uid):
#此处需要读取创建者ID时,必须在对象中包含create_uid列
raise
osv.except_osv(_(u'警告!'),_(u'您只能删除自己创建的单据.'))
return super(kl_qingjd, self).unlink(cr, uid, ids,
context)
#更换员工时自动修改员工所属的部门
def onchange_employee(self, cr, uid,
ids, employee_id):
result =
{'value': {'department_id':
False}}
if
employee_id:
employee = self.pool.get('hr.employee').browse(cr, uid,
employee_id)
result['value'] = {'department_id':
employee.department_id.id}
return
result
#更改起始日期,自动计算请假天数
def onchange_date_from(self, cr, uid,
ids, date_to, date_from):
"""
If there are no date set for
date_to, automatically set one 8 hours later
than
the
date_from.
Also update the
number_of_days.
"""
# date_to has to be greater
than date_from
if (date_from and
date_to) and (date_from >
date_to):
raise osv.except_osv(_(u'警告!'),_(u'开始日期必须小于结束日期.'))
result = {'value': {}}
# No date_to set so far:
automatically compute one 8 hours
later
if date_from and not
date_to:
date_to_with_delta = datetime.datetime.strptime(date_from,
tools.DEFAULT_SERVER_DATETIME_FORMAT) +
datetime.timedelta(hours=8)
result['value']['date_to'] = str(date_to_with_delta)
# Compute and update the number of
days
if (date_to and date_from)
and (date_from <=
date_to):
diff_day = self._get_number_of_days(date_from,
date_to)
result['value']['days'] =
round(math.floor(diff_day))+1
else:
result['value']['days'] = 0
return
result
#更改结束日期,自动计算请假天数
def onchange_date_to(self, cr, uid, ids,
date_to, date_from):
"""
Update the
number_of_days.
"""
# date_to has to be greater
than date_from
if (date_from and
date_to) and (date_from >
date_to):
raise osv.except_osv(_(u'警告!'),_(u'开始日期必须小于结束日期.'))
result = {'value': {}}
# Compute and update the number of
days
if (date_to and date_from)
and (date_from <=
date_to):
diff_day = self._get_number_of_days(date_from,
date_to)
result['value']['days'] =
round(math.floor(diff_day))+1
else:
result['value']['days'] = 0
return
result
#设置为草稿状态,需要重新初始化工作流
def set_to_draft(self, cr, uid, ids,
context=None):
for rec in
self.browse(cr, uid, ids,
context=context):
#当请假单不是自己创建的时,不能设置为草稿
if rec.create_uid.id !=
uid:
raise
osv.except_osv(_(u'警告!'),_(u'您不能设置他人创建的单据为草稿状态.'))
self.write(cr, uid, ids,
{
'state':
'draft',
'manager_id':
False,
'refuse_notes':False
})
#重新初始化工作流
wf_service =
netsvc.LocalService("workflow")
for id in
ids:
wf_service.trg_delete(uid, 'kl.qingjd', id, cr)
#传入对象名称
wf_service.trg_create(uid, 'kl.qingjd', id,
cr)
return
True
#审批请假单,自动记录审批人
def set_to_validate(self, cr, uid, ids,
context=None):
#审批时,此处可以增加审批权限的校验
for rec in
self.browse(cr, uid, ids,
context=context):
#当请假单的主管不是自己时,不能审批
if rec.employee_id and rec.employee_id.parent_id and
rec.employee_id.parent_id.user_id:
if rec.employee_id.parent_id.user_id.id !=
uid:
raise
osv.except_osv(_(u'警告!'),_(u'您不能审批当前单据,应由申请人的主管审批.'))
else:
raise
osv.except_osv(_(u'警告!'),_(u'您不能审批当前单据,应由申请人的主管审批.'))
obj_emp =
self.pool.get('hr.employee')
ids2
= obj_emp.search(cr, uid, [('user_id', '=',
uid)])
manager = ids2 and ids2[0]
or False
#self.send_validate_notificate(cr, uid, ids, context=context)
#批准时发送消息给自己,跟系统自动发送的消息重复
return self.write(cr, uid, ids, {'state':'validate', 'manager_id':
manager})
#发送消息给自己,已批准
#def send_validate_notificate(self, cr, uid,
ids, context=None):
# for obj in
self.browse(cr, uid, ids, context=context):
# self.message_post(cr, uid, [obj.id],
body=_(u'您的请假申请已批准!'), context=context)
#提交请假单,发送消息给主管
def
set_to_confirm(self, cr, uid, ids,
context=None):
#发送消息给主管
for rec in
self.browse(cr, uid, ids,
context=context):
#当请假单不是自己创建的时,不能提交
if rec.create_uid.id !=
uid:
raise
osv.except_osv(_(u'警告!'),_(u'您不能提交他人创建的单据.'))
#提交请假单时发送系统消息,指定消息相关的用户(发送消息给主管和自己),消息的起始点,如果接收人只有自己则消息不在邮件中显示
if rec.employee_id and rec.employee_id.parent_id and
rec.employee_id.parent_id.user_id:
self.message_subscribe_users(cr, uid, [rec.id],
user_ids=[rec.employee_id.parent_id.user_id.id],
context=context)
return
self.write(cr, uid, ids, {'state': 'confirm'})
#拒绝请假单,自动记录审批人
def
set_to_refuse(self, cr, uid, ids,
context=None):
for rec in self.browse(cr, uid,
ids,
context=context):
#当请假单的主管不是自己时,不能拒绝
if rec.employee_id and rec.employee_id.parent_id and
rec.employee_id.parent_id.user_id:
if rec.employee_id.parent_id.user_id.id !=
uid:
raise
osv.except_osv(_(u'警告!'),_(u'您不能拒绝当前单据,应由申请人的主管拒绝.'))
else:
raise
osv.except_osv(_(u'警告!'),_(u'您不能拒绝当前单据,应由申请人的主管拒绝.'))
#拒绝时验证决绝原因不能为空
if (rec.refuse_notes == False) or (rec.refuse_notes.strip() ==
''):
raise
osv.except_osv(_(u'警告!'),_(u'拒绝原因不能为空,请编辑并填写.'))
obj_emp =
self.pool.get('hr.employee')
ids2
= obj_emp.search(cr, uid, [('user_id', '=',
uid)])
manager = ids2 and ids2[0]
or False
#self.send_refuse_notificate(cr, uid, ids, context=context)
#拒绝时发送消息给自己,跟系统自动发送的消息重复
return self.write(cr, uid, ids, {'state':'refuse', 'manager_id':
manager})
#发送消息给自己,已拒绝
#def send_refuse_notificate(self, cr, uid,
ids, context=None):
# for obj in
self.browse(cr, uid, ids, context=context):
# self.message_post(cr, uid, [obj.id],
body=_(u'您的请假申请已拒绝!'), context=context)
kl_qingjd()#对象定义结束
openerp学习笔记 跟踪状态,记录日志,发送消息的更多相关文章
-
RocketMQ 源码学习笔记————Producer 是怎么将消息发送至 Broker 的?
目录 RocketMQ 源码学习笔记----Producer 是怎么将消息发送至 Broker 的? 前言 项目结构 rocketmq-client 模块 DefaultMQProducerTest ...
-
RocketMQ 源码学习笔记 Producer 是怎么将消息发送至 Broker 的?
目录 RocketMQ 源码学习笔记 Producer 是怎么将消息发送至 Broker 的? 前言 项目结构 rocketmq-client 模块 DefaultMQProducerTest Roc ...
-
【Visual C++】游戏编程学习笔记之八:鼠标输入消息(小demo)
本系列文章由@二货梦想家张程 所写,转载请注明出处. 作者:ZeeCoder 微博链接:http://weibo.com/zc463717263 我的邮箱:michealfloyd@126.c ...
-
APUE学习笔记——10.9 信号发送函数kill、 raise、alarm、pause
转载注明出处:Windeal学习笔记 kil和raise kill()用来向进程或进程组发送信号 raise()用来向自身进程发送信号. #include <signal.h> int k ...
-
webservice系统学习笔记5-手动构建/发送/解析SOAP消息
手动拼接SOAP消息调用webservice SOAP消息的组成: 1.创建需要发送的SOAP消息的XML(add方法为例子) /** * 创建访问add方法的SOAP消息的xml */ @Test ...
-
rabbitMQ学习笔记(二) 简单的发送与接收消息 HelloWorld
首先要下载rabbitmq的javaClient库,然后加入到项目中,下载地址为:http://www.rabbitmq.com/releases/rabbitmq-java-client/v3.1. ...
-
ucos实时操作系统学习笔记——任务间通信(消息)
ucos另一种任务间通信的机制是消息(mbox),个人感觉是它是queue中只有一个信息的特殊情况,从代码中可以很清楚的看到,因为之前有关于queue的学习笔记,所以一并讲一下mbox.为什么有了qu ...
-
【Visual C++】游戏编程学习笔记之七:键盘输入消息
本系列文章由@二货梦想家张程 所写,转载请注明出处. 作者:ZeeCoder 微博链接:http://weibo.com/zc463717263 我的邮箱:michealfloyd@126.c ...
-
RabbitMQ学习系列二-C#代码发送消息
RabbitMQ学习系列二:.net 环境下 C#代码使用 RabbitMQ 消息队列 http://www.80iter.com/blog/1437455520862503 上一篇已经讲了Rabbi ...
随机推荐
-
关于更改MYECLIPSE JS 代码背景颜色
白色的背景,看花了眼,你想改一下编辑器的背景颜色,移步这里就可以了. 这时你高兴的打开编辑器,发现颜色确实变了,但是当你打开有JS的JSP时,你碉堡了,发现JS的背景颜色还是默认的, 看着让人纠结,好 ...
-
Oracle ->;>; 连续聚合
select id, grp_factor, sum (id) over( partition by grp_factor order by id rows between unbounded pre ...
-
backbone-1.3.3源码解析-----------Event
第一次写,写的不对的请指正 backbone.js中的Event实现了自定义事件.自定义事件就是一个对象的键值对,key为事件名,value为一个function数组.在backbone这个对象中有一 ...
-
/Home/Tpl/Equipment/rangeIndex.html 里调用魔板
<pre name="code" class="html">demo:/var/www/DEVOPS# vim ./Home/Tpl/Equipme ...
-
JSP导出Excel后身份证后三位为0
JSP导出Excel身份证号码超出Excel最大限制,用科学计数法表示,但后三位为0,修改方式: <style type="text/css">.txt { ...
-
CMDB资产管理系统开发【day25】:表结构设计1
资产表 # _*_coding:utf-8_*_ __author__ = 'jieli' from assets.myauth import UserProfile from django.db i ...
-
sql 查询语句的练习2
--14.列出所有雇员的雇员名称.部门名称和薪金. select e.ename,d.dname,e.sal from emp e,dept d where e.deptno = d.deptno;- ...
-
前端自动化构建工具webpack (二)之css和插件加载总结
1. webpack只识别js文件,其他文件都需要转换成js文件.所有文件都是模块; 2. css解析 css需要css-loader --->style-loader ----- ...
-
JVM探秘2--详解内存溢出OutOfMemoryError异常
JVM运行时内存被划分成多个区域,而除了程序计数器之外,其他几个区都会出现OutOfMemoryError异常,主要原因就是对应内存区域的内存不足以再分配内存,一般要么是内存泄漏了要么就是内存参数设置 ...
-
[转帖]新的Linux后门开始肆虐 主要攻击中国服务器
新的Linux后门开始肆虐 主要攻击中国服务器 https://www.cnbeta.com/articles/tech/815639.htm 一种新的 Linux 系统后门已经开始肆虐,并主要运行在 ...