openerp 7.0 升级笔记 ---HR考勤(一)
签到功能说明:
1、右上角的签入签出按钮,动作之间没有时间限制,如果员工误操作,点击两次,则有可能签入之后紧接着就签出,造成数据错误,因此需要限制签入后三分钟之内不能进行签出操作。
2、考虑员工签到的几种实际情况:
(1)正常上下班签到,这个不需要再做任何设置。
(2)上班迟到,一个小时之内,弹出对话框,提示迟到时间,提醒员工注意。如员工因公迟到,或不可抗力迟到,或已到公司却忘记打卡,可以填写说明,提交主管,由主管根据情况,决定是否将员工此次迟到记录在案。需要开发
(3)上班迟到,超过一个小时,不允许再签入,此时已经不能按照迟到处理。员工需要根据实际情况,填写请假单(按照请假处理),因公外出单,或忘记打卡说明单,由主管审批。需要开发
(4)下班前超过一个小时,不能签出,如有事需提前离开,需要填写请假单或因公外出单。需要开发
(5)下班前一个小时之内,可以签出,但是需要说明理由,主管根据员工工作表现和具体情况,决定此次早退是否视为请假。需要开发。
对hr_attendance类进行扩展。
第一个问题比较简单,重载create函数,针对当前时间和最后一次签到时间做一个比较,小于设定值则不允许签到。
代码如下:
def create(self,cr,uid,vals,context=None): now=datetime.datetime.now() employee_id=self._employee_get(cr,uid,context=context) last_sign=self._last_sign(cr,uid,employee_id,context=context) last=datetime.datetime.strptime(last_sign,'%Y-%m-%d %H:%M:%S') if (now-last).seconds<180: raise osv.except_osv(_('错误!'),_('你已经签到,请勿重复操作。')) return False return super(hr_attendance,self).create(cr,uid,vals,context=context)
这里要记录一个问题,在获取最后一次签到时间的时候,一开始的代码如下:
cr.execute("""select max(name) as name from hr_attendance where action in ('sign_in', 'sign_out') and employee_id = %s""",(employee_id,))
这个时候我要同时获取最后一次签到的动作类型,是sign_in或者sing_out,如果直接将代码改成:
cr.execute("""select max(name) as name,action from hr_attendance where action in ('sign_in', 'sign_out') and employee_id = %s group by action""",(employee_id,))
这样得到的结果是:
"2012-12-02 09:33:48";"sign_out"
"2012-12-02 09:24:03";"sign_in"
这就不是我想要的结果了,我需要的是9点33分的那个结果的action类型,也就是sign_out,而不是每一个action都获取一个最大值。
经过google,最终的代码如下:
select a.name,a.action from hr_attendance a inner join (select max(name) as maxf from hr_attendance) b on a.name=b.maxf where employee_id=1
第二个问题,首先需要设置一个上下班的时间,OE自带的resource.canlendar.attendance类可以设置上下班时间,具体设置位置在:设置->底层对象->资源->工作时间。
系统自带的设置我认为并不太适合中国的情况,每一天的时间都要单独设置,难道老外每天上班的时间都不同的?不过貌似这个工作时间主要是用来设置劳动合同中的工作时间项目的。
不管怎样,现在只要设置一天的时间即可,通过当前时间与设置时间的比较,来判断是否迟到,以及是否过了或还未到打卡时间。
代码如下:
work_time=self._get_work_time(cr,uid,context=context)#[(8.75, 17.5)] work_time_in=string.atof(work_time[0][0]) current_time=now.hour+now.minute/60 if current_time>work_time_in: diff=current_time-work_time_in diff_f=diff-int(diff)#取小数位计算分钟数 raise osv.except_osv(_('错误!'),_("今天你迟到了%s小时%s分钟"%(int(diff),int(diff_f*60)))) return False
这里要提到两个问题,一个是设置上下班时间后,系统内的时间字段的定义是否float型的,也就是说,你设置的8:30的上班时间,取值出来则是8.5,xml中有一个新的widget被使用,这个在6.1下是没有见过的:
<field name="hour_from" widget="float_time"/>
另外一个问题是Python本身的问题,如2/3在一般情况下的返回值是0,要想得到实际的计算结果,就必须加入:
from __future__ import division
另外,7.0下的时区还是有问题,datetime.datetime.today()取不到正确的时间,令人郁闷。