超實用的精細化處理考勤(原創)

如何精細化處理考勤

新單位對考勤的核算要求比較高,員工在平時工作日和週末的加班要分開覈算,普員和中乾的加班覈算方式不同,中乾的平時加班是不算加班費的,加班小時數要按季度算工作,員工可以在季末申請剩餘的小時數結轉到下個季度,加班要逐次累計,有加班數纔可以調休,調休數不可以大於可用的加班數。員工要能實時看見自己的可用加班數。如果沒有或不夠,不讓建流程。要方便考勤人員查看每個人的數據確定考勤,因爲必須得一個一個看。
怎麼樣,是不是有點暈啊。
開始吧。

設計

首先聲明,公司的OA系統是基於泛微Ecology8. 總體需要考慮幾個大的部分:
1、員工考勤數據的可視化和流程控制,強調實時性
這要包含具體的流程表單的控制,也要有統計報表。
2、方便考勤人員覈算
主要是通過流程節點控制和優化,當然,完全的自動化考勤是不可能的。

技術實現

第一部分:考勤數據可視化

後臺建立兩個表:
考勤數據的明細表:包含加班時數、調休時數、請假時數,公休日和工作日用一個flag區分,如HD是公休日,WD是工作日。
考勤數據餘額表:這個表是記錄季度餘額的表,其實也可以不設這個表,但是因爲考勤是按季度覈算的,有些人的考勤餘額要轉到下個季度,爲了數據清晰和系統性能,還是設計這個表(我不想一下子把1年或幾年的數據都查出來),這樣最後出來的最多的是餘額+本季的數據。

形成
調用
結轉
加班流程
明細表
調休流程
餘額表

效果

加班流程表單:
在這裏插入圖片描述
生成的明細表:
在這裏插入圖片描述

季末形成的餘額表,這個通過泛微的計劃任務接口做:
在這裏插入圖片描述

調休時可根據明細表和餘額表計算得出可用的調休時數,並顯示出來。
在這裏插入圖片描述

剩餘可用時數的顯示,泛微有現成的doFieldMath()函數,也可以使用ajax,這裏不再贅述。

流程生成報表可以泛微的流程節點附加操作掛在自定義接口來實現。在這裏加班和調休使用相同的接口,根據標誌的不同而進行區分,加班的接口放在歸檔處(因爲需要人事專員確認實際的加班時數),調休的接口放在人事專員之前。
上接口代碼:

package develop.workflow;
import weaver.interfaces.workflow.action.Action;
import weaver.general.BaseBean;
import weaver.soa.workflow.request.RequestInfo;
import weaver.soa.workflow.request.Property;
import weaver.conn.RecordSet;
import weaver.general.Util;
import java.text.SimpleDateFormat;
import java.util.*;
public class overTime extends BaseBean implements Action {
	public String execute(RequestInfo requestinfo) {
	    String requestid = requestinfo.getRequestid();  
		Property[] properties = requestinfo.getMainTableInfo().getProperty();// 獲取表單主字段信息      
		String ymd =  Util.null2String(properties[26].getValue());
		String userid = Util.null2String(properties[16].getValue());
		String avaliable = Util.null2String(properties[30].getValue());
		String realhour = Util.null2String(properties[4].getValue());
		String series = Util.null2String(properties[34].getValue());	  
		String thistime = Util.null2String(properties[22].getValue());
    	String qt = Util.null2String(properties[11].getValue());
    	String sal = Util.null2String(properties[24].getValue());
    	String delayhour = Util.null2String(properties[25].getValue());
    	String leave = Util.null2String(properties[10].getValue());
    	String type = Util.null2String(properties[9].getValue());
    	String ifconvert = Util.null2String(properties[3].getValue());
    	
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//
		String datetime = df.format(new Date());// new Date()  
		Calendar calendar=Calendar.getInstance();
		int mth = calendar.get(Calendar.MONTH) + 1;
		int yr = calendar.get(Calendar.YEAR);
		String year = String.valueOf(yr);
		String month = String.valueOf(mth);
		String[] fa = {"1","2","3"}; 
		String[] sa = {"4","5","6"};
		String[] ta = {"7","8","9"};
		String[] la = {"10","11","12"};
		
    
		String quarter = "";
		String note = "";
		String sql = "";
	
		if (Arrays.asList(fa).contains(month)) {
			quarter = "1";
		 }else if(Arrays.asList(sa).contains(month)){
			quarter = "2";
		}else if(Arrays.asList(ta).contains(month)){
			quarter = "3";
		  }else if(Arrays.asList(la).contains(month)){
			quarter = "4";
		}
		
	
			  RecordSet rs = new RecordSet();
			 
	   //計算加班時數,工作日和週末分開,WD工作日。HD週末,法定節假日乘2
		if (realhour != "") {
			int type1 = Integer.parseInt(type);
			if (type1 == 2) {
				note = "HD";
				double r = Double.valueOf(realhour);
				r = r * 2;
				String r1 = String.valueOf(r);
				sql = "insert into formtable_main_902(requestid,userid,overtime,series,quarter,datetime,year,month,note) values('"+requestid+"','"+userid+"','"+r1+"','"+series+"','"+quarter+"','"+datetime+"','"+year+"', '"+month+"','"+note+"')";
				  rs.executeSql(sql);
			}else {
				if (type1 == 0) {
			
				note = "WD";
				} else if (type1 == 1) {
			
				note = "HD";
				}
				  sql = "insert into formtable_main_902(requestid,userid,overtime,series,quarter,datetime,year,month,note) values('"+requestid+"','"+userid+"','"+realhour+"','"+series+"','"+quarter+"','"+datetime+"','"+year+"', '"+month+"','"+note+"')";
				  rs.executeSql(sql);
			}
	  }
			
		//計算無調休的請假,全部請假
		note = "LV";
		int	cv = Integer.parseInt(ifconvert);
		if (ifconvert != "") {
		  
		
		
		if (cv == 0) {
			sql = "insert into formtable_main_902(requestid,userid,on_leave,series,quarter,datetime,year,month,note) values('"+requestid+"','"+userid+"','"+leave+"','"+series+"','"+quarter+"','"+datetime+"','"+year+"', '"+month+"','"+note+"')";
			  rs.executeSql(sql);
		} 
		
		else if (cv == 1) {
			// 部分請假
			float pt1 = Float.parseFloat(leave);
			float pt2 = Float.parseFloat(thistime);
			float pt3 = pt1 - pt2;
			if (pt3 > 0) {
				//請假的部分
				String pt = String.valueOf(pt3);
				sql = "insert into formtable_main_902(requestid,userid,on_leave,series,quarter,datetime,year,month,note) values('"+requestid+"','"+userid+"','"+pt+"','"+series+"','"+quarter+"','"+datetime+"','"+year+"', '"+month+"','"+note+"')";
				  rs.executeSql(sql);
				
				
			}
		}
	}	
		
		
		//計算調休
	    if (thistime != "" && cv != 0) {
	    	  note = "OF";
			  sql = "insert into formtable_main_902(requestid,userid,overoff,series,quarter,datetime,year,month,note) values('"+requestid+"','"+userid+"','"+thistime+"','"+series+"','"+quarter+"','"+datetime+"','"+year+"', '"+month+"','"+note+"')";
			  rs.executeSql(sql);
	       }
	
	       
        //季末延遲調休
		if (qt != "") {
			
		    //發薪部分
			if (sal != "") {
				
				note = "Q_SAL";
				sql = "insert into formtable_main_905(requestid,userid,sal,series,quarter,datetime,year,month,note) values('"+requestid+"','"+userid+"','"+sal+"','"+series+"','"+quarter+"','"+datetime+"','"+year+"', '"+month+"','"+note+"')";
				rs.executeSql(sql);
				sql = "insert into formtable_main_902(requestid,userid,sal,series,quarter,datetime,year,month,note) values('"+requestid+"','"+userid+"','"+sal+"','"+series+"','"+quarter+"','"+datetime+"','"+year+"', '"+month+"','"+note+"')";
				rs.executeSql(sql);
			}
	    	//平衡本季餘額
			note = "Q_END";
	    	sql = "insert into formtable_main_902(requestid,userid,overoff,series,quarter,datetime,year,month,note) values('"+requestid+"','"+userid+"','"+avaliable+"','"+series+"','"+quarter+"','"+datetime+"','"+year+"', '"+month+"','"+note+"')";
			  rs.executeSql(sql); 
			 
			//將結轉部分轉到下月期初
				float s1 = 0;
		    	float s2 = 0;
		    	float off = 0;
		    	float q_bal_hd = 0;
		    	float q_bal_wd = 0;
		    	float q_lv = 0;
		    	String quarter1 ="";
		    	String year1 ="";
		    	String month1 = "";
		    	//本季總的平時加班數
		    	note = "WD";
		    	sql = "select sum(overtime) as sum from  formtable_main_902 where note = '"+note+"' and quarter = '"+quarter+"' and year = '"+year+"' and userid = '"+userid+"'";
		    	rs.executeSql(sql);
		    	if (rs.next()) {
		    		 s1 = rs.getFloat("sum");
		    		
		    	}
		    	//週末加班數
		    	note = "HD";
		    	sql = "select sum(overtime) as sum from  formtable_main_902 where note = '"+note+"' and year = '"+year+"' and quarter = '"+quarter+"' and userid =  '"+userid+"'";
		    	rs.executeSql(sql);
		    	if (rs.next()) {
		    		 s2 = rs.getFloat("sum");
		    		
		    	} 
		    	
		    	//調休數
		    	note = "OF";
		    	sql ="select sum(overoff) as sum from  formtable_main_902 where note = '"+note+"' and quarter = '"+quarter+"' and year = '"+year+"' and userid = '"+userid+"'";
		    	rs.executeSql(sql);
		    	if (rs.next()) {
		    		off = rs.getFloat("sum");
		    		if(off < 0)
		    			off = 0;
		    		
		    	}
		    	
		    	//上季度加班餘額
		    	
		    	note = "Q_BAL_WD";
		    	sql = "select sum(overtime) as overtime from  formtable_main_905 where note = '"+note+"' and quarter = '"+quarter+"' and year = '"+year+"' and userid = '"+userid+"'";
		    	rs.executeSql(sql);
		    	if (rs.next()) {
		    		q_bal_wd = rs.getFloat("overtime");
		    		if (q_bal_wd < 0)
		    			q_bal_wd = 0;
		    		
		    	} 
		    	s1 = s1 + q_bal_wd;
		    	note = "Q_BAL_HD";
		    	sql = "select sum(overtime) as overtime from  formtable_main_905 where note = '"+note+"' and quarter = '"+quarter+"' and year = '"+year+"' and userid = '"+userid+"'";
		    	rs.executeSql(sql);
		    	if (rs.next()) {
		    		q_bal_hd = rs.getFloat("overtime");
		    		if (q_bal_hd < 0)
		    			q_bal_hd = 0;
		    	} 
		    	s2 = s2 + q_bal_hd;
		
		    	float s3 = s1 - off;
		    	float hd_bal = 0;
		    	float wd_bal = 0;
		    	if (s3 < 0) {
		    	  hd_bal = s2 + s3;
		    	  wd_bal = 0;
		    	} else {
		    	  wd_bal = s3;
		    	  hd_bal = s2;
		    	}
		    
		    	float d1 = Float.parseFloat(sal);
		    	
		    	float s4 = wd_bal - d1;
		    	if (s4 < 0) {
			    	  hd_bal = hd_bal + s4;
			    	 
			    	  wd_bal = 0;
			    	} else {
			    	//  hd_bal = hd_bal;
			    	  wd_bal = s4;
			    	}
		    	//結轉到下季
		    	if (quarter == "1" || quarter == "2" || quarter == "3") {
					 int q = Integer.parseInt(quarter);
					 q = q + 1;
					 quarter1 = String.valueOf(q);
					 year1 = year;
					 int mth1 = mth + 1;
					  month1 = String.valueOf(mth1); 
					
				 } else if (quarter == "4") {
					 quarter1 = "1";
					 int y = Integer.parseInt(year);
					 y = y + 1;
					 year1 = String.valueOf(y);
					 month1 = "1";
				 }
		    if (hd_bal > 0) {
	    	note = "Q_BAL_HD";
	    	sql = "insert into formtable_main_905(requestid,userid,overtime,series,quarter,datetime,year,month,note) values('"+requestid+"','"+userid+"','"+hd_bal+"','"+series+"','"+quarter1+"','"+datetime+"','"+year1+"', '"+month1+"','"+note+"')";
			  rs.executeSql(sql); 
		    }
		    if (wd_bal > 0) {
			note = "Q_BAL_WD";
		    sql = "insert into formtable_main_905(requestid,userid,overtime,series,quarter,datetime,year,month,note) values('"+requestid+"','"+userid+"','"+wd_bal+"','"+series+"','"+quarter1+"','"+datetime+"','"+year1+"', '"+month1+"','"+note+"')";
			rs.executeSql(sql);   
		    }
			sql = "select sum(on_leave)  as sum from  formtable_main_902 where year = '"+year+"' and quarter = '"+quarter+"' and userid =  '"+userid+"'";
			rs.executeSql(sql); 
			if (rs.next()) {
				q_lv = rs.getFloat("sum");
				if (q_lv > 0) {
					note = "Q_LV";
					sql = "insert into formtable_main_905(requestid,userid,on_leave,quarter,datetime,year,month,note) values('"+requestid+"','"+userid+"','"+q_lv+"','"+quarter+"','"+datetime+"','"+year+"', '"+month+"','"+note+"')";
		    		rs.executeSql(sql); 
				}
            }
			
	       }
		
		  return SUCCESS ;  
	   }
	}

到這裏第一部分基本完成了,但是還需要再加一點工作,就是流程的校驗,比如可調休時數爲0,不允許提交流程,不允許調休超過可調休時數的流程。就用泛微提供的函數:checkCustomize,該函數在流程提交時進行校驗,如果不通過就返回 false,流程就不能提交了。

在這裏插入圖片描述

至此第一部分就完成了。

第二部分 方便考勤人員

由於考勤人員需要對每個人覈對考勤,還要換算保留兩位小數,可以看到考勤人員的工作量還是比較大的。
思路是整合考勤系統,在具體的審批單的考勤節點設置兩個按鈕“查考勤”和“填考勤”,查考勤功能通過ajax獲取申請人那一天的考勤數據,形成一個頁面,然後返回給主單據頁面,祝單據頁面在適當位置建立一個iframe,src指向這個頁面就OK了。當然這個頁面除了顯示考勤數據外,還要有計算加班時數的功能,要能區分工作日和公休日,考勤數據沒有形成的時候也不至於報錯。
效果如下:
在這裏插入圖片描述
點擊“查考勤"按鈕:
在這裏插入圖片描述

點擊”填考勤“按鈕,會將實際考勤時數填寫。
在這裏插入圖片描述

怎麼樣,是不是極大的提高了效率。
轉載請註明出處。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章