现在不明白是:
1:加班怎么样设计.
2:比如在7:30---11:30之间有多少条打卡记录应该怎么处理?
3:什么是考勤异常,该如何设计与处理?分不够再加.越详细越好.顶者有分.

解决方案 »

  1.   

    什么叫越详细越好,如果真的是详细,那么文档厚厚一大叠逐渐回答问题1、加班一般分为固定加班和自由加班
       固定加班类似于普通上下班,其中具体可以分为4种:
       A、固定时间,就是和普通上下班一样,有迟到早退问题
       B、超时计加班,譬如12:00下班,如果到了12:30可以算加班半小时
       C、早到计加班,类似上面
       D、连班,譬如中午8:00-12:00/14:00-18:00,那么12:00-14:00之间可能会计算加班,当然要控制扣除中间吃饭时间   自由加班简单就是在某个时间段内,何时来都可以计算加班
       譬如18:00-23:00算加班时间,如果是19:00-21:00,那么算加班2小时   其中自由加班的算法又可以分为8种,简单说几种
       1、按指定时间取整计算,譬如8:08开始加班,可以自由设置为8:08/8:15/8:30
       2、按照次数计算,譬如指定时间段内只能有2次
       3、超时转页计算
       4、先计算后取整
       ......2、如果是自由加班那就是小儿科的问题了,按照次序一进一出就完了,依次算多次上下班
       如果是正常上下班就罗嗦之极
       譬如如果 9:00-10:00请假一小时,那么应该要刷卡4次,否则肯定是旷工
       如果时间乱,那么可能有很多废卡,直接标记为废卡不参与计算即可
       如果......3、考勤异常,那可就多了,迟到、早退、旷工、空卡、签卡、多刷卡......要考虑这么多啊
    如果真的完全通用,一个好的考勤计算软件大约需要4000-8000行左右的存储过程进行计算,这可是一个相当庞大的工程
      

  2.   

    这个只是一个很初步的方案,具体的方案远远比这个更加复杂
    当然,如果你的考勤软件是用在那种早九晚五的普通公司,那么寥寥几行SQL语句即可搞定,如果在工厂,尤其是台湾的工厂,这可相当的复杂,当然价格也是>5W的
      

  3.   

    凑下热闹。
    1、要通用,就应该没有排班。
    2、加班就是正常上班时间之外的打卡记录,但这里可能关系到取卡技巧的问题,有些地方可能还要求与加班纸配合。
    3、7:30-11:30,如果是工作时间,有多笔记录,则肯定是外出,应有假条。如果是非工作时间,如7:30下班,11:30上班,则取期间的两笔,min和max就可以了,其它的是废卡。
      

  4.   

    我觉得楼主的很多问题,应该去找人事了解,先了解了需求才有设计。各企事业单位的人事制度是有所不同的。30多种的并不算多,我还见过有超过一百二十多种的,这个种类,关键看你如何去划分。其实加班无非就是Hank (星星农场)说的几种外加一些如法定假期等的特例而构成。
      

  5.   

    呵呵.找人事了解是有一定的帮助.但众所周知,每一个企业的情况是不太一样的.取一家的人事制度进行研究不足以解决软件的通用性的问题.当然了,要做到完全通用也只是一个相对的说法,一个字,难!,无论怎么讲,还得尽量往通用这个方向靠拢.现在的问题难度就是,在进行逐步分析的时候,感觉很烦锁,有时候自已也弄糊涂了,才发现分析打卡记录时有很多的情况需要考虑.
    我现在是这样做的:
    第一步:制定好排班表       
           根据班次表和时间段关系表,可以得出某一段时间内(用户制定的开始和结束时间)的所有组(此组是指班次与时间段关系进行分组,也就是一个时间段的集合.然后用户与此组建立联系)的排班方案,此方案包含了朝九晚五制(员工组和时间段的关系是一对多),轮班制(员工组和时间段的关系是一对一,但需要根据时间循环),N分制(员工组和时间段的关系是一对一,不需根据时间循环),以及考勤方式按打卡次数,按累计工时,按固定时间考勤. 比如办公室组(朝九晚五制)在2008-01-01号哪几个时间段内需要上班;锅炉组(轮班制)的A班在2008-01-01号在哪个时间内需要上班,B班在2008-01-02需要上哪个班.裁剪车间(N分制:就是把一天的时间划分N等分)A班需要在2008-01-01需要在哪个时间段上班.在此排班表中,包含班前加班时间段,根据上下班的冗余时间得出每个时间段落的最早打卡时间,最晚打卡时间,上下班是否需要打卡,上班打卡时间段,下班打卡时间段,迟到时间段,旷工时间段(早退情况下的旷工时间段和迟到情况下的旷工时间段),早退时间段,下班打卡时间段,直落加班时间段,是否跨天(跨天的情况下,前面的时间段会根据此条件自动计算,避免在分析考勤时再去计算)
    形成一个工作日的排班格式如下:
    [排班流水号][排班时间][时间段名称][班前加班开始时间][班前加班长度][上班最早打卡时间][上班时间点][上班最晚打卡时间点][迟到长度][迟到截止时间][ 旷工截止时间(上班段)] [旷工长工][旷工截止时间][早退截止时][下班最早打卡时间点]     [下班时间][下班最晚打卡时间][直接加班时长][跨天][加班][...]
    如果一个工作日有三段(早中晚,视实际情况而定),则上面的记录有三条.第二步:根据打卡记录生成打卡记录视图
     包含如下字段
    [卡号][员工姓名][打卡时间]第三步:进行分析打卡记录
    我原来是对所有用户组进行循环,找出该组的在某段时间的排班记录,然后再找到该组的用户的打卡记录与排班表进行对比.但是后来存储过程越写越长,写的自已也糊涂了(分析情况太多了),就写不下去了.
    又改成对第一个用户逐一循环,先根据用户所在的组,找到该用户的排班表,然后再对打卡记录进行循环.但发现问题依然存在,主要集中在某一时间段(上面的排班表中的时间段内)内
    1:比如有多条记录,特别是在正常工作时间内有多条记录,如果要精确到求出具体出去了几分钟的话,得分析哪条是进哪条是出,在同一时间内如果连续打一两下,其实按道理应该只算一条.这样就无法判断.我又设想如果两次打卡的时间差在三分钟内一条记录;
    2:对于晚上加班一直到第二个工作日(或者下一次上班时间),如果有一条打卡记录,怎么区分是加班的结束时间或是下一个上班时段打卡?如果这个卡落在了允许班前加班的时间段内,又如何区是班前加班的开始时间或者是前天晚上加班的结束时间?
    3:在正常加班时间段内有多条记录怎么办?如果记录是偶数,表示出厂后就再也没有进来了.或者到晚上有一条记录,可能是这其中进来了没有打卡,哪么这个从出去到进来这段时间应该算是正常上班,但是他没有打卡,只能算做旷工,这样的情况如何纠正?
    4:对于一直加班了一天或N天的而没有打卡该怎么样处理(工厂确实存在这样的情况,尽管劳动法不允许这样做)?
    5:请做过考勤分析的兄弟给点比较健全的思路,或者说处理这些情况(跨天,统计旷工,旷工跨天,请假跨天,多条记录,进出厂记录有效的判断,实际工作时间,加班时间...)有一个比较清晰的思路.现在我越做脑子越乱,十来遍了,写到一一半又卡住了,又重写.又有好几天卡住没有写代码了.
    6:欢迎相互交流.分不够可以另开贴再加!!!!
      

  6.   

    那你的彻底理清思路再说,考勤这玩意毕竟是一个相当复杂的东西,我见识过的最离谱的厂有200个班次,本来应该是没这么多的,只是根据就餐规定(员工分三拨就餐)认为的错开了这么多,而且有很多特殊岗位的特殊人员看看这个   http://www.starfarmsoft.com/Aoitine/index.htm
      

  7.   

    3:什么是考勤异常,该如何设计与处理? 就是不该打的时候打了,比如早上8点上班,下班之前就打卡跑了。该打卡的时候又忘记打卡了处理:先要分析 报告打卡异常,还要能消除这些异常。PS:我觉得 排班 不是最好的方案,因为经常变化,而且你叫HR小姐排班她很不耐烦,因为不了解生产计划,也不认识那些人。
      

  8.   

    我也有做這種考勤系統,確實是要考慮的情況太多,再結合計薪方式,其要處理的分支很多。1、不敢用SQL寫考勤存储过程,程序直接從數據庫取數據後作本地分析,最後將分析結果寫回數據庫,1081人,74個班次,計算一個月考勤,一般C4 1.7G 256M的電腦不超過30秒就可完成,計算時間約1~3秒,其他是從數據庫讀數據及寫數據的時間。用SQL寫是不可能這麼快的,而且用SQL寫無法做到面向對象,出錯了讓人抓狂,時間久一點都讓人不願再看那長長的SQL語句,可擴展性可維護性差,而考勤面對的可能性太多,日後的變數也很大,難以維護的考勤軟件是沒有前途的,所以建議直接用支持面向對象的語言如pascal c++等編寫。我是選用BCB寫。2、排班,不排班的智能班次(或智能班次組),出來的結果沒有說服力,如果考勤與薪資掛鉤,那麼最好不要使用智能選班次的行為,因為一個月下來,總有幾個人是算錯的,你又是如何發現哪幾個是錯的?如何向那幾個少數員工解析?固定排班後,有理有據的考勤數據就能上得了公堂。不排班的智能班次只能適用於班次簡單,人員較少的情況。同時,加班,請假,異常情況等等,都需要與當日班次一起校驗才能正常識別,這也使智能班次的實用性大大降低。3、加班與請假,可能會影響原有的班次設定,使得預定的上下班打卡時間發生變化,這也是智能選班的方式很難做到不出錯的一個重要原因。4、异常的反饋與追蹤,所謂異常,一般是指當天上班不正常,出現早退 遲到 缺席 ...等情況,另外還要處理的是:加班單無效,請假無效或請假期間打卡等情況。請假期間打卡或安排休息的時間打卡,一般為別人代打卡,所以這也是一種異常。這些均要手工處理,系統只要將異常列出即可。5、腳本語言支持及考勤規則定制,考勤系統復雜,因為太多的考勤規則,結合薪資計算方式時,規則將呈指數增長,一些考勤軟件試圖用腳本語言去定制這些規則。注意大部分軟件只能是定制薪資項目,未能做到定制考勤規則。6、有效刷卡,連續刷卡很多考勤機都能自行識別,遇考勤機不能識別時,就將2~5分鐘內的刷卡視作一條刷卡記錄即可。7、歷史記錄問題,如員工的考勤班組變更記錄,部門變更記錄,磁卡持有變更...等等情況,目的是,系統支持重算3個月前的考勤數據嗎?那個每天部門出勤人數統計有沒有考慮員工部門調動啊,現在重算一次可以嗎?   總結,考勤至少需要面對以下對象:員工,磁卡,班次,排班,加班,請假,異常情況。支持得越多,需要面向的對象就越多,對象間的千絲萬縷關系就越容易扯不清,所以使用SQL過程或VB之類的對面向對象支持不好的技術,在需要變更時將困難重重。
      

  9.   

    PS:"我觉得   排班   不是最好的方案,因为经常变化,而且你叫HR小姐排班她很不耐烦,因为不了解生产计划,也不认识那些人。"
      這個問題可將排班工作下放至部門,各部門自行排班,自行錄入加班與請假數據等,做好部門權限的設定工作即可。其實,如果軟件的排班系統做得好的話,HR小姐足可應付。如星星农场所說,程序员需要解决的是如何让排班次更简单,方便,更灵活,工作量更小 。再加上一句,如何讓使用者更直觀地查詢到自己所排的班次,方便直觀地知道HR小姐沒排錯班。復雜考勤軟件的目標:有理可依,有據可查;歷史能夠重現,操作員作弊也可輕易查出。上傳兩張圖片,居然要先放到blog中,不知道CSDN有沒有快速的上傳圖片的方法。
    個人月排班及加班請假排定個人考勤明細
      

  10.   

    PS:比如在7:30---11:30之间有多条打卡记录应该怎么处理?   
    1、先匹配正常的上下班时段,时段段可分为:上班允许刷卡时段,下斑允许刷时段,班段内刷卡时段,上班刷卡以最后一次刷卡为准,下班刷卡以最先一次刷卡为准,中间刷卡则要视中间有无请假或异常情况出现。
    2、允许刷卡时段交叉的情况,即相邻班段间允许刷卡的时间范围相交叉的情况,这是软件要智能识别的地方,如果出现太多的刷卡,其实都能正确识别的,多出的卡被作为无效卡,唯一不能识别的是相邻交叉时段只有一张刷卡的情况,此时不能匹配是属于哪一个班段的刷卡,那么就该将情况记录到考勤日记中,然后使用就近规则或优先规则选择匹配其中一个班段即可(该情况为员工不正常刷卡导致,计算为哪个班段员工均无话可说,系统只能依据预定义规则划分班段,规则一般选用朝向员工有利的方向,以减少工时纠纷)。
    3、每一个计算项目均可能有不同的选项,每一个员工其选项都可能不同,这就让SQL过程很难处理复杂考勤过程,选用面向对象的语言结合专用脚本来定制考勤计算过程就显得非常必要。
    强烈建议抛弃写SQL过程来计算考勤这种难以维护的方法。当然如果软件定位是只处理简单考勤或单一模式考勤则另作别论。  我正在改进这种复杂考勤系统中,虽然工作重点是生产管理系统而不是考勤系统,但欢迎讨论拍砖。
      

  11.   

    如某部门,8:30上班,17:30下班,有午餐时间,时间从11:00-13:00其中的任意一个小时,可以从11:00-12:00,也可以从12:00到13:00,由部门按排,你HR小姐如何排定其中某人的班?你看一下上面那個個人考勤明細中的圖,上面的班次簡要說明,會發現,這個問題是要在班次中支持這種用餐制度,所以考勤結果中會多出一項用餐超時。
    也就是,你所設計的班次,要支持這種用餐制度,而不是遇到了問題就回避。要明白,這種班次是合理的,軟件要做出支持,計算時規則是多了一些,但我這裡的結果是軟件能處理這種自由用餐制度。自由用餐制度,指允許用餐時間是2小時,但你只能在30分鐘內用餐完畢,否則為用餐超時,這情況稱為自由用餐方式;另一種為浮動用餐方式即同樣允許用餐是11:00~12:30小時,但你只能在以下預定的用餐時段用餐:11:00~11:30 11:15~11:45 11:30~12:00 12:00~12:30 ,不在預定義用餐時段則異常,這種方式叫浮動用餐時段。這裡還遇到的實際情況有:員工真實用掉30分鐘的用餐時間,但依據不同工種,工時中只扣除15分鐘,或不扣,這種情況。這裡也是體現考勤的復雜性的一個方面,再次建议抛弃写SQL过程来计算考勤这种难以维护的方法。在企業出現這種用餐制度時,在班次中直接支持是最好的解決方法,一些軟件不在班次中支持,就用了智能班次的概念,即將所有用餐時間及上下班時間都列出來,形成多個班次,劃為一個班次組,然後智能匹配其中一組。該方式因為與實際情況不夠吻合,不說是否能正確匹配班次,單是排次就多出了很多,而且沒有用餐超時這個概念,實施起來難度稍大些。
      

  12.   

    想了想PPOwer的话.感觉就算是用面向对象的方法.也无法抛开存储过程的应用.
    最起码的比如找到上班的最大一条记录,比如某一条打卡记录是否落在请假或者节假日之内等等.如果用面向对象的方面首先将时间段和班次建立对象.取得这些对象列表,再进行比如的话,感觉比用存储过程来的更慢,而且更不方便.
      

  13.   

    想了想PPOwer的话.感觉就算是用面向对象的方法.也无法抛开存储过程的应用. 
    最起码的比如找到上班的最大一条记录,比如某一条打卡记录是否落在请假或者节假日之内等等.如果用面向对象的方面首先将时间段和班次建立对象.取得这些对象列表,再进行对比的话,感觉比用存储过程来的更慢,而且更不方便.
    特地查看了在DateUtils单元中, 无法找到类似BetWeen结构的语法.如果在将一个用户的某一个工作日的时间段放在TStringList中的话,再去结合打卡时间比如,简直就是折磨人!
    难道PPower有更好的解决方案?望赐教!
      

  14.   

    簡述應用“問題分解”來分析考勤計算過程
    1、首先要解決工廠的考勤,自然是要逐個計算出每個人的考勤。
    2、再看個人,對於一個人,要分開天計算,也就是工作日這個概念,解決了一個人某一天的考勤那麼個人當月考勤也就解決了,
    那麼考勤計算的基本單位是一個人一天的數據量,首先有數據分配給對象,整塊數據如何切割成小塊,這個遍歷一次就可以切割成很多對象,當初我想要計算更快,每100個人開一個線程來計算,後來實際運行發現,速度瓶頸不在計算,速度瓶頸在於計算好的數據向數據庫提交SQL語句這裡,也就不在使用線程來分配任務,簡單地循環即可。工作天分割也是考勤計算中的一個難點,畢竟要支持跨天,及可能的24小時以上的加班或其他異常。
    3、做好工作天分割後,就是刷卡與班次的匹配,這個交給各個班次執行,因為不同的班次其匹配邏輯不一樣。
    4、異常處理,加班,請假,出差等異常其處理模式很相似,一般加班請假等都會被分配到天,也就是該天有無加班請假在最終做刷卡匹配時,是一目了然的。 
    5、計算完畢後,那麼你就要定義計算的結果是什麼,這樣數據的來攏去脈就理出一條路線來了。最後將結果送回數據庫就行了。
    <你參考上面給出的個人考勤明細,那當天數據要清楚地展現出來,也就是原始數據要劃分到天,這也符合問題分解的原則:將復雜的問題分解成一個個子問題,逐一解決。加班也是,請假或異常是跨工作天的,那就多天共用一條請假記錄。>
    6、如果你要考慮員工歷史記錄對考勤及其統計的影響,你會感覺用SQL實在不知道如何辦才好了。而在考勤對象中,面對歷史記錄,一切都那麼自然。
       歷史記錄的影響:1、排班分部門(考勤班組)排班及個人排班,當員工部門(考勤班組)變更,那班次會跟著變,所以必須追蹤異動記錄以推算出當天班次,然後每天部門人數統計也面臨同樣問題,薪資計算也是,因為調動到不同的部門後,其薪資計算方法不同,你也得追蹤歷史記錄。....歷史記錄是人事系統不可回避的問題。如果不支持歷史記錄,考勤將結果的來攏去脈SHOW出來時,難免牽強。
    “.如果在将一个用户的某一个工作日的时间段放在TStringList中的话,”確實,每個人每天的數據將都被放於各個對象內,內存中,所以計算起來才飛快,但不是TStringList中。班次是一個對象,其中有各種各樣的班次,但每種班次必須完成幾乎相同的任務,也就是算法接口,這裡可以使用繼承,對於算法,因為我用C++,也就部分用了模板,用Pascal時,最多就是多寫幾行代碼每種班次類型全都重寫一下,調試修改代碼時工作量就稍大些。排班也是一個對象,通過繼承或組合可以派生很多種排班方法,但無論哪種排班方法,總要給出當天排的是什麼班次,這就是接口。你說的問題:“比如某一条打卡记录是否落在请假或者节假日之内等等.”這個簡單些歸納為一個函數就行了。我是引申出時段的概念,上班時段,用餐時段,加班段,請假期間,等等時段,“打卡记录是否落在時段之內”那只是一個時間對比問題,該函數應該很好寫才對。時段要支持的一些常用函數是求多個時段的交集,時間是否在時段內,時段整體偏移等等函數。在解決時段求交時,BetWeen是不行的,還是得寫函數。從上面寫的,該可以感覺出面向對象方法擴展性極強,模塊重用性也高。不是面向對象的方法不好,而是面向對象需要先做對象分析,然後再將對象顆粒化,定義對象功能屬性,寫出對象間的接口, 最後才是編碼驗證階段,如果熬到編碼階段,那成功幾乎是在向你招手了。往往程序員只是粗粗分析一下規劃一下模塊,就動手寫代碼了,這樣出來的對象,其難成體系,對象模型不明確,也就收不到預期的效果,急功近利比較難做出好產品。但總是分析沒有代碼或階段性成果,也是讓人倍受壓力。如果初期分析規劃較好,就可以先做簡單的實現,後期擴展到復雜的實現,從而讓軟件實現螺旋式前進。
    今天在BLOG寫了一下用“問題分解”方法來分析考勤對象的過程,可惜提交時沒成功,是想將逐步將考勤對象體系的建立與考勤模型的形成這個分析過程寫出來,目的是一起共享解決問題的分析方法,代碼與語言確實不是很重要的。其實,如果你從來沒有在面向對象中嘗過甜頭的話,參考我所說的來做,或許對你來說是惡夢的開始,或許直接采用你熟悉的方法能更快地交付出一個可用的版本,但如果想走入面向對象的大門的話,拿出勇氣與智慧來實踐才行。我也是在實踐在摸索,我水平不好,光這個就熬了一個多接近兩個月,感覺寫考勤計算過程是很累人的活,但如果做完後很難更改擴展,就累得沒有價值了。 
      

  15.   

    顺便说一句.一定要轮班. 为什么 HR不知道班次? 如果她不知道她怎么算工资呢?所以她一定要知道的.这个班次只要在最后统计之前上报就OK了.而且作为一个运作正常的公司,班次都是正常的设置一次就OK了,~个别情况都是需要班组上报,部门上报 
    :)~ 不要用我们程序员的眼光看企业的运作 ,呵呵.我也是算跑过蛮多客户单位的人了
      

  16.   

    楼上的tetsuya说得在理,复杂问题要简单化,而不是复杂化,要有变化,但更应该有一定的规则,上下班打卡就
    该按规则打卡,不按规则打卡就报异常,异常反馈后可以取消。
      

  17.   

    to PPower:
    请问你的工作天的定义是如何设想的?
    你上面的工作天是8小时;哪么一个工作天的开始时间和结束时间是怎么得来的呢?
    另外在求取某员工某天的有效打卡时间范围又如何设计的呢?
    望赐教!
      

  18.   

    比如:要求分析出某员工在2008-01-02的打卡记录与排班记录;
    该员工的工作时间段为:2008-01-02 20:30:00 到 2008-01-04 02:00:00 (跨了两天);
    哪么提取打卡记录范围应该是2008-01-02 20:00:00到2008-01-04 19:59:59(假设可以提前和推迟半小时打卡);问题出来了?
    上面的Case中,2008-01-02,2008-01-03这两天的打卡记录都应该取2008-01-02 20:00:00到2008-01-04 19:59:59之间的记录;
    在这里有点混乱了;感觉不太合理;你是怎么处理这个问题呢?
      

  19.   

    你可以參考一下BLOG中描述的班次及規則設定
    http://blog.csdn.net/PPower/archive/2008/02/21/2111975.aspx
    http://blog.csdn.net/ppower/archive/2008/02/20/2109073.aspx班次定義的是一個工作天該如何刷卡,規則又是如何。如果班次定義過於簡單,處理復雜問題時就會出現“已知條件不足”難以計算的現象。我是在班次中定義一個工作天是從什麼時候開始,又到哪結束的。當出現加班超過工作天定義時,才修改實際工作天切割點。工作天切割點是需要調整的,有時排班就會出現工作天沖突的現象,如果兩個工作天其上下班時間沖突,那麼在排班時就應該檢測到,並提出警告。
    如果工作天切割時間沖突,則視加班及實際刷卡情況進行適當調整。最終刷卡是可以合理分配到正確的工作天去的。因為如果刷卡不能合理地分配到正確的工作天去,那麼就算是人工算考勤,也沒辦法算清楚了,所以,只要已知條件充分,刷卡就一定能正確合理地分配到工作天去,這也是班次匹配的基礎。(具體過程你不會連代碼也要我貼出來吧)该员工的工作时间段为:2008-01-02   20:30:00   到   2008-01-04   02:00:00   (跨了两天); 
    可定義工作天為:2008-01-02   12:00:00 - 2008-01-03 12:00:00 , 一天剛好24小時。
    加班及轉班時一天可能定義為36小時。連續工作48小時以上者,要求將加班時間切割成兩個工作天,即加班單可以跨一天,但不能跨兩天,跨兩天時,將其中一部分加班時間要放入第二個工作天去。如果想簡單一點實現,可以先分析一下具體工廠所用到的班次,先做需要用到的部分,然後逐步擴展,這也是軟件工程所倡導的模式。一下子全部到位,寫計算過程會讓人瘋掉的,記住設計留下接口,逐步實現。
    因工作原因(頭大了),這段時間不想再討論考勤問題了,如果討論BOM的生產工藝接口或生產排程則歡迎,請見諒。
      

  20.   

    要重視游戲規則設定,如曠工的定義,是缺勤8小時以上算曠工,還是當天無刷卡算曠工,還是曠工需要開異常單指定,等等規則,因為在不同的企業中同是曠工確實有著不同的解析。特別是在每天考勤報表中要反映的各部門 當天應出勤人員,實際出勤人員,曠工,新入廠,離職(部門則是調入調出),其中同樣的術語,但在不同的廠其解析不同,導致計算結果不是客戶所需要的。全部情況羅列出來的話,組合爆炸現象會令數據太多,系統很快變慢。目前SQL Server使用AMDX2-3600+ 2G內存,數據庫備份達1.7G(含生產管理系統),正常在線用戶數 > 10 ,但速度還是沒慢下來。規則定制可以讓用戶需要的數據得以計算及顯示,避免進行無用的計算及數據傳輸。請將游戲規則擺出來,不要玩黑箱操作。
      

  21.   

    To PPOwer:
    首先感谢ppOwer兄弟的热情回复;
    近日拜读了你的文章<<考勤術語及規則定制>>和<<考勤中的班次>>两篇文章;
    -------------------------------------------------------------------------------------------------
    有两点不太清楚:
    1:
    在考勤中的班次的第三点"工作天"的重要性这一节中有如下内容:
    '班次解决了员工当天该如何上下班,排班指定了员工当天上哪个班次。这个天并非我们时常说的24小时的一天,而是“工作天”。一个工作天可能不止24小时。班次中定义工作天的起止时间点,加班可能会改变该时间点,从而使得一个工作天实际上不止24小时。'
    我的理解是这样的:
    一个工作日是24小时[24小时制]的情况下:比如,通常的朝九晚五制;
    第一个班段时间为: [2000-01-01 9:00:00   至  2000-01-01 12:00:00];
    第二个班段时间为: [2000-01-01 13:00:00  至  2000-01-01 18:00:00];
    第三个班段时间为: [2000-01-01 18:00:00  至  2000-01-01 20:00:00];
    哪么当前工作日的起止时间是? {从第一天的00:00:00到当天的23:59:59}
                            或 {(假设允许提前和推迟半小时打卡)为:2000-01-01 08:30:00至 2000-01-01 20:30:00} ??
    一个工作日是36小时[36小时制]的情况下:
    第一个班段时间为: [2000-01-01 9:00:00至2000-01-01 16:00:00];
    第二个班段时间为: [2000-01-01 17:00:00至2000-01-01 23:30:00];
    第三个班段时间为: [2000-01-02 00:00:00至2000-01-02 07:00:00];
    第四个班段时间为: [2000-01-02 07:30:00至2000-01-02 11:30:00];
    哪么当前工作日的起止时间是? {从第一天的00:00:00到第二天的12:00:00}
                            或 {(假设允许提前和推迟半小时打卡)为:2000-01-01 08:30:00至 2000-01-02 12:30:00} ??一个工作日是48小时[48小时制]的情况下:
    第一个班段时间为: [2000-01-01 9:00:00至2000-01-01 16:00:00];
    第二个班段时间为: [2000-01-01 17:00:00至2000-01-01 23:30:00];
    第三个班段时间为: [2000-01-02 00:00:00至2000-01-02 07:00:00];
    第四个班段时间为: [2000-01-02 07:30:00至2000-01-02 20:00:00];
    第五个班段时间为: [2000-01-02 07:30:00至2000-01-02 20:00:00];
    哪么当前工作日的起止时间是? {从第一天的00:00:00到第二天的23:59:59}
                            或 {(假设允许提前和推迟半小时打卡)为:2000-01-01 08:30:00至 2000-01-02 23:59:59} ??...72小时制...略;2:
    在<<考勤術語及規則定制>>文章中的第一节考勤班次的设定第五点:工作天定义:默认每工作天为8小时;
    我猜想这里的8小时是指在24小时制下每个工作天的正班时长为8小时;
    有点不清楚这里的8小时意义?
    我想应该有以下几个方面可以用到:
    (1):可以考核在自由班次中某个员工是否上足了8小时的班;-----------------------------------------------------------------------------------------------------问题的引出:
    案例:
    比如某员工A的班次时间段为(允许提前和推迟30分钟打卡){暂不考虑每一个时间段匹配到具体到哪一天的情况}:
    [
     第一个班段时间为: [2000-01-01 9:00:00至2000-01-01 16:00:00];
     第二个班段时间为: [2000-01-01 17:00:00至2000-01-01 23:30:00];
     第三个班段时间为: [2000-01-02 00:00:00至2000-01-02 07:00:00];
     第四个班段时间为: [2000-01-02 07:30:00至2000-01-02 20:00:00];
     第五个班段时间为: [2000-01-02 07:30:00至2000-01-02 20:00:00];
    ]比如某员工A的打卡记录为:
    [
      2008-01-01  08:00:00
      2008-01-02  20:45:00  
    ]>1:如果排班按工作日进行排的话,这个工作日的具体起止时间如何确定?
    >2:如果按某一段时间内的具体某天进行循环的话,如何确定某一天在哪一个工作日内?因为工作日可能有跨几天的情况;比如:2008-01-01和2008-01-02这两天其实都是排的一个工作日的排班记录;
    >3:同理:对于取得打卡记录,如果是36小时制或者48小制,按某一天取打卡记录是不对的,应该按工作天的开始时间和结束时间进行去取得这个时间范围内的打卡记录;
    >4:在分析考勤的时候,是按工作日进行分析还是按具体某一天进行分析?望赐教,不胜感激!
      

  22.   

    1、当前工作日的起止时间,在班次中手工設定。程序只作合理性檢測,但不作推測。
    2、默认每工作天为8小时 , 是指每8個工時合計為一個天(計算薪資時)。或許寫成:
      計薪時:每工作天為8個工時。那是因為一些工廠計薪時,分開日薪時薪所致。
    3、案例: 
    比如某员工A的班次时间段为(允许提前和推迟30分钟打卡){暂不考虑每一个时间段匹配到具体到哪一天的情况}: 

      第一个班段时间为:   [2000-01-01   9:00:00至2000-01-01   16:00:00]; 
      第二个班段时间为:   [2000-01-01   17:00:00至2000-01-01   23:30:00]; 
      第三个班段时间为:   [2000-01-02   00:00:00至2000-01-02   07:00:00]; 
      第四个班段时间为:   [2000-01-02   07:30:00至2000-01-02   20:00:00]; 
      第五个班段时间为:   [2000-01-02   07:30:00至2000-01-02   20:00:00]; 

    比如某员工A的打卡记录为: 

        2008-01-01     08:00:00 
        2008-01-02     20:45:00     
    ] > 1:如果排班按工作日进行排的话,这个工作日的具体起止时间如何确定? 
    A:手工確定,可設定為:2008-01-01 00:00:00 - 2008-01-02     24:00:00     
      但是這樣之後會產生一個問題,即工作日不能連續,即 1/1 號上班,1/2號必然無任何工時(因為2日所有時間都被計入上一天中去了),企業選擇這樣的班次制度,應該只是特殊情況(第二天應該是休息吧),否則企業應該有其他管理制度以適應該情況。注意:班次中的工作天劃分設定是手工設定的,那就會出現相鄰兩天劃分時間沖突的問題,這也是軟件要解決的問題。> 2:如果按某一段时间内的具体某天进行循环的话,如何确定某一天在哪一个工作日内?因为工作日可能有跨几天的情况;比如:2008-01-01和2008-01-02这两天
    其实都是排的一个工作日的排班记录; 
    A:排班是按工作是按工廠日歷進行按的班,並不是按公歷進行排班。的?結合班次中的工作天設定及排班,可能清楚地知道某一天在哪一个工作日内。
       比如:2008-01-01和2008-01-02这两天其实都是排的一个工作日的排班记录; 這情況是班次有48小時的情況,那麼排班時應該是隔天排班的。如果連續排班,那麼無法知道當天是屬於哪個工作天。所以最好是一個班次不要超過36小時。> 3:同理:对于取得打卡记录,如果是36小时制或者48小制,按某一天取打卡记录是不对的,应该按工作天的开始时间和结束时间进行去取得这个时间范围内的打卡记录; 
    A:取某一天打卡记录,這個問題也就是工作日分割問題,48小時時,就會造成下一個工作日無工時,因為當天所有刷卡及工時都被算入上一個工作天去了。
      單純地按班次中預定義的工作天切割點去進行切割是不行的,因為1、加班會超過工作天定義。2、相鄰工作天可能沖突。3、要處理36小時或48小時這種變態班次,軟件中處理的原則是按預定義的切割點進行切割,沖突時考慮允許刷卡時段及實際刷卡情況。
      有些情況是無法調解的,如:第一天排夜班 1-1 19:00 ~ 1-2 7:00 第二天,排班時排白班 1-2 7:00 ~ 1-2 19:00 , 這種情況在早上7:00鐘的刷卡就無法簡單識別是屬於哪一個工作天。此時就要視實際情況來劃分切割點,如果在允許刷卡段 6:30-7:30 間多於1張卡,那麼就將卡平均分配給兩個工作天,如果沒有刷卡,那麼就將切割點定義在 7:00 ,因為沒有刷卡,就不會錯。當只有一張卡時,優先分配給能夠匹配上下班的那一天。這種簡易的沖突在排班時就能檢測出來,排班時就該提出警告(只是警告,但允許這情況存在):“相鄰工作天上下班時間沖突!”所以轉班時,專門定義一個轉班班次,能夠良好地解決這種情況。> 4:在分析考勤的时候,是按工作日进行分析还是按具体某一天进行分析? 
    A:先按自然天分析出工作日切割時間,然後按工作日進行最終考勤匹配分析。  
      

  23.   

    To ppower:
    根据你的提供的思路和方法,一直做到了今天,在理论上来说,觉得使用面向对象的方法的优势是明显的,也将使用Sql语句的方法改为面向对象的方法了。目前卡在了最关键的部分,即对考勤结果的分析上面,一直在努力向你提出的能够回朔到最原始的信息靠拢;目前的问题有两个,还望不啬赐教;
    第一个问题就是时间段的确定的问题.
    问题的产生:比如将要处理一个时间段,如某一个正班段(起点为A终点为B);欲分析出这个段内的的不应考勤段(节假日段,请假段,出差段)和应考勤段(正班段),得出一个正班段内的明细情况,结果类似如以下格式:----------------------------------------------------------------------
    |正班段(1) | 出差段(1) |  请假段  |  出差段(2) | 段(n)   |    正班段   ....
    ------------------------------------------------------------------------
    A-------->A1-------->A2-------->A3---------->An.......->An+1-------->B;以是一个正班段内的明细情况(包含了请假,出差,节假日等情况分析),它始于正班段的A点终于正班段的B点;说到这里就知道是要求N个时间段交集的问题,明确的确定出是什么情况段,它的始点和终点时间;
    他的优先级情况应该是:
    第一级:节假日;  凡是处于节假日内,1,请假情况将不存在;2:出差算是节假日出差;3:正班段算为节假日加班;
    第二级:出差和请假;包含请假内出差了或者出差的时间内请假了的情况;
    第三级:正班段;余下的就是处理正班段;其实我一直怀疑这样做会不会影响速度。毕竟在第一个时间段内都要分析这样的情况,哪一个工作日如果有三段,则成了
    (3*3(or >3))*6(卡的次数; or >6)=54(一天的循环处理次数。最少的54次).当然这是后话;问题:不知你是如何处理这个交集的情况的?或者说你是另外一种思路,不会出现处理交集的情况;望指明出路;第二个问题就是打卡点的匹配.
    承接第一个问题的描述;
    问题的引出:如果在A-A1段中有一个打卡时间,
    第二个打卡点可能落在B内(A1到A2,A2到A3,A3到A4不可能出现打卡点,出现了算无效.),即可能落在B外;该如何处理这个段的考勤情况得出考勤结果呢?
      

  24.   

    1、你可以先不用考慮速度問題。除非你在計算過程中使用DataSet,而且頻繁移動記錄指針,否則速度不成問題。我的做法是將數據讀入內存中,DataSet只是一個跳板,讀入內存後DataSet就沒用了。用DBX要比用ADO移動記錄指針的速度快很多。
    2、我覺得你用
    ---------------------------------------------------------------------- 
    ¦正班段(1)  ¦ 出差段(1)  ¦  请假段   ¦  出差段(2)  ¦ 段(n)    ¦    正班段   .... 
    ------------------------------------------------------------------------ 
    A--------> A1--------> A2--------> A3----------> An.......-> An+1--------> B; 
    這種預計算時段的方式,或許計算效率會高一些,但不是很符合面向對象的原則,算法上已經將班次與出差請假融合在一起了,這將使得擴展一個班次類型或請假類型的難度增加。這種方式的匹配思路是先將所有已經條件的考勤結果羅列出來,然後對號入座。這是面向過程的思維方式,也是我們所說的瀑布式開發,前提是情況都已經全部知道了,這不符合復雜的考勤環境,在復雜的考勤環境下,我們不能預料所有的考勤情況。舉例:請假有很多種,其對上下班時間的影響也不一樣,如果班次是采用相對自由的上下班(一天只要上8小時,時間自由掌握),這時對應的請假單上可能是:今天請假3小時,根本沒有具體的請假時間,這時又如何應對?班次有很多種,請假、加班也有很多種,在某些班次類型下,只能匹配對應的請假加班種類,不符合條件的請假加班就是無效的不合理的。這樣設計的考勤模型,我們只需要不停地加入新的班次類型,新的請假類型,新的加班類型,就能有更多的選擇,以適應新的考勤規則。而不是一開始就把所有的規則都搞通搞透,采用瀑布式開發。面向對象的開發過程,大都是走螺旋式上升的逐步開發的過程,並不需要一開始就對整個情況了如指掌。我的做法是:在班次匹配時,不考慮加班與請假,這樣班次的匹配邏輯就不會過於困難,也符合對象內聚的原則,保證對象的可擴展性。請假加班的處理使用其自己內部的邏輯對班次的匹配結果進行再修改。堅持將復雜問題逐步分解為一個個的小問題,然後逐一解決的原則。另外,节假日與薪資計算相關,因為並不會因為是節假日而采用不同的考勤規則,但是有不同的計薪規則,考勤與薪資是分開設計的。這裡再次體現“問題分解”這個方法的應用。3、對於打卡點的匹配,本來班次中就明確規定了什麼時候是無效的打卡,請假時也有規定,又是該如何打卡的,如果上班時中途請假,一般要求打卡,也可以不用打卡就下班,直接就默認請假單是有效的,這要看考勤設定。因為每一個項目的設定都不少,所以要將這些設定分類整理,計算時才能有足夠的已知條件,考勤才能管理得井井有條。4、至於計算速度的問題,真是不用過多考慮,因為是分級計算的,一般情況下,請假人數較少,所以程序很少進入到請假處理邏輯段中,加班倒是多一些,但常見的加班類型其計算速度也是挺快的,不常見的也就不用管速度快慢了。如果發現速度有問題,那才統計速度瓶頸出現在哪裡,專門針對該瓶頸進行加速,這樣才是王道。我的經驗是:將計算結果提交回數據庫執行占去了總時間的60%以上,我是在事務中用大量的insert into 語句遞交考勤結果,用的是SQL Server 或許 Oracle會快些,但沒試過。可預測的速度是:AMD3600+ 1G內存下,30秒/K人月,1W人月的話就要5分鐘。如果不能接受該速度可考慮升級服務器。
    下面貼出來的是實際計算提示:(總共26s)
    2008/03/10 09:53:07:計算考勤,開始從服務器取得數據
    2008/03/10 09:53:08:開始計算,人數:1129
    2008/03/10 09:53:08: 錯誤的請假單:有薪假期,不允許切割班段。日期:2008/02/26,員工:胡立鋒[045745],假期:2008/02/26 08:30:00--2008/02/26 20:00:00
    2008/03/10 09:53:09:當次加班無效(加班時間與上班時間有重復):盧聖燕[056258],2008/02/28
    2008/03/10 09:53:09:當次加班無效(加班時間與上班時間有重復):劉亮亮[066738],2008/02/25
    2008/03/10 09:53:09:當次加班無效(加班時間與上班時間有重復):劉亮亮[066738],2008/02/28
    2008/03/10 09:53:09:計算完成,准備提交數據
    2008/03/10 09:53:12:刪除舊考勤結果成功,日期:2008/02/01--2008/02/29,耗時:3s
    2008/03/10 09:53:12:開始輸出考勤結果
    2008/03/10 09:53:32:輸出考勤結果成功,耗時:19s
    2008/03/10 09:53:33:建立部門考勤索引成功,日期:2008/02/01--2008/02/295、我說的是我自己的理解,我只是提出並實現了一個可行的方案,而且在維護中不停地豐富它完善它,但並不是我這個方案就是最好的,該方案只供參考。具體的對象及其接口,該由你自己去理解去設計,才能設計出更好的軟件。注意是做軟件設計而不是做代碼工人,中國更多的是軟件項目全包,設計與代碼由個人全包了。
      

  25.   

    同意这位仁兄的话!引用,哈,开发的流程应该可以再根据具体的工作验证流程.
    什么叫越详细越好,如果真的是详细,那么文档厚厚一大叠 逐渐回答问题 1、加班一般分为固定加班和自由加班 
       固定加班类似于普通上下班,其中具体可以分为4种: 
       A、固定时间,就是和普通上下班一样,有迟到早退问题 
       B、超时计加班,譬如12:00下班,如果到了12:30可以算加班半小时 
       C、早到计加班,类似上面 
       D、连班,譬如中午8:00-12:00/14:00-18:00,那么12:00-14:00之间可能会计算加班,当然要控制扣除中间吃饭时间    自由加班简单就是在某个时间段内,何时来都可以计算加班 
       譬如18:00-23:00算加班时间,如果是19:00-21:00,那么算加班2小时    其中自由加班的算法又可以分为8种,简单说几种 
       1、按指定时间取整计算,譬如8:08开始加班,可以自由设置为8:08/8:15/8:30 
       2、按照次数计算,譬如指定时间段内只能有2次 
       3、超时转页计算 
       4、先计算后取整 
       ...... 2、如果是自由加班那就是小儿科的问题了,按照次序一进一出就完了,依次算多次上下班 
       如果是正常上下班就罗嗦之极 
       譬如如果 9:00-10:00请假一小时,那么应该要刷卡4次,否则肯定是旷工 
       如果时间乱,那么可能有很多废卡,直接标记为废卡不参与计算即可 
       如果...... 3、考勤异常,那可就多了,迟到、早退、旷工、空卡、签卡、多刷卡......要考虑这么多啊 
    如果真的完全通用,一个好的考勤计算软件大约需要4000-8000行左右的存储过程进行计算,这可是一个相当庞大的工程 
      

  26.   

    今天試圖改進一下考勤遞交的SQL語句,使用CSV文件作中轉,加快了數據遞交速度,這需要客戶端與服務端能共享文件,就沒有使用Insert into語句那麼通用了。
    下面貼出實際計算提示:(共用18s,原來用26s,速度提升了 (26-18)/26 = 30%) 
    2008/03/19 12:11:47:計算考勤,開始從服務器取得數據
    2008/03/19 12:11:48:開始計算,人數:1129
    2008/03/19 12:11:49:計算完成,准備提交數據
    2008/03/19 12:11:50:刪除舊考勤結果成功,日期:2008/02/01--2008/02/29
    2008/03/19 12:11:51:開始輸出考勤結果         //這裡將CSV文件(3W多行約8M)傳送到服務端:文件傳輸過程速度不穩定,有時很慢,4s是正常速度。
    2008/03/19 12:11:55:開始將結果導入數據庫     //用SQL Server 的BULT INSERT 導入文件。
    2008/03/19 12:12:04:輸出考勤結果成功,耗時:13s //原來用19s,單項速度提升為: (19-13)/19 = 31%
    2008/03/19 12:12:05:建立部門考勤索引成功,日期:2008/02/01--2008/02/29 
    //部門考勤索引表就是部門每天出勤表,因為要考慮員工歷史異動記錄,而且使用頻繁,所以事先建立一份。這個是用貯存過程實現的,有時花費時間超過5s(SQL Server 有時會很忙),如果數據量大,應該用本地計算要比用貯存過程計算速度快且穩定。//
    測試時發現網絡文件傳輸過程速度不穩定,有時很慢,如果應用程序服務器與SQLServer是同一台電腦速度就很快。使用Insert into語句遞交結果速度穩定,不會有寫遠程文件那樣時快時慢的情況。所以最終的解決結果是:使用ini文件配置,讓最終用戶可以依據員工的數量及服務器配置來選擇適當的傳輸方式以得到更快的速度。
    //
    原以為 insert into XXX() select a,b,c union select d,e,f 這種方式比 insert into XXX() Values()快,但是實測結果令人大跌眼鏡,速度不是相差一點點, insert into XXX() Values()的方式快太多了。以上是在 SQL Server 2000 SP4 上作的測試,不同的數據庫、不同的服務器有不同的結果,請自行判斷該用哪種方式,允許用戶選擇不同的計算方法
    考勤煩,至少還有道理可說;生產管理更煩,規章制度是可以隨意改變的,要整理個模式出來真煩。
      

  27.   

    TO ppower:
    你的速度确实够快的。我测试的12人,一个月。排班就花了3分钟左右。发现速度主要卡在向数据库服务器频繁的取信息上面。现在正在最后一步的分析考勤结果上面,等做完了再认真弄弄速度的问题。
      

  28.   

    5:请做过考勤分析的兄弟给点比较健全的思路 ——建议还是请一个强一点的项目经理来设计吧,想免费从别人那里得到一整套有价值的东西,有点异想天开了
    ------------------------------------------------------------------------------------------
    兄弟,此言差矣!上MSDN讨论学习与交流,不收费的.
      

  29.   

    你言更差,你连这个网站叫什么名字都说错了,是csdn,不是msdn好不好。
    这个世界就是这么现实,这里是免费讨论技术问题没错,但是如果是别人辛辛苦苦设计出来的拿来赚钱的家伙,人家凭什么跟你分享?
    “健全”的思路?唉……
      

  30.   

    班次和时间段都需要循环.
    上班时间段内如果有多条打卡记录的.取得后一条;下班时间段有打卡记录的,取早一条;
    迟到与早退;将打卡时间减去上班时间点与下班时间点,如果不在迟到/早退规定的时间范围内,分别判断.再合计早退,迟到的时间,如果在旷工时间值外,就计旷工;
    如果在班次中有多条打卡记录的,需要判断该打卡记录是否落在出差,请假,国家假日,公司自定义日历之类./////////////////////////////////////////////////////////////////////////////////////////////////
    "你言更差,你连这个网站叫什么名字都说错了,是csdn,不是msdn好不好。 
    这个世界就是这么现实,这里是免费讨论技术问题没错,但是如果是别人辛辛苦苦设计出来的拿来赚钱的家伙,人家凭什么跟你分享? 
    “健全”的思路?唉……"
    ---------------------------------------------------------------------------------------------------
    这话说的有点过了!分不分享是个人的自由.来这里讨论本身就是一个分享与被分享的过程.哈哈~!口下留情,不要骂我.
      

  31.   

    同意这位仁兄的话!开发的流程应该可以再根据具体的工作验证流程. 1、加班一般分为固定加班和自由加班  
       固定加班类似于普通上下班,其中具体可以分为4种:  
       A、固定时间,就是和普通上下班一样,有迟到早退问题  
       B、超时计加班,譬如12:00下班,如果到了12:30可以算加班半小时  
       C、早到计加班,类似上面  
       D、连班,譬如中午8:00-12:00/14:00-18:00,那么12:00-14:00之间可能会计算加班,当然要控制扣除中间吃饭时间     自由加班简单就是在某个时间段内,何时来都可以计算加班  
       譬如18:00-23:00算加班时间,如果是19:00-21:00,那么算加班2小时     其中自由加班的算法又可以分为8种,简单说几种  
       1、按指定时间取整计算,譬如8:08开始加班,可以自由设置为8:08/8:15/8:30  
       2、按照次数计算,譬如指定时间段内只能有2次  
        3、先计算后取整  
      我一般就是想到这个地步.做到这个地步了.