UserAttendanceDetailQueryServiceImpl.java 139 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382
  1. package cn.com.lzt.userattendancedetail.service.impl;
  2. import java.math.BigDecimal;
  3. import java.text.SimpleDateFormat;
  4. import java.util.ArrayList;
  5. import java.util.Calendar;
  6. import java.util.Collections;
  7. import java.util.Date;
  8. import java.util.HashMap;
  9. import java.util.List;
  10. import org.jeecgframework.core.common.hibernate.qbc.CriteriaQuery;
  11. import org.jeecgframework.core.common.service.impl.CommonServiceImpl;
  12. import org.jeecgframework.core.constant.Globals;
  13. import org.jeecgframework.core.util.DataUtils;
  14. import org.jeecgframework.core.util.ListUtils;
  15. import org.jeecgframework.core.util.oConvertUtils;
  16. import org.jeecgframework.tag.vo.datatable.SortDirection;
  17. import org.jeecgframework.web.system.pojo.base.TSDepart;
  18. import org.jeecgframework.workflow.common.WorkFlowGlobals;
  19. import org.springframework.beans.factory.annotation.Autowired;
  20. import org.springframework.stereotype.Service;
  21. import com.alibaba.fastjson.JSONObject;
  22. import cn.com.lzt.attendance.entity.TBusSpecialAttendEntity;
  23. import cn.com.lzt.attendance.service.TBusSpecialAttendServiceI;
  24. import cn.com.lzt.calendar.entity.CalendarEntity;
  25. import cn.com.lzt.calendar.service.CalendarServiceI;
  26. import cn.com.lzt.dingattendanceinfo.entity.DingAttendanceinfoEntity;
  27. import cn.com.lzt.dingattendanceinfo.service.DingAttendanceinfoServiceI;
  28. import cn.com.lzt.holiday.entity.HolidayEntity;
  29. import cn.com.lzt.holiday.service.HolidayServiceI;
  30. import cn.com.lzt.mealsdeduct.entity.MealsDeductEntity;
  31. import cn.com.lzt.mealssubsidy.entity.MealsSubsidyEntity;
  32. import cn.com.lzt.overtimerecord.entity.OvertimeRecordEntity;
  33. import cn.com.lzt.overtimerecord.service.OvertimeRecordServiceI;
  34. import cn.com.lzt.projarrangedetail.entity.ProjarrangeDetailEntity;
  35. import cn.com.lzt.snapregularborrow.entity.SnapRegularborrowEntity;
  36. import cn.com.lzt.snapregularborrow.service.SnapRegularborrowServiceI;
  37. import cn.com.lzt.snapsingleborrow.entity.SnapSingleborrowEntity;
  38. import cn.com.lzt.snapsingleborrow.service.SnapSingleborrowServiceI;
  39. import cn.com.lzt.userattendancedetail.dao.UserAttendanceDetailDao;
  40. import cn.com.lzt.userattendancedetail.dto.AttendanceDetailJsonObj;
  41. import cn.com.lzt.userattendancedetail.dto.AttendanceTotalJsonObj;
  42. import cn.com.lzt.userattendancedetail.dto.UserAttendanceDetailDto;
  43. import cn.com.lzt.userattendancedetail.entity.UserAttendanceDetailAdjustedEntity;
  44. import cn.com.lzt.userattendancedetail.entity.UserAttendanceDetailEntity;
  45. import cn.com.lzt.userattendancedetail.service.UserAttendanceDetailQueryServiceI;
  46. import cn.com.lzt.userattendancetotal.entity.UserAttendanceTotalEntity;
  47. import cn.com.lzt.userwagestrategy.entity.UserWagestrategyEntity;
  48. import cn.com.lzt.userwagestrategy.service.UserWagestrategyServiceI;
  49. @Service("userAttendanceDetailQueryService")
  50. public class UserAttendanceDetailQueryServiceImpl extends CommonServiceImpl
  51. implements UserAttendanceDetailQueryServiceI {
  52. @Autowired
  53. private UserAttendanceDetailDao userAttendanceDetailDao;
  54. // 员工工资策略表
  55. @Autowired
  56. private UserWagestrategyServiceI userWagestrategyService;
  57. // 休假申请表
  58. @Autowired
  59. private HolidayServiceI holidayService;
  60. // 加班备案表
  61. @Autowired
  62. private OvertimeRecordServiceI overtimeRecordService;
  63. // 临时借调(单次)申请表
  64. @Autowired
  65. private SnapSingleborrowServiceI snapSingleborrowService;
  66. // 临时固定周期申请表
  67. @Autowired
  68. private SnapRegularborrowServiceI snapRegularborrowService;
  69. // 钉钉考勤原始信息表
  70. @Autowired
  71. private DingAttendanceinfoServiceI dingAttendanceinfoService;
  72. @Autowired
  73. private CalendarServiceI calendarService;
  74. @Autowired
  75. private TBusSpecialAttendServiceI specialAttendService;
  76. /**
  77. * 通过月度考勤计算更新月度每日的考勤信息
  78. * @author hualong.zhao
  79. * @date 2017-11-30
  80. * @param userAttendanceTotalEntity
  81. * @param hm_cache
  82. * @throws Exception
  83. */
  84. private void updateDetailinfoBytotalEntity(
  85. UserAttendanceTotalEntity userAttendanceTotalEntity, HashMap<String, HashMap<String, Object>> hm_cache) throws Exception {
  86. List<UserAttendanceDetailDto> uatdlist = null;
  87. if(hm_cache == null) {
  88. uatdlist = getallUsefulField(userAttendanceTotalEntity, null, null);
  89. }else {
  90. uatdlist = getallUsefulFieldWithCache(hm_cache,userAttendanceTotalEntity);
  91. }
  92. List<UserAttendanceDetailEntity> detailEntities = new ArrayList<>();
  93. for (UserAttendanceDetailDto dto : uatdlist) {
  94. //
  95. // if("ff808081657e96b10165848ae5d61df2".equals(dto.getUserid())) {
  96. // System.out.println("张义华日夜");
  97. // }else {
  98. // continue;
  99. // }
  100. UserAttendanceDetailEntity userAttendanceDetailEntity = new UserAttendanceDetailEntity();
  101. //时间微调 默认为零
  102. userAttendanceDetailEntity.setTimeFineTuning(BigDecimal.ZERO);
  103. //设置当前时间
  104. userAttendanceDetailEntity.setYmdDate(dto.getYmdDate());
  105. // 设置考勤id; ok
  106. userAttendanceDetailEntity.setAttendanceId(dto.getAttendanceId());
  107. // 设置实际出勤时间
  108. userAttendanceDetailEntity.setAttendanceDate(dto.getActattendanceDate());
  109. // 设置实际退勤时间
  110. if (oConvertUtils.isNotEmpty(dto.getActattendanceDate())&&
  111. oConvertUtils.isNotEmpty(dto.getActretreatDate())&&
  112. dto.getActattendanceDate().equals(dto.getActretreatDate())) {
  113. userAttendanceDetailEntity.setRetreatDate(null);
  114. }else {
  115. userAttendanceDetailEntity.setRetreatDate(dto.getActretreatDate());
  116. }
  117. // 设置班次id 如果排班类型为休息 则此处不存储班次id
  118. if (Globals.DUTYTYPE_xiuxi.equals(oConvertUtils.getString(dto.getDutyType()))) {
  119. userAttendanceDetailEntity.setDutyId(null);
  120. }else {
  121. userAttendanceDetailEntity.setDutyId(dto.getShiftid());
  122. }
  123. // 设置基准时间
  124. userAttendanceDetailEntity.setDatumDate(dto.getDatumDate());
  125. // 設置时间差值
  126. if (null==dto.getTimeDifference()) {
  127. userAttendanceDetailEntity.setTimeDifference(BigDecimal.ZERO);
  128. }else {
  129. userAttendanceDetailEntity.setTimeDifference(dto.getTimeDifference());
  130. }
  131. //设置超时加班时长
  132. userAttendanceDetailEntity.setTimeoutOvertimeDuration(dto.getTimeoutOvertimeDuration());
  133. //设置 国定加班时长
  134. userAttendanceDetailEntity.setNationalOvertimeDuration(dto.getNationalOvertimeDuration());
  135. //设置 特殊加班时长
  136. userAttendanceDetailEntity.setSpecialOvertime(dto.getSpecialOvertime());
  137. // 获取当前状态
  138. userAttendanceDetailEntity.setStatus(dto.getCurdateStatus());
  139. // 获取借调信息-==start
  140. userAttendanceDetailEntity.setBorrowstatus(dto.getBorrowstatus());
  141. userAttendanceDetailEntity.setBorrowspid(dto.getBorrowspid());
  142. userAttendanceDetailEntity.setBorrowsdepartid(dto.getBorrowsdepartid());
  143. userAttendanceDetailEntity.setDayPay(dto.getDayPay());
  144. // 获取借调信息-==end
  145. // 设置实际出勤时间
  146. if (null==dto.getActualAttendanceDate()) {
  147. userAttendanceDetailEntity.setAttendanceMins(BigDecimal.ZERO);
  148. userAttendanceDetailEntity.setActualAttendanceDate(BigDecimal.ZERO);
  149. }else{
  150. userAttendanceDetailEntity.setAttendanceMins(dto.getActualAttendanceDate());
  151. userAttendanceDetailEntity.setActualAttendanceDate(dto.getActualAttendanceDate());
  152. }
  153. AttendanceDetailJsonObj jsonobj = getjsonObjfromDto(dto);
  154. if(hm_cache != null) {
  155. // 单个考勤核算不覆盖调整记录
  156. // 恢复调整记录, 主要是针对重复生成考勤的调整记录被覆盖的问题
  157. List<UserAttendanceDetailAdjustedEntity> adjustedEntities = getAdjustedAttendEntitiesWithCache(hm_cache, dto);
  158. UserAttendanceDetailAdjustedEntity currDateAdjustEntity = getCurrDateAdjustEntity(adjustedEntities, dto);
  159. if(currDateAdjustEntity != null) {
  160. userAttendanceDetailEntity.setStatus(currDateAdjustEntity.getStatus());
  161. userAttendanceDetailEntity.setFineTuningType(currDateAdjustEntity.getFineTuningType());
  162. userAttendanceDetailEntity.setAdjustReason(currDateAdjustEntity.getAdjustReason());
  163. userAttendanceDetailEntity.setTimeFineTuning(currDateAdjustEntity.getTimeFineTuning());
  164. jsonobj.setPrimevalAttendanceDate(dto.getPrimevalAttendanceDate());
  165. jsonobj.setPrimevalRetreatDate(dto.getPrimevalRetreatDate());
  166. jsonobj.setAdjustRecord(1);
  167. userAttendanceTotalEntity.setAdjustRecord("1");
  168. }
  169. }
  170. //设置其他参数
  171. userAttendanceDetailEntity.setJsonObj(JSONObject.toJSONString(jsonobj));
  172. saveOrUpdate(userAttendanceDetailEntity);
  173. detailEntities.add(userAttendanceDetailEntity);
  174. }
  175. //设置固定固定餐费补贴
  176. /**固定餐费补贴*/
  177. UserWagestrategyEntity userWagestrategy = userWagestrategyService.getUserWagestrategyEntityByUserId(userAttendanceTotalEntity.getUserId());
  178. Integer fixedValue = null;
  179. if (null!=userWagestrategy) {
  180. /**餐补类型*/
  181. String strategyType=oConvertUtils.getString(userWagestrategy.getStrategyType());
  182. if (strategyType.equals("0")) {
  183. // 0按固定餐补;1按班次餐补
  184. String temp = userWagestrategy.getNofixedmealsSubsidyid();
  185. try {
  186. fixedValue = Integer.valueOf(oConvertUtils.getString(temp));
  187. } catch (Exception e) {
  188. }
  189. }
  190. }
  191. if (null==fixedValue) {
  192. fixedValue = 0;
  193. }
  194. userAttendanceTotalEntity.setFixedValue(fixedValue);
  195. //更新月度汇总信息
  196. updateMonthlyInfo(userAttendanceTotalEntity,detailEntities);
  197. }
  198. /**
  199. * @param adjustedEntities
  200. * @param dto
  201. * @return
  202. */
  203. private UserAttendanceDetailAdjustedEntity getCurrDateAdjustEntity(
  204. List<UserAttendanceDetailAdjustedEntity> adjustedEntities, UserAttendanceDetailDto dto) {
  205. if(adjustedEntities != null && adjustedEntities.size()>0 && dto != null) {
  206. for(UserAttendanceDetailAdjustedEntity ae : adjustedEntities) {
  207. if(dto.getYmdDate().compareTo(ae.getYmdDate()) == 0) {
  208. return ae;
  209. }
  210. }
  211. }
  212. return null;
  213. }
  214. //将dto 中的其他字段信息 转化成jsonString 用于数据库保存
  215. private AttendanceDetailJsonObj getjsonObjfromDto(UserAttendanceDetailDto dto) {
  216. AttendanceDetailJsonObj jsonobj = new AttendanceDetailJsonObj();
  217. jsonobj.setNoPunchCard(0);
  218. jsonobj.setAdjustRecord(0);
  219. jsonobj.setMoneyLeave(false);
  220. jsonobj.setWorktype(dto.getDtype());
  221. BigDecimal actDatumDate = dto.getDatumDate();
  222. if (null==actDatumDate) {
  223. actDatumDate = BigDecimal.ZERO;
  224. }
  225. //设置 早退 状态
  226. jsonobj.setLeaveEarly(dto.isLeaveEarly());
  227. //设置 迟到 状态
  228. jsonobj.setBelate(dto.isBelate());
  229. //设置 旷工 状态
  230. jsonobj.setAbsenteeism(dto.getAbsenteeism());
  231. //设置事假请假的分钟数
  232. jsonobj.setThingLeaveMins(dto.getThingLeaveMins());
  233. //设置病假请假的分钟数
  234. jsonobj.setSickLeaveMins(dto.getSickLeaveMins());
  235. //设置这一天加过班
  236. jsonobj.setIhadDuty(dto.isIhadDuty());
  237. //设置这一天未打卡
  238. if (oConvertUtils.isNotEmpty(dto.getActattendanceDate())&&
  239. oConvertUtils.isNotEmpty(dto.getActretreatDate())&&
  240. dto.getActattendanceDate().equals(dto.getActretreatDate())) {
  241. //如果上班时间和下班时间相等 则认定为 一次漏打卡
  242. if (Globals.DUTYTYPE_xiuxi.equals(oConvertUtils.getString(dto.getDutyType()))) {
  243. //休息的时候 不记录漏打卡
  244. jsonobj.setNoPunchCard(0);
  245. }else {
  246. jsonobj.setNoPunchCard(1);
  247. }
  248. }
  249. jsonobj.setExtraOvertime(dto.getExtraOvertime());
  250. //如果既没有开始时间 也没有结束时间 切 当前状态为正常的时候记录 漏打卡两次
  251. if (oConvertUtils.isEmpty(dto.getActattendanceDate())&&
  252. oConvertUtils.isEmpty(dto.getActretreatDate()) ) {
  253. if (Globals.DUTYTYPE_xiuxi.equals(oConvertUtils.getString(dto.getDutyType()))) {
  254. //休息的时候 不记录漏打卡
  255. jsonobj.setNoPunchCard(0);
  256. }else {
  257. //正常的需要工作的时候
  258. // 判断当天有没有长假期
  259. Boolean longHoliday = dto.getLongHoliday();
  260. //没有请长假 切当天没有打卡记录 则记录两次漏打卡
  261. if (!longHoliday) {
  262. // 如果当天请了事假或者是病假,不记录未打卡 事假和病假 也按照480计算
  263. if ((!dto.getSickLeaveMins().equals(BigDecimal.ZERO))||
  264. (!dto.getThingLeaveMins().equals(BigDecimal.ZERO)) ) {
  265. actDatumDate = new BigDecimal(480);
  266. jsonobj.setNoPunchCard(0);
  267. }else {
  268. //当该员工在没有情况在前提下 没有打卡记录的时候, 实际出勤时间记作480分,避免超时加班时长)
  269. actDatumDate = new BigDecimal(480);
  270. jsonobj.setMoneyLeave(true);
  271. jsonobj.setNoPunchCard(2);
  272. }
  273. }
  274. }
  275. }
  276. //如果这一天又带薪假 将工作状态记录为已请假
  277. Boolean longHoliday = dto.getLongHoliday();
  278. if (longHoliday) {
  279. actDatumDate = new BigDecimal(480);
  280. }
  281. jsonobj.setActDatumDate(actDatumDate );
  282. jsonobj.setDayShiftSubsidy(dto.getDayShiftSubsidy());
  283. jsonobj.setNightShiftSubsidy(dto.getNightShiftSubsidy());
  284. jsonobj.setDayShift(dto.getDayShift());
  285. jsonobj.setRegularShift(dto.getRegularShift());
  286. jsonobj.setDayShiftId(dto.getDayShiftId());
  287. jsonobj.setNightShiftSubsidyId(dto.getNightShiftSubsidyId());
  288. jsonobj.setDayShiftSubsidyId(dto.getDayShiftSubsidyId());
  289. jsonobj.setRegularShiftId(dto.getRegularShiftId());
  290. return jsonobj;
  291. }
  292. //更新月度请假信息
  293. private void updateMonthlyInfo(
  294. UserAttendanceTotalEntity userAttendanceTotalEntity,List<UserAttendanceDetailEntity> detailEntities) throws Exception {
  295. /**调整时间*/
  296. BigDecimal adjustTime = BigDecimal.ZERO;
  297. /**总时间差*/
  298. BigDecimal timeDifferenceTotal= BigDecimal.ZERO;
  299. /**总加班时间*/
  300. BigDecimal overtimeTotalTime= BigDecimal.ZERO;
  301. /**超时加班时长*/
  302. BigDecimal timeoutOvertimeDuration= BigDecimal.ZERO;
  303. /**国定加班时长*/
  304. BigDecimal nationalOvertimeDuration= BigDecimal.ZERO;
  305. /**特殊加班费*/
  306. BigDecimal specialOvertime= BigDecimal.ZERO;
  307. /**夜班白班津贴*/
  308. Integer dayShiftSubsidy= 0;
  309. /**夜班夜班津贴*/
  310. Integer nightShiftSubsidy= 0;
  311. /**日班*/
  312. Integer dayShift= 0;
  313. /**常班*/
  314. Integer regularShift= 0;
  315. /**额外加班*/
  316. Integer extraOvertime= 0;
  317. /**基准出勤时间*/
  318. BigDecimal datumAttendanceDate = BigDecimal.ZERO;
  319. /**实际出勤时间*/
  320. BigDecimal actualAttendanceDate= BigDecimal.ZERO;
  321. /** 早退次数 */
  322. Integer earlyLeaveAmount = 0;
  323. /** 迟到次数 */
  324. Integer lateAmount = 0;
  325. /** 旷工次数 */
  326. BigDecimal absenteeismAmount = BigDecimal.ZERO;
  327. /** 未打卡次 */
  328. Integer noPunchCardAmount = 0;
  329. /** 带薪假 */
  330. BigDecimal paidLeave = BigDecimal.ZERO;
  331. /** 事假 */
  332. BigDecimal thingLeave = BigDecimal.ZERO;
  333. /** 病假 */
  334. BigDecimal sickLeave = BigDecimal.ZERO;
  335. /** 病假分钟数 */
  336. BigDecimal sickLeavetotalmins = BigDecimal.ZERO;
  337. /** 婚假 */
  338. BigDecimal marriageLeave = BigDecimal.ZERO;
  339. /** 丧假 */
  340. BigDecimal funeralLeave = BigDecimal.ZERO;
  341. /** 产假 */
  342. BigDecimal maternityLeave = BigDecimal.ZERO;
  343. /** 陪产假 */
  344. BigDecimal accompanyMaternityLeave = BigDecimal.ZERO;
  345. /**请假总时间*/
  346. BigDecimal leaveTotalTime= BigDecimal.ZERO;
  347. /**普通值班时长*/
  348. BigDecimal dutyDuration = BigDecimal.ZERO;
  349. /**国定值班天数*/
  350. BigDecimal nationalDutyDuration = BigDecimal.ZERO;
  351. /**
  352. * 月度基准时间合计
  353. */
  354. BigDecimal monthlyActDatumsum = BigDecimal.ZERO;;
  355. /**
  356. * 国定假日排班时长
  357. */
  358. BigDecimal monthlyLegalholidaysum = BigDecimal.ZERO;;
  359. /**
  360. * 月度法定工时天数
  361. */
  362. Integer monthlyLegalworktime = 0;
  363. /**
  364. * 是否单次临时调动过 0没有调动过;1调动过
  365. */
  366. String ifmoved = Globals.SHIFOU_01_0;
  367. /**夜班白班津贴主键*/
  368. String dayShiftSubsidyId = "";
  369. /**夜班夜班津贴主键*/
  370. String nightShiftSubsidyId= "";
  371. /**日班津贴主键*/
  372. String dayShiftId= "";
  373. /**常班津贴主键*/
  374. String regularShiftId= "";
  375. //缓存出勤日期和出勤实体,用于解决请病假却出勤的病假扣除问题
  376. HashMap<String, UserAttendanceDetailEntity> hm_Date2AttendanceDetail = new HashMap<String, UserAttendanceDetailEntity>();
  377. for (UserAttendanceDetailEntity entity:detailEntities) {
  378. //读取其他字段信息, 变转化成实体类 对其进行相关逻辑判断
  379. AttendanceDetailJsonObj jsonObj = getJsonObjFromString(oConvertUtils
  380. .getString(entity.getJsonObj()));
  381. if (jsonObj.getIhadDuty()) {
  382. // 把国定值班从值班天数中分离出去 zy 20180416
  383. if(jsonObj.getWorktype().equals(Globals.dtype_2)) {
  384. //国定值班
  385. nationalDutyDuration = nationalDutyDuration.add(BigDecimal.ONE);
  386. }else {
  387. //非国定普通加班
  388. //如果这一天加班了 月度加班总和+1
  389. dutyDuration = dutyDuration.add(BigDecimal.ONE);
  390. }
  391. }
  392. hm_Date2AttendanceDetail.put(DataUtils.date2Str(entity.getYmdDate(), DataUtils.date_sdf), entity);
  393. //查看当天是否有迟到
  394. if (jsonObj.getBelate()) {
  395. lateAmount = lateAmount +1 ;
  396. }
  397. //查看当天是否有早退
  398. if (jsonObj.getLeaveEarly()) {
  399. earlyLeaveAmount = earlyLeaveAmount +1 ;
  400. }
  401. //查看当天是否有旷工
  402. if (null!=jsonObj.getAbsenteeism() && !jsonObj.getWorktype().equals(Globals.dtype_2)) {
  403. absenteeismAmount = absenteeismAmount.add(jsonObj.getAbsenteeism());
  404. }
  405. //查看月度基准时间
  406. if (null!=jsonObj.getActDatumDate() /*&& !jsonObj.getWorktype().equals(Globals.dtype_2)*/) {
  407. monthlyActDatumsum = monthlyActDatumsum.add(jsonObj.getActDatumDate());
  408. }
  409. //查看 月度额外加班
  410. if (null!=jsonObj.getExtraOvertime()) {
  411. extraOvertime = extraOvertime+jsonObj.getExtraOvertime();
  412. }
  413. String worktype = jsonObj.getWorktype();
  414. //查看月度国定假日时长
  415. if (null!=worktype) {
  416. if (worktype.equals(Globals.dtype_2)) {
  417. //国定休日
  418. monthlyLegalholidaysum = monthlyLegalholidaysum.add(jsonObj.getActDatumDate());
  419. }
  420. if (worktype.equals(Globals.dtype_0)) {
  421. //工作日
  422. monthlyLegalworktime++;
  423. }
  424. }
  425. //查看 夜班白班津贴
  426. if (null!=jsonObj.getDayShiftSubsidy()) {
  427. dayShiftSubsidy = dayShiftSubsidy+jsonObj.getDayShiftSubsidy();
  428. }
  429. //查看夜班夜班津贴
  430. if (null!=jsonObj.getNightShiftSubsidy()) {
  431. nightShiftSubsidy = nightShiftSubsidy+jsonObj.getNightShiftSubsidy();
  432. }
  433. //查看日班
  434. if (null!=jsonObj.getDayShift()) {
  435. dayShift = dayShift+jsonObj.getDayShift();
  436. }
  437. //查看 常班
  438. if (null!=jsonObj.getRegularShift()) {
  439. regularShift = regularShift+jsonObj.getRegularShift();
  440. }
  441. if(isPayLeave(entity)) {
  442. //年假等带薪假+8小时
  443. datumAttendanceDate = datumAttendanceDate.add(new BigDecimal(8*60));
  444. }else if (null!=entity.getDatumDate()) {
  445. // add by zy 20180413
  446. // 刨除国定假
  447. // 在计算应出勤时间是已经处理过国定时间 -zy 20180513
  448. if(null!=worktype /*&& !worktype.equals(Globals.dtype_2)*/) {
  449. datumAttendanceDate = datumAttendanceDate.add(entity.getDatumDate());
  450. }
  451. }
  452. //查看员工的 实际出勤时间
  453. if(isPayLeave(entity)) {
  454. //年假等带薪假+8小时
  455. actualAttendanceDate = actualAttendanceDate.add(new BigDecimal(8*60));
  456. }else if (null!=entity.getActualAttendanceDate()) {
  457. // add by zy 20180413
  458. // 刨除国定假
  459. // 直接减掉国定加班时长
  460. if(null!=worktype /*&& !worktype.equals(Globals.dtype_2))*/) {
  461. actualAttendanceDate = actualAttendanceDate.add(entity.getActualAttendanceDate());
  462. if(entity.getNationalOvertimeDuration() != null && entity.getNationalOvertimeDuration().compareTo(BigDecimal.ZERO)>0) {
  463. actualAttendanceDate =actualAttendanceDate.subtract(entity.getNationalOvertimeDuration());
  464. }
  465. }
  466. }
  467. //查看员工的 国定加班时长
  468. if (null!=entity.getNationalOvertimeDuration()) {
  469. nationalOvertimeDuration = nationalOvertimeDuration.add(entity.getNationalOvertimeDuration());
  470. }
  471. //查看员工的 临时借调状态
  472. if (null!=entity.getBorrowstatus()&&"1".equals(entity.getBorrowstatus())) {
  473. ifmoved =Globals.SHIFOU_01_1;
  474. }
  475. //查看员工的 时间差值
  476. if (null!=entity.getTimeDifference()) {
  477. timeDifferenceTotal = timeDifferenceTotal.add(entity.getTimeDifference());
  478. }
  479. //查看员工的 特殊加班费
  480. if (null!=entity.getSpecialOvertime()) {
  481. specialOvertime = specialOvertime.add(entity.getSpecialOvertime());
  482. }
  483. //查看员工的 时间微调
  484. if (null!=entity.getTimeFineTuning()) {
  485. adjustTime = adjustTime.add(entity.getTimeFineTuning());
  486. }
  487. //查看当天是否有未打卡
  488. if (null!=jsonObj.getNoPunchCard()) {
  489. noPunchCardAmount = noPunchCardAmount +jsonObj.getNoPunchCard() ;
  490. }
  491. /*//这一天状态是事假 事假统计分钟数
  492. if (entity.getStatus().equals(Globals.ATTENDANCE_STATUS_EDIT_0)) {
  493. BigDecimal thingLeaveMins =jsonObj.getThingLeaveMins();
  494. if (null==thingLeaveMins) {
  495. thingLeaveMins = BigDecimal.ZERO;
  496. }
  497. thingLeave = thingLeave.add(thingLeaveMins);
  498. }*/
  499. //这一天状态是病假 月度病假数+1
  500. if (entity.getStatus().equals(Globals.ATTENDANCE_STATUS_EDIT_1)) {
  501. /*BigDecimal sickLeaveMins =jsonObj.getSickLeaveMins();
  502. if (null==sickLeaveMins) {
  503. sickLeaveMins = BigDecimal.ZERO;
  504. }*/
  505. sickLeave = sickLeave.add( BigDecimal.ONE);
  506. //sickLeavetotalmins = sickLeavetotalmins.add(sickLeaveMins);
  507. }
  508. //这一天状态是年假? 年假就是带薪假
  509. if (entity.getStatus().equals(Globals.ATTENDANCE_STATUS_EDIT_2)) {
  510. paidLeave = paidLeave.add(BigDecimal.ONE);
  511. }
  512. //这一天状态是丧假 月度丧假数+1
  513. if (entity.getStatus().equals(Globals.ATTENDANCE_STATUS_EDIT_3)) {
  514. funeralLeave = funeralLeave.add(BigDecimal.ONE);
  515. }
  516. //这一天状态是婚假 月度婚假数+1
  517. if (entity.getStatus().equals(Globals.ATTENDANCE_STATUS_EDIT_4)) {
  518. marriageLeave = marriageLeave.add(BigDecimal.ONE);
  519. }
  520. //这一天状态是产假 月度产假数+1
  521. if (entity.getStatus().equals(Globals.ATTENDANCE_STATUS_EDIT_5)) {
  522. maternityLeave = maternityLeave.add(BigDecimal.ONE);
  523. }
  524. //这一天状态是陪产假 月度陪产假数+1
  525. if (entity.getStatus().equals(Globals.ATTENDANCE_STATUS_EDIT_6)) {
  526. accompanyMaternityLeave = accompanyMaternityLeave.add(BigDecimal.ONE);
  527. }
  528. //这一天状态是法定假日 法定假日也归属于带薪假
  529. if (entity.getStatus().equals(Globals.ATTENDANCE_STATUS_EDIT_11)) {
  530. paidLeave = paidLeave.add(BigDecimal.ONE);
  531. }
  532. }
  533. // =====查询请假情况
  534. String yearmonth=userAttendanceTotalEntity.getYearmonth();
  535. String userid = userAttendanceTotalEntity.getUserId();
  536. String ymdDate = yearmonth+"-01";
  537. Calendar calendar = Calendar.getInstance();
  538. Date endDate = DataUtils.str2Date(ymdDate, DataUtils.date_sdf);
  539. calendar.setTime(endDate);
  540. calendar.add(Calendar.DATE, -1);
  541. // 上个月的最后一天
  542. String lastmonthlatestday = DataUtils.date2Str(endDate, DataUtils.date_sdf);
  543. calendar.add(Calendar.DATE, 1);
  544. //这个月的第一天
  545. String monthfirstday = DataUtils.date2Str(endDate, DataUtils.date_sdf);
  546. calendar.add(Calendar.MONTH, 1);
  547. endDate = calendar.getTime();
  548. //下个月的第一天
  549. String nextmonthfirstday = DataUtils.date2Str(endDate, DataUtils.date_sdf);
  550. calendar.add(Calendar.DATE, -1);
  551. endDate = calendar.getTime();
  552. //这个月的最后一天
  553. String monthlatestday = DataUtils.date2Str(endDate, DataUtils.date_sdf);
  554. List<HolidayEntity> userHolidayEntities = holidayService
  555. .getUserHolidayEntities(userid, yearmonth);
  556. if (null==userHolidayEntities) {
  557. userHolidayEntities = new ArrayList<HolidayEntity>();
  558. }
  559. for (HolidayEntity holiday:userHolidayEntities) {
  560. String hilidaytype =oConvertUtils.getString( holiday.getHolidayType());
  561. BigDecimal holidayDuration= holiday.getHolidayDuration();
  562. Date holidayStime= holiday.getHolidayStime();
  563. Date holidayEtime= holiday.getHolidayEtime();
  564. //如果开始时间 和结束时间为空// 跳过
  565. if (null==holidayStime||null==holidayEtime) {
  566. continue;
  567. }
  568. //请假类型不是事假 也不是病假 跳过 不做处理
  569. if (!(Globals.REST_TYPE_1.equals(hilidaytype)|| Globals.REST_TYPE_0.equals(hilidaytype))) {
  570. continue;
  571. }
  572. String holidaySdate = DataUtils.date2Str(holidayStime, DataUtils.date_sdf);
  573. String holidayEdate = DataUtils.date2Str(holidayEtime, DataUtils.date_sdf);
  574. //如果结束日期晚于下月一号 跳过
  575. if (holidayEdate.compareTo(nextmonthfirstday)>0) {
  576. continue;
  577. }
  578. /* 此处处理逻辑混乱, 注释不知所云. 暂且去掉. 20180702 xzx
  579. // 如果请假开始日期 等于本月的一号 切请假结束日期也是本月的一号
  580. if (holidaySdate.equals(monthfirstday)&&holidayEdate.equals(monthfirstday)) {
  581. //判断上月的最后一天 是否为夜班
  582. List<UserAttendanceDetailDto> yestoryday = userAttendanceDetailDao.
  583. getlistbyProjarrangeDetailid(null,userid,lastmonthlatestday);
  584. if (!ListUtils.isNullOrEmpty(yestoryday)) {
  585. UserAttendanceDetailDto ydto = yestoryday.get(0);
  586. if (Globals.DUTYTYPE_yeban115.equals(oConvertUtils.getString(ydto.getDutyType()))) {
  587. //如果上月的最后一天是夜班, 则将该事假/病假 记录
  588. }else {
  589. //如果上月的最后一天不是夜班, 则将该事假/病假 记录
  590. continue;
  591. }
  592. }
  593. }
  594. // 如果请假开始日期 等于下个月的一号 切请假结束日期也是下个月的一号
  595. if (holidaySdate.equals(nextmonthfirstday)&&holidayEdate.equals(nextmonthfirstday)) {
  596. //判断本月的最后一天 是否为夜班
  597. List<UserAttendanceDetailDto> yestoryday = userAttendanceDetailDao.
  598. getlistbyProjarrangeDetailid(null,userid,monthlatestday);
  599. if (!ListUtils.isNullOrEmpty(yestoryday)) {
  600. UserAttendanceDetailDto ydto = yestoryday.get(0);
  601. if (Globals.DUTYTYPE_yeban115.equals(oConvertUtils.getString(ydto.getDutyType()))) {
  602. //如果本月的最后一天是夜班, 则将该事假/病假 记录
  603. }else {
  604. //如果本月的最后一天不是夜班, 则将该事假/病假 记录
  605. continue;
  606. }
  607. }
  608. }
  609. */
  610. //对 每天请假时长 非空处理
  611. if (oConvertUtils.isEmpty(holidayDuration)) {
  612. holidayDuration = BigDecimal.ZERO;
  613. }
  614. //对 每天请假时长 进行单位转换: 小时--> 分钟
  615. holidayDuration = holidayDuration.multiply(new BigDecimal(60));
  616. Calendar dd = Calendar.getInstance();
  617. dd.setTime(holidayStime);
  618. while(dd.getTime().compareTo(holidayEtime)<=0) {
  619. UserAttendanceDetailEntity temp_entity = hm_Date2AttendanceDetail.get(DataUtils.date2Str(dd.getTime(), DataUtils.date_sdf));
  620. if(temp_entity != null && temp_entity.getActualAttendanceDate() != null && temp_entity.getActualAttendanceDate().compareTo(BigDecimal.ZERO)>0) {
  621. if (temp_entity.getStatus().equals(Globals.ATTENDANCE_STATUS_EDIT_10)) {
  622. holidayDuration = holidayDuration.subtract(temp_entity.getActualAttendanceDate());
  623. if(holidayDuration.compareTo(BigDecimal.ZERO)<0) {
  624. holidayDuration = BigDecimal.ZERO;
  625. }
  626. }
  627. }
  628. dd.add(Calendar.DATE, 1);
  629. }
  630. if (Globals.REST_TYPE_1.equals(hilidaytype) ) {
  631. sickLeavetotalmins = sickLeavetotalmins.add(holidayDuration);
  632. }else if ( Globals.REST_TYPE_0.equals(hilidaytype)) {
  633. thingLeave = thingLeave.add(holidayDuration);
  634. }
  635. }
  636. //超时加班时长计算 月度基准时间-国定假日排班时长 -带薪休假时长-法定工时 ---原算法,新算法是月基准时间-法定工时然后抵扣旷工时长 zy20180416
  637. //月度法定工时=(当月天数-休假天数-国定休假天数)*8;datumAttendanceDate
  638. // timeoutOvertimeDuration= monthlyActDatumsum.subtract(monthlyLegalholidaysum)
  639. // .subtract(new BigDecimal(monthlyLegalworktime*8*60));
  640. // 2018年11月15日前的算法是169应出勤时间-月度法定工时
  641. // timeoutOvertimeDuration= datumAttendanceDate.subtract(new BigDecimal(monthlyLegalworktime*8*60));//xzx
  642. //2018年11月15日后的算法是实际出勤时间-法定工时,这里面实际出勤时间包含漏打卡时间 //xzx
  643. timeoutOvertimeDuration= actualAttendanceDate.subtract(new BigDecimal(monthlyLegalworktime*8*60));
  644. // 记录抵扣前的原始的超时加班时长和旷工时长
  645. if(timeoutOvertimeDuration == null) {
  646. userAttendanceTotalEntity.setTimeoutOvertimeDuration_orig(BigDecimal.ZERO);
  647. }else {
  648. userAttendanceTotalEntity.setTimeoutOvertimeDuration_orig(timeoutOvertimeDuration);
  649. }
  650. if(absenteeismAmount == null) {
  651. absenteeismAmount = BigDecimal.ZERO;
  652. userAttendanceTotalEntity.setAbsenteeismAmount_orig(BigDecimal.ZERO);
  653. }else {
  654. userAttendanceTotalEntity.setAbsenteeismAmount_orig(absenteeismAmount);
  655. }
  656. // 负数归零
  657. // 2019/2/11 超时加班时长负数代表没有做满法定工时
  658. // if(timeoutOvertimeDuration.compareTo(BigDecimal.ZERO) < 0) {
  659. // timeoutOvertimeDuration = BigDecimal.ZERO;
  660. // }
  661. if(absenteeismAmount.compareTo(BigDecimal.ZERO) < 0) {
  662. absenteeismAmount = BigDecimal.ZERO;
  663. }
  664. //旷工工时和超时加班工时进行相互抵扣 zy20180415
  665. // 2019/2/11由于超时加班采用实际出勤时间来计算,故不存在抵扣
  666. // if(timeoutOvertimeDuration.compareTo(absenteeismAmount) == 0) {
  667. // //旷工工时等于超时加班工时
  668. // timeoutOvertimeDuration = BigDecimal.ZERO;
  669. // absenteeismAmount = BigDecimal.ZERO;
  670. // }else if(timeoutOvertimeDuration.compareTo(absenteeismAmount) > 0) {
  671. // //超时加班工时多
  672. // timeoutOvertimeDuration = timeoutOvertimeDuration.subtract(absenteeismAmount);
  673. // absenteeismAmount = BigDecimal.ZERO;
  674. // }else {
  675. // //旷工工时多
  676. // absenteeismAmount = absenteeismAmount.subtract(timeoutOvertimeDuration);
  677. // timeoutOvertimeDuration = BigDecimal.ZERO;
  678. // }
  679. // /**
  680. // * 超时加班时长 当小于零的时候, 按 零存储
  681. // */
  682. // if (timeoutOvertimeDuration.compareTo(BigDecimal.ZERO)<0) {
  683. // timeoutOvertimeDuration = BigDecimal.ZERO;
  684. // }
  685. userAttendanceTotalEntity.setPaidLeave(paidLeave);
  686. userAttendanceTotalEntity.setThingLeave(thingLeave);
  687. userAttendanceTotalEntity.setSickLeave(sickLeave);
  688. userAttendanceTotalEntity.setMarriageLeave(marriageLeave);
  689. userAttendanceTotalEntity.setFuneralLeave(funeralLeave);
  690. userAttendanceTotalEntity.setMaternityLeave(maternityLeave);
  691. leaveTotalTime = thingLeave.add(sickLeavetotalmins)
  692. .add((paidLeave
  693. .add(marriageLeave)
  694. .add(funeralLeave)
  695. .add(maternityLeave)
  696. .add(accompanyMaternityLeave)).multiply(new BigDecimal(8*60)));
  697. userAttendanceTotalEntity.setLeaveTotalTime(leaveTotalTime);
  698. userAttendanceTotalEntity.setAccompanyMaternityLeave(accompanyMaternityLeave);
  699. userAttendanceTotalEntity.setDutyDuration(dutyDuration);
  700. userAttendanceTotalEntity.setNationalDutyDuration(nationalDutyDuration);
  701. userAttendanceTotalEntity.setEarlyLeaveAmount(earlyLeaveAmount);
  702. userAttendanceTotalEntity.setLateAmount(lateAmount);
  703. userAttendanceTotalEntity.setAbsenteeismAmount(absenteeismAmount);
  704. userAttendanceTotalEntity.setNoPunchCardAmount(noPunchCardAmount);
  705. userAttendanceTotalEntity.setDatumAttendanceDate(datumAttendanceDate);
  706. userAttendanceTotalEntity.setActualAttendanceDate(actualAttendanceDate);
  707. /**调整时间*/
  708. userAttendanceTotalEntity.setAdjustTime(adjustTime);
  709. /**超时加班时长*/
  710. userAttendanceTotalEntity.setTimeoutOvertimeDuration(timeoutOvertimeDuration);
  711. /**国定加班时长*/
  712. userAttendanceTotalEntity.setNationalOvertimeDuration(nationalOvertimeDuration);
  713. /**总时间差*/
  714. userAttendanceTotalEntity.setTimeDifferenceTotal(timeDifferenceTotal);
  715. /**特殊加班费*/
  716. userAttendanceTotalEntity.setSpecialOvertime(specialOvertime);
  717. /**总加班时间*/
  718. overtimeTotalTime = timeoutOvertimeDuration.add(nationalOvertimeDuration).add(specialOvertime);
  719. // 当总加班时间小于零的时候 以零处理
  720. if (overtimeTotalTime.compareTo(BigDecimal.ZERO)<0) {
  721. overtimeTotalTime = BigDecimal.ZERO;
  722. }
  723. userAttendanceTotalEntity.setOvertimeTotalTime(overtimeTotalTime);
  724. /**夜班白班津贴*/
  725. userAttendanceTotalEntity.setDayShiftSubsidy(dayShiftSubsidy);
  726. /**夜班夜班津贴*/
  727. userAttendanceTotalEntity.setNightShiftSubsidy(nightShiftSubsidy);
  728. /**日班*/
  729. userAttendanceTotalEntity.setDayShift(dayShift);
  730. /**常班*/
  731. userAttendanceTotalEntity.setRegularShift(regularShift);
  732. /** 额外加班 */
  733. userAttendanceTotalEntity.setExtraOvertime(extraOvertime);
  734. /** 是否单次临时调动过 */
  735. userAttendanceTotalEntity.setIfmoved(ifmoved);
  736. AttendanceTotalJsonObj json = new AttendanceTotalJsonObj();
  737. json.setSickLeavetotalmins(sickLeavetotalmins);
  738. userAttendanceTotalEntity.setJsonObj(JSONObject.toJSONString(json));
  739. saveOrUpdate(userAttendanceTotalEntity);
  740. }
  741. /**
  742. * 判断是否是带薪假
  743. * @param entity
  744. * @return
  745. */
  746. private boolean isPayLeave(UserAttendanceDetailEntity entity) {
  747. if (entity.getStatus().equals(Globals.ATTENDANCE_STATUS_EDIT_2)) {
  748. return true;
  749. }
  750. if (entity.getStatus().equals(Globals.ATTENDANCE_STATUS_EDIT_3)) {
  751. return true;
  752. }
  753. if (entity.getStatus().equals(Globals.ATTENDANCE_STATUS_EDIT_4)) {
  754. return true;
  755. }
  756. if (entity.getStatus().equals(Globals.ATTENDANCE_STATUS_EDIT_5)) {
  757. return true;
  758. }
  759. if (entity.getStatus().equals(Globals.ATTENDANCE_STATUS_EDIT_6)) {
  760. return true;
  761. }
  762. return false;
  763. }
  764. /**
  765. * 将从数据库中读取的字符串信息转化成实体类
  766. * 需求變更: 2018年1月12日17:30:17
  767. * 当员工两次都没打卡的时候, 默认界定为该员工旷工, 此时不提供餐补
  768. * @author hualong.zhao
  769. * @date 2017-11-29
  770. *
  771. * @param jsonobjString
  772. * @return
  773. */
  774. @Override
  775. public AttendanceDetailJsonObj getJsonObjFromString(String jsonobjString) {
  776. AttendanceDetailJsonObj jsonObj = new AttendanceDetailJsonObj();
  777. if (oConvertUtils.isNotEmpty(jsonobjString)) {
  778. try {
  779. jsonObj = (JSONObject.parseObject(jsonobjString)).toJavaObject(AttendanceDetailJsonObj.class);
  780. } catch (Exception e) {
  781. }
  782. }
  783. return jsonObj;
  784. }
  785. /*记一次迟到情况:
  786. 出勤时间>排班工作开始时间;并且10分钟<两者之差≤30分钟;*/
  787. /*当月的迟到次数累计 迟到:10min之内不算迟到,10<min≤30 算迟到,min>30 算旷工半天;
  788. 当天请事假,也得考察迟到;*/
  789. private void calculateBelateAndLeaveEarlyAndabsenteeism(
  790. UserAttendanceDetailDto dto) {
  791. //判断当天是否请了长假期
  792. boolean longHoliday = dto.getLongHoliday();
  793. //实际上班时间
  794. Date actattendanceDate = dto.getActattendanceDate();;
  795. //实际下班时间
  796. Date actretreatDate= dto.getActretreatDate();
  797. String dutyType = oConvertUtils.getString(dto.getDutyType());
  798. //前提条件: 如果排班为休息时 , 不考虑 迟到 / 早退 / 旷工
  799. if (!Globals.DUTYTYPE_xiuxi.equals(dutyType)) {
  800. //当班次为加班 或者是值班时 不考虑 迟到 / 早退
  801. if (oConvertUtils.isNotEmpty(dto.getNormalworkStime())&&oConvertUtils.isNotEmpty(dto.getNormalworkEtime())) {
  802. /**理应工作开始时间*/
  803. Date workStarttime =getexactDate(dto.getYmdDate(), dto.getNormalworkStime(), 0, 0);
  804. /**理应工作结束时间*/
  805. Integer t1flag = 0;
  806. boolean hassickorthingLeave = false;
  807. if (Globals.DUTYTYPE_yeban115.equals(dutyType)) {
  808. t1flag = 1;
  809. }
  810. Date workendtime = getexactDate(dto.getYmdDate(), dto.getNormalworkEtime(), t1flag, 0);
  811. // =====查询请假情况, 去掉事假的加班申请时长,计算理应的开始和结束工作时间 如果员工在这一天请了非事假意外的假 不认为该员工旷工 /迟到/早退
  812. List<HolidayEntity> userHolidayEntities = dto.getUserHolidayEntities();
  813. if (!ListUtils.isNullOrEmpty(userHolidayEntities)) {
  814. for (HolidayEntity holiday:userHolidayEntities) {
  815. String hilidaytype =oConvertUtils.getString( holiday.getHolidayType());
  816. if (Globals.REST_TYPE_1.equals(hilidaytype)||Globals.REST_TYPE_0.equals(hilidaytype)) {
  817. BigDecimal holidayDuration= calculateHolidayDuration(holiday,workStarttime,workendtime,dto);
  818. /**休假开始时间*/
  819. Date holidayStime = holiday.getHolidayStime();
  820. /**休假结束时间*/
  821. Date holidayEtime = holiday.getHolidayEtime();
  822. if (holidayStime.compareTo(workStarttime)<=0&&holidayEtime.compareTo(workStarttime)>=0) {
  823. workStarttime = holidayEtime;
  824. }
  825. if (holidayStime.compareTo(workendtime)<=0&&holidayEtime.compareTo(workendtime)>=0) {
  826. workendtime = holidayStime;
  827. }
  828. BigDecimal datumDate = dto.getDatumDate();
  829. //如果休假表中填写的申请假期时长 大于当天的基准时间 是按照基准时间处理
  830. holidayDuration = holidayDuration.compareTo(datumDate)>0?datumDate:holidayDuration;
  831. if(dto.getActualAttendanceDate() != null && dto.getActualAttendanceDate().compareTo(BigDecimal.ZERO)>0) {
  832. // 如果当天有实际出勤时间,那么从请假中扣除
  833. holidayDuration = holidayDuration.subtract(dto.getActualAttendanceDate());
  834. }
  835. if (Globals.REST_TYPE_1.equals(hilidaytype)) {
  836. dto.setSickLeaveMins(holidayDuration);
  837. }else {
  838. // 修改为 改天请假的 小时数 这算的分钟数
  839. dto.setThingLeaveMins(holidayDuration);
  840. }
  841. hassickorthingLeave = true;
  842. }else {
  843. dto.setLeaveEarly(false);
  844. dto.setBelate(false);
  845. dto.setAbsenteeism(BigDecimal.ZERO);
  846. longHoliday = true;
  847. break;
  848. }
  849. }
  850. }
  851. //如果请了事假之外的假期, 则认为该员工没有迟到 没有早退 没有旷工
  852. //如果是国定假出现缺勤,不算旷工
  853. if (!longHoliday && !Globals.dtype_2.equals(oConvertUtils.getString(dto.getDtype()))) {
  854. //如果两个打卡时间均为空, 则该员工旷工(前提条件是该员工没有请事假或者是病假)
  855. if (!hassickorthingLeave) {
  856. if (oConvertUtils.isEmpty(actattendanceDate)&&oConvertUtils.isEmpty(actretreatDate)) {
  857. // 当员工两次都没打卡的时候, 界定为该员工旷工, 此时不提供餐补
  858. dto.setAbsenteeism(dto.getDatumDate());
  859. }
  860. }
  861. //计算是否为迟到 或者是早旷工
  862. if (oConvertUtils.isNotEmpty(actattendanceDate)&&actattendanceDate.after(workStarttime)) {
  863. // 实际上班时间
  864. Calendar actattendanceCalendar = Calendar.getInstance();
  865. actattendanceCalendar.setTime(actattendanceDate);
  866. // 理论应该工作时间
  867. Calendar workStartCalendar = Calendar.getInstance();
  868. workStartCalendar.setTime(workStarttime);
  869. int dateDiffint = DataUtils.dateDiff('m', actattendanceCalendar,workStartCalendar);
  870. if (actattendanceDate.equals(actretreatDate)) {
  871. // 如果開始時間等於结束时间 则定义为该员工漏打卡 , 此时 不计算欠勤时间
  872. dateDiffint = 0;
  873. }
  874. dto.setBelatemins(dateDiffint);
  875. //出勤时间>排班工作开始时间;并且10分钟<两者之差≤30分钟;
  876. if (dateDiffint>10&&dateDiffint<=30) {
  877. dto.setBelate(true);
  878. }
  879. //迟到,min>30 切小于240分钟 算旷工4小时
  880. if (dateDiffint>30&&dateDiffint<240) {
  881. BigDecimal absenteeism = dto.getAbsenteeism().add(new BigDecimal(240));
  882. dto.setAbsenteeism(absenteeism);
  883. }
  884. //迟到,min>=240&&dateDiffint<480 算旷工8小时
  885. if(dateDiffint>=240&&dateDiffint<480) {
  886. BigDecimal absenteeism = dto.getAbsenteeism().add(new BigDecimal(480));
  887. dto.setAbsenteeism(absenteeism);
  888. }
  889. //迟到,min>=480 算旷工实际班次工时
  890. if (dateDiffint>=480) {
  891. BigDecimal absenteeism = dto.getAbsenteeism().add(new BigDecimal(dateDiffint));
  892. dto.setAbsenteeism(absenteeism);
  893. }
  894. }
  895. if (oConvertUtils.isNotEmpty(actretreatDate)
  896. && oConvertUtils.isNotEmpty(actattendanceDate)
  897. && actretreatDate.after(actattendanceDate)
  898. && actretreatDate.before(workendtime)) {
  899. // 实际下班时间
  900. Calendar actretreatCalendar = Calendar.getInstance();
  901. actretreatCalendar.setTime(actretreatDate);
  902. // 理论应该下班时间
  903. Calendar workendCalendar = Calendar.getInstance();
  904. workendCalendar.setTime(workendtime);
  905. int dateDiffint = DataUtils.dateDiff('m',workendCalendar, actretreatCalendar);
  906. if (actattendanceDate.equals(actretreatDate)) {
  907. // 如果開始時間等於结束时间 则定义为该员工漏打卡 , 此时 不计算欠勤时间
  908. dateDiffint = 0;
  909. }
  910. dto.setLeaveEarlymins(dateDiffint);
  911. //出勤时间>排班工作开始时间;并且10分钟<两者之差≤30分钟;
  912. if (dateDiffint>10&&dateDiffint<=30) {
  913. dto.setLeaveEarly(true);
  914. }
  915. //迟到,min>30 切小于240分钟 算旷工4小时
  916. if (dateDiffint>30&&dateDiffint<240) {
  917. BigDecimal absenteeism = dto.getAbsenteeism().add(new BigDecimal(240));
  918. dto.setAbsenteeism(absenteeism);
  919. }
  920. //迟到,min>=240&&dateDiffint<480 算旷工8小时
  921. if(dateDiffint>=240&&dateDiffint<480) {
  922. BigDecimal absenteeism = dto.getAbsenteeism().add(new BigDecimal(480));
  923. dto.setAbsenteeism(absenteeism);
  924. }
  925. //迟到,min>=480 算旷工实际班次工时
  926. if (dateDiffint>=480) {
  927. BigDecimal absenteeism = dto.getAbsenteeism().add(new BigDecimal(dateDiffint));
  928. dto.setAbsenteeism(absenteeism);
  929. }
  930. }
  931. // BigDecimal absenteeism = dto.getAbsenteeism();
  932. // if (absenteeism.compareTo(new BigDecimal(8))>=0) {
  933. // dto.setLeaveEarly(false);
  934. // dto.setBelate(false);
  935. // dto.setAbsenteeism(new BigDecimal(8));
  936. // }
  937. // 如果漏打卡: 打卡开始时间等于打卡结束时间 这个时候 只计算迟到和早退 旷工按零计算
  938. if (oConvertUtils.isNotEmpty(actattendanceDate)
  939. && oConvertUtils.isNotEmpty(actretreatDate)
  940. && actattendanceDate.equals(actretreatDate)) {
  941. dto.setAbsenteeism(BigDecimal.ZERO);
  942. }
  943. }
  944. }else {
  945. // 当加班/值班 的时候 不迟到 也不早退 也不认为该员工旷工
  946. }
  947. }
  948. dto.setLongHoliday(longHoliday);
  949. }
  950. /**FIXME 有待校验
  951. * 动态计算 事假/病假的分钟数
  952. * @author hualong.zhao
  953. * @date 2018-1-10
  954. * @param holiday
  955. * @param workStarttime
  956. * @param workendtime
  957. * @param dto
  958. * @param dto
  959. * @return
  960. */
  961. private BigDecimal calculateHolidayDuration(HolidayEntity holiday,
  962. Date workStarttime, Date workendtime, UserAttendanceDetailDto dto) {
  963. BigDecimal holidayDuration=BigDecimal.ZERO;
  964. /**休假开始时间*/
  965. Date holidayStime = holiday.getHolidayStime();
  966. /**休假结束时间*/
  967. Date holidayEtime = holiday.getHolidayEtime();
  968. Date startmax =workStarttime;
  969. Date endmin =workendtime;
  970. if (workStarttime.compareTo(holidayStime) <= 0
  971. && holidayStime.compareTo(workendtime) <= 0){
  972. startmax = holidayStime;
  973. }
  974. if (workStarttime.compareTo(holidayEtime) <= 0
  975. && holidayEtime.compareTo(workendtime) <= 0){
  976. endmin =holidayEtime;
  977. }
  978. String durationCode = "0";
  979. //如果请假开始时间小于等于上班开始时间 且请假结束时间早于下班时间 则认为该员工请的假期为前半夜假期
  980. if (holidayStime.compareTo(workStarttime) <= 0
  981. && holidayEtime.compareTo(workendtime) <0){
  982. durationCode = "1";
  983. }
  984. //如果请假开始时间大于上班开始时间 且请假结束时间等于或者是晚于下班时间 则认为该员工请的假期为后半夜假期
  985. if (workStarttime.compareTo(holidayStime ) < 0
  986. &&workendtime.compareTo(holidayEtime) <=0) {
  987. durationCode = "2";
  988. }
  989. dto.setDurationCode(durationCode);
  990. // 时间段开始时间
  991. Calendar startCalendar = Calendar.getInstance();
  992. startCalendar.setTime(startmax);
  993. // 时间段结束时间
  994. Calendar endCalendar = Calendar.getInstance();
  995. endCalendar.setTime(endmin);
  996. int startDiffint = DataUtils.dateDiff('m', endCalendar,startCalendar);
  997. holidayDuration = new BigDecimal(Math.abs(startDiffint));
  998. return holidayDuration;
  999. }
  1000. /**设置基准时间
  1001. * 排班计划中的: 正常工作基准工时 每日的排班的基准时间 排班信息:获取员工当日的排班基准时间;
  1002. * 根据“月度员工排班”中的员工排班情况,获取每日的班次; 根据“班次设定”中的“基准时间”获取每日的基准时长;
  1003. *
  1004. *
  1005. *
  1006. * 请婚假、丧假、带薪假、陪产假情况下,计算超时加班时长=月度基准时长-法定工时,其中请假当天的月度基准时长要按照8小时累计
  1007. * @param hm_cache
  1008. */
  1009. private void calculateDatumDate(HashMap<String, HashMap<String, Object>> hm_cache, UserAttendanceDetailDto dto) {
  1010. // 基准时间
  1011. BigDecimal datumDate = BigDecimal.ZERO;
  1012. if (Globals.DUTYTYPE_yeban115.equals(dto.getDutyType())) {
  1013. //如果是跨日期夜班,需要判断是否有国定时间,有的话要刨除 -zy 20180513
  1014. BigDecimal yebanNationalDuration = calculateHalfNationalOvertime(hm_cache, dto,false);
  1015. if(yebanNationalDuration.compareTo(BigDecimal.ZERO) >= 0) {
  1016. datumDate = new BigDecimal(11.5*60).subtract(yebanNationalDuration);
  1017. }
  1018. }else if(Globals.dtype_2.equals(oConvertUtils.getString(dto.getDtype()))) {
  1019. //如果是国定排班,且不跨夜
  1020. datumDate = BigDecimal.ZERO;
  1021. }else {
  1022. BigDecimal datumWorkhours = dto.getDatumWorkhours();
  1023. if (null != datumWorkhours) {
  1024. datumDate = datumWorkhours.multiply(new BigDecimal(60));
  1025. }
  1026. }
  1027. dto.setDatumDate(datumDate);
  1028. }
  1029. /**
  1030. * 获取借调信息 疑问点: 1 当某人处于周期临时借调中时, 刚好这一天又有单次临时借调, 这个怎么处置? (目前在临时借调处没有限制) 2 同一天,
  1031. * 某人即被A部门临时借调, 又被B部门临时借调, 算哪一天
  1032. *
  1033. *
  1034. *
  1035. * @author hualong.zhao
  1036. * @date 2017-11-25
  1037. * @param dto
  1038. */
  1039. private void calculateBorrowsInfo(UserAttendanceDetailDto dto) {
  1040. // 借调状态;0未借调,1单次借调 2 周期性临时借调
  1041. String borrowstatus = "0";
  1042. // 借调项目id
  1043. String borrowspid = null;
  1044. // 借调部门id 对应的是临时借调表中的调入单位id
  1045. String borrowsdepartid = null;
  1046. // 单次借调日薪
  1047. BigDecimal dayPay = null;
  1048. // 01 临时借调(单次)申请表
  1049. List<SnapSingleborrowEntity> snapSingleborrowEntities = dto
  1050. .getSnapSingleborrowEntities();
  1051. // 02 临时借调(固定周期)申请表
  1052. List<SnapRegularborrowEntity> snapRegularborrowEntities = dto
  1053. .getSnapRegularborrowEntities();
  1054. if (!ListUtils.isNullOrEmpty(snapRegularborrowEntities)) {
  1055. borrowstatus = "2";
  1056. for (SnapRegularborrowEntity entity : snapRegularborrowEntities) {
  1057. // 临时借调表中的调入单位id
  1058. borrowsdepartid = entity.getInUnitid();
  1059. TSDepart tsDepart = getQyDepartByorgid(borrowsdepartid);
  1060. if (oConvertUtils.isEmpty(tsDepart)||oConvertUtils.isEmpty(tsDepart.getId())) {
  1061. }else {
  1062. borrowspid = tsDepart.getId();
  1063. }
  1064. }
  1065. }
  1066. if (!ListUtils.isNullOrEmpty(snapSingleborrowEntities)) {
  1067. borrowstatus = "1";
  1068. for (SnapSingleborrowEntity entity : snapSingleborrowEntities) {
  1069. // 临时借调表中的调入单位id
  1070. borrowspid = entity.getInUnitid();
  1071. // 查询当前员工的区域组织机构
  1072. TSDepart tsDepart = getQyDepartByorgid(borrowspid);
  1073. if (oConvertUtils.isEmpty(tsDepart)||oConvertUtils.isEmpty(tsDepart.getId())) {
  1074. }else {
  1075. borrowspid = tsDepart.getId();
  1076. }
  1077. borrowsdepartid = entity.getInUnitid();
  1078. //--author:zhaohualong-----start----date: 2018年1月19日--------for: 需求确认: 当且仅当是工作日的时候 才允许给该员工单日的日付薪------
  1079. if (oConvertUtils.getString(dto.getDtype()).equals(Globals.dtype_0)) {
  1080. dayPay = entity.getDayPay();
  1081. }
  1082. }
  1083. }
  1084. dto.setBorrowstatus(borrowstatus);
  1085. dto.setBorrowspid(borrowspid);
  1086. dto.setBorrowsdepartid(borrowsdepartid);
  1087. dto.setDayPay(dayPay);
  1088. }
  1089. /**
  1090. * 根据组织机构id 获取项目 (直属项目 or 区域项目)
  1091. * @author hualong.zhao
  1092. * @date 2018-1-17
  1093. * @param orgid
  1094. * @return
  1095. */
  1096. private TSDepart getQyDepartByorgid(String orgid) {
  1097. if (oConvertUtils.isEmpty(orgid)) {
  1098. return null;
  1099. }
  1100. TSDepart tsDepart = get(TSDepart.class, orgid);
  1101. if (tsDepart.getOrgType().equals(Globals.org_type_3)||tsDepart.getOrgType().equals(Globals.org_type_5)) {
  1102. return tsDepart;
  1103. } else {
  1104. TSDepart parentdepart = tsDepart.getTSPDepart();
  1105. if (oConvertUtils.isEmpty(parentdepart)||oConvertUtils.isEmpty(parentdepart.getId())) {
  1106. return null;
  1107. } else {
  1108. return getQyDepartByorgid(tsDepart.getTSPDepart().getId());
  1109. }
  1110. }
  1111. }
  1112. /**
  1113. *
  1114. *
  1115. * new*
  1116. 1 如果"考勤退勤时间"晚于"排班基准时间"的"结束时间",并且"考勤出勤时间"早于"排班基准时间"的"开始时间":(未早退也未迟到)
  1117. 实际出勤时间="排班基准时间";(未更改)
  1118. 2如果"考勤退勤时间"早于"排班基准时间"的"结束时间",并且"考勤出勤时间"早于"排班基准时间"的"开始时间":(早退 但是没有迟到)
  1119. 实际出勤时间=排班基准时间-早退的分钟数
  1120. 3 如果"考勤退勤时间"晚于"排班基准时间"的"结束时间",并且"考勤出勤时间"晚于"排班基准时间"的"开始时间":(迟到 但是没有早退)
  1121. 实际出勤时间=排班基准时间-迟到的分钟数
  1122. 4 如果"考勤退勤时间"早于"排班基准时间"的"结束时间",并且"考勤出勤时间"晚于"排班基准时间"的"开始时间":(有迟到 也有早退)
  1123. 实际出勤时间= 排班基准时间-(早退的分钟数"+迟到的分钟数);
  1124. * old
  1125. * 根据实际考勤记录计算的时间 如果“考勤退勤时间”晚于“排班基准时间”的“结束时间”,并且“考勤出勤时间”早于“排班基准时间”的“开始时间”:
  1126. * 实际出勤时间=“排班基准时间”; 如果“考勤退勤时间”早于“排班基准时间”的“结束时间”,并且“考勤出勤时间”早于“排班基准时间”的“开始时间”:
  1127. * 实际出勤时间=“考勤退勤时间”-“排班基准时间”的开始时间;
  1128. * 如果“考勤退勤时间”晚于“排班基准时间”的“结束时间”,并且“考勤出勤时间”晚于“排班基准时间”的“开始时间”:
  1129. * 实际出勤时间=“排班基准时间”的结束时间-“考勤出勤时间”;
  1130. * 如果“考勤退勤时间”早于“排班基准时间”的“结束时间”,并且“考勤出勤时间”晚于“排班基准时间”的“开始时间”: 实际出勤时间=
  1131. * “考勤退勤时间”-“考勤出勤时间”; 实际出勤时长不考虑中间的休息时长;
  1132. * 考勤退勤时间、考勤出勤时间点应该是在当日打卡标准范围内的才计算,超出范围内视为漏打卡;
  1133. *
  1134. *
  1135. * 实际出勤时间大于基准时间的按照基准时间计算;
  1136. *
  1137. * @author hualong.zhao
  1138. * @date 2017-11-24
  1139. * @param dto
  1140. */
  1141. private void calculateActualAttendanceDate(UserAttendanceDetailDto dto) {
  1142. BigDecimal actualAttendanceDate = new BigDecimal(0);
  1143. // 正常上班时间
  1144. String normalworkStime = dto.getNormalworkStime();
  1145. // 正常下班时间
  1146. String normalworkEtime = dto.getNormalworkEtime();
  1147. if (oConvertUtils.isEmpty(normalworkStime)||oConvertUtils.isEmpty(normalworkEtime)) {
  1148. String dutyType = oConvertUtils.getString(dto.getDutyType());
  1149. if (Globals.DUTYTYPE_jiaban.equals(dutyType)) {
  1150. normalworkStime = oConvertUtils.getString(dto.getTimeOutOvertimeStime(), "00:00");
  1151. normalworkEtime =oConvertUtils.getString( dto.getTimeOutOvertimeEtime(), "23:59");
  1152. //计算加班的时候的实际出勤时间
  1153. }else if ( Globals.DUTYTYPE_zhiban.equals(dutyType)) {
  1154. // normalworkStime = oConvertUtils.getString(dto.getOndutyStime(), "00:00");
  1155. // normalworkEtime =oConvertUtils.getString( dto.getOndutyEtime(), "23:59");
  1156. return;
  1157. //计算加班的时候的实际出勤时间
  1158. }else if (Globals.DUTYTYPE_xiuxi.equals(dutyType)) {
  1159. // 当他休息的时候
  1160. //计算加班的时候的实际出勤时间
  1161. return ;
  1162. }
  1163. }
  1164. Date normalworkStartdate = getexactDate(dto.getYmdDate(),
  1165. normalworkStime, 0, 0);
  1166. Integer t1flag = 0;
  1167. if (oConvertUtils.getString(dto.getDutyType()).equals(Globals.DUTYTYPE_yeban115)) {
  1168. t1flag = 1;
  1169. }
  1170. Date normalworkenddate = getexactDate(dto.getYmdDate(),
  1171. normalworkEtime, t1flag, 0);
  1172. // 实际打卡开始时间
  1173. Date actattendanceDate = dto.getActattendanceDate();
  1174. // 实际打卡结束时间
  1175. Date actretreatDate = dto.getActretreatDate();
  1176. if (normalworkStartdate.equals(normalworkenddate)) {
  1177. // 当这天安排的工作是休息时---上班时间等于下班时间
  1178. }
  1179. // 正常工作基准工时
  1180. BigDecimal datumWorkhours = dto.getDatumWorkhours();
  1181. BigDecimal datumWorkmins = BigDecimal.ZERO;
  1182. if (null != datumWorkhours) {
  1183. datumWorkmins = datumWorkhours.multiply(new BigDecimal(60));
  1184. }
  1185. if (oConvertUtils.isEmpty(actattendanceDate)
  1186. && oConvertUtils.isEmpty(actretreatDate)) {
  1187. dto.setActualAttendanceDate( new BigDecimal(0));
  1188. //如果开始打卡时间 或结束打卡时间为空,则时间差值 应当等于 负的 正常工作基准工时
  1189. return;
  1190. }else if(oConvertUtils.isEmpty(actattendanceDate) && !oConvertUtils.isEmpty(actretreatDate)) {
  1191. // 开始没打开,下班打卡
  1192. if (actretreatDate.compareTo(normalworkenddate) >= 0) {
  1193. // 如果“考勤退勤时间”晚于“排班基准时间”的“结束时间”,算漏打卡
  1194. // 实际出勤时间=“排班基准时间”;
  1195. actualAttendanceDate = datumWorkmins;
  1196. }else {
  1197. // 如果“考勤退勤时间”早于“排班基准时间”的“结束时间”,算早退
  1198. Calendar actretreatDateCalendar = Calendar.getInstance();
  1199. actretreatDateCalendar.setTime(actretreatDate);
  1200. // “排班基准时间”的结束时间
  1201. Calendar normalworkendCalendar = Calendar.getInstance();
  1202. normalworkendCalendar.setTime(normalworkenddate);
  1203. //早退的分钟数
  1204. int dateDiffint = DataUtils.dateDiff('m', actretreatDateCalendar,normalworkendCalendar);
  1205. actualAttendanceDate = datumWorkmins.subtract(new BigDecimal(Math.abs(dateDiffint)));
  1206. }
  1207. }else if(!oConvertUtils.isEmpty(actattendanceDate) && oConvertUtils.isEmpty(actretreatDate)) {
  1208. // 上班打卡,结束没打卡
  1209. if (actattendanceDate.compareTo(normalworkStartdate) <= 0) {
  1210. // 如果“考勤开始时间”早于“排班基准时间”的“开始时间”,算漏打卡
  1211. // 实际出勤时间=“排班基准时间”;
  1212. actualAttendanceDate = datumWorkmins;
  1213. }else {
  1214. // 如果“考勤开始时间”晚于“排班基准时间”的“开始时间”,算迟到
  1215. // “排班基准时间”的“开始时间”
  1216. Calendar normalworkStartCalendar = Calendar.getInstance();
  1217. normalworkStartCalendar.setTime(normalworkStartdate);
  1218. // “考勤出勤时间”
  1219. Calendar actattendanceCalendar = Calendar.getInstance();
  1220. actattendanceCalendar.setTime(actattendanceDate);
  1221. //迟到的分钟数
  1222. int dateDiffint = DataUtils.dateDiff('m', normalworkStartCalendar,actattendanceCalendar);
  1223. actualAttendanceDate = datumWorkmins.subtract(new BigDecimal(Math.abs(dateDiffint)));
  1224. }
  1225. }else {
  1226. // 上下班都有考勤打卡
  1227. // 如果“考勤退勤时间”晚于“排班基准时间”的“结束时间”,并且“考勤出勤时间”早于“排班基准时间”的“开始时间”:
  1228. // 实际出勤时间=“排班基准时间”;
  1229. if ((actretreatDate.compareTo(normalworkenddate) >= 0)
  1230. && (actattendanceDate.compareTo(normalworkStartdate) <= 0)) {
  1231. actualAttendanceDate = datumWorkmins;
  1232. }
  1233. // 如果“考勤退勤时间”早于“排班基准时间”的“结束时间”,并且“考勤出勤时间”早于“排班基准时间”的“开始时间”:
  1234. // 实际出勤时间=排班基准时间- 早退的分钟数
  1235. if ((actretreatDate.compareTo(normalworkenddate) < 0)
  1236. && (actattendanceDate.compareTo(normalworkStartdate) <= 0)) {
  1237. // 考勤退勤时间"
  1238. Calendar actretreatDateCalendar = Calendar.getInstance();
  1239. actretreatDateCalendar.setTime(actretreatDate);
  1240. // “排班基准时间”的结束时间
  1241. Calendar normalworkendCalendar = Calendar.getInstance();
  1242. normalworkendCalendar.setTime(normalworkenddate);
  1243. //早退的分钟数
  1244. int dateDiffint = DataUtils.dateDiff('m', actretreatDateCalendar,normalworkendCalendar);
  1245. actualAttendanceDate = datumWorkmins.subtract(new BigDecimal(Math.abs(dateDiffint)));
  1246. }
  1247. // 如果“考勤退勤时间”晚于“排班基准时间”的“结束时间”,并且“考勤出勤时间”晚于“排班基准时间”的“开始时间”:
  1248. // 实际出勤时间=排班基准时间- 迟到的分钟数
  1249. if ((actretreatDate.compareTo(normalworkenddate) >= 0)
  1250. && (actattendanceDate.compareTo(normalworkStartdate) > 0)) {
  1251. // “排班基准时间”的“开始时间”
  1252. Calendar normalworkStartCalendar = Calendar.getInstance();
  1253. normalworkStartCalendar.setTime(normalworkStartdate);
  1254. // “考勤出勤时间”
  1255. Calendar actattendanceCalendar = Calendar.getInstance();
  1256. actattendanceCalendar.setTime(actattendanceDate);
  1257. //迟到的分钟数
  1258. int dateDiffint = DataUtils.dateDiff('m', normalworkStartCalendar,actattendanceCalendar);
  1259. actualAttendanceDate = datumWorkmins.subtract(new BigDecimal(Math.abs(dateDiffint)));
  1260. }
  1261. // 如果“考勤退勤时间”早于“排班基准时间”的“结束时间”,并且“考勤出勤时间”晚于“排班基准时间”的“开始时间”:
  1262. // 实际出勤时间= 排班基准时间- (“考勤退勤欠勤时间”+“考勤出勤欠勤时间”);
  1263. if ((actretreatDate.compareTo(normalworkenddate) < 0)
  1264. && (actattendanceDate.compareTo(normalworkStartdate) > 0)) {
  1265. // 考勤退勤时间"
  1266. Calendar actretreatCalendar = Calendar.getInstance();
  1267. actretreatCalendar.setTime(actretreatDate);
  1268. //“排班基准时间”的“结束时间”
  1269. Calendar normalworkenddateCalendar = Calendar.getInstance();
  1270. normalworkenddateCalendar.setTime(normalworkenddate);
  1271. // “考勤出勤时间”
  1272. Calendar actattendanceCalendar = Calendar.getInstance();
  1273. actattendanceCalendar.setTime(actattendanceDate);
  1274. // “排班基准时间”的“开始时间”
  1275. Calendar normalworkStartdateCalendar = Calendar.getInstance();
  1276. normalworkStartdateCalendar.setTime(normalworkStartdate);
  1277. //出勤欠勤分钟数
  1278. int belatedateDiffint = DataUtils.dateDiff('m', actattendanceCalendar,
  1279. normalworkStartdateCalendar);
  1280. //退勤欠勤分钟数
  1281. int leaveearlyDiffint = DataUtils.dateDiff('m', normalworkenddateCalendar,
  1282. actretreatCalendar);
  1283. //实际出勤分钟数 = min(打卡结束时间, 理论下班结束时间)-max(实际打卡时间, 理论上班时间)
  1284. Date startDate =normalworkStartdate.compareTo(actattendanceDate)<= 0?actattendanceDate:normalworkStartdate;
  1285. Date endDate =normalworkenddate.compareTo(actretreatDate)<= 0?normalworkenddate:actretreatDate;
  1286. Calendar startCalendar = Calendar.getInstance();
  1287. startCalendar.setTime(startDate);
  1288. Calendar endCalendar = Calendar.getInstance();
  1289. endCalendar.setTime(endDate);
  1290. int dateDiffint = 0;
  1291. if (startDate.compareTo(endDate)<=0) {
  1292. dateDiffint = Math.abs(DataUtils.dateDiff('m', startCalendar, endCalendar));
  1293. }
  1294. actualAttendanceDate = datumWorkmins.subtract(new BigDecimal(Math.abs(belatedateDiffint)))
  1295. .subtract(new BigDecimal(Math.abs(leaveearlyDiffint)));
  1296. //当值班或者是加班的时候 只要有打卡记录, 代码就会走到这里来, 这个时候 将实际出勤时间 记作 加班/值班的基准时间
  1297. String dutyType = oConvertUtils.getString(dto.getDutyType());
  1298. if (Globals.DUTYTYPE_jiaban.equals(dutyType)||Globals.DUTYTYPE_zhiban.equals(dutyType)) {
  1299. //当为值班或者是加班的时候 获取这一天的实际出勤分钟数, 与这一天的基准出勤分钟数 取这两个值的最小值 记为实际出勤时间
  1300. BigDecimal actmins = new BigDecimal(dateDiffint);
  1301. actualAttendanceDate =datumWorkmins.compareTo(actmins)<0?datumWorkmins:actmins;
  1302. }
  1303. }
  1304. }
  1305. // 实际出勤时间大于基准时间的按照基准时间计算;
  1306. if (!datumWorkmins.equals(BigDecimal.ZERO)&&datumWorkmins.compareTo(actualAttendanceDate)<0) {
  1307. actualAttendanceDate = datumWorkmins;
  1308. }
  1309. //实际出勤时间小于零的时候 写为零
  1310. if (actualAttendanceDate.compareTo(BigDecimal.ZERO)<0) {
  1311. actualAttendanceDate = BigDecimal.ZERO;
  1312. }
  1313. //设置实际出勤时间
  1314. dto.setActualAttendanceDate(actualAttendanceDate);
  1315. }
  1316. /**
  1317. * 根据钉钉打卡记录原始数据, 查询有效开始打卡时间内的最早打卡时间 和 最晚打卡时间
  1318. * update 2018年1月14日10:24:32
  1319. * 额外加班 只要有加班申请 就记作+1 不用查看是否有打卡记录
  1320. * @author hualong.zhao
  1321. * @date 2017-11-24
  1322. * @param dto
  1323. * @param dingAttendanceinfoEntities
  1324. * @param hm_specialAttendEntities
  1325. * @param adjustedEntities
  1326. * @param adjustedEntities
  1327. * @param detailEntity
  1328. */
  1329. private void calculateActAttendancetime(UserAttendanceDetailDto dto,
  1330. List<DingAttendanceinfoEntity> dingAttendanceinfoEntities, List<UserAttendanceDetailAdjustedEntity> adjustedEntities, List<UserAttendanceDetailDto> uatdlist, UserAttendanceDetailEntity detailEntity) {
  1331. // 根据钉钉打卡记录原始数据, 查询有效开始打卡时间内的最早打卡时间 和 最晚打卡时间
  1332. //获取有效开始打卡时间
  1333. Date effectiveStime =dto.getEffectiveStime();
  1334. //获取有效结束打卡时间
  1335. Date effectiveEtime = dto.getEffectiveEtime();
  1336. // 实际打卡开始时间
  1337. Date actattendanceDate = null;
  1338. // 实际打卡结束时间
  1339. Date actretreatDate = null;
  1340. boolean yesterdayisyb = true;
  1341. // 有特殊考勤记录
  1342. boolean hasSpecialAttendInfo = false;
  1343. try {
  1344. hasSpecialAttendInfo = specialAttendService.hasSpecialAttendInfo(dto.getUserid());
  1345. } catch (Exception e) {
  1346. e.printStackTrace();
  1347. }
  1348. // 如果是特殊考勤类型,不管钉钉记录如何,都进行统一处理,比如手工考勤——默认全勤
  1349. if(hasSpecialAttendInfo) {
  1350. // 默认全勤, 模拟钉钉考勤记录, 默认有效开始和结束打卡时间
  1351. dingAttendanceinfoEntities = new ArrayList<DingAttendanceinfoEntity>();
  1352. DingAttendanceinfoEntity startDingdingAttend = new DingAttendanceinfoEntity();
  1353. startDingdingAttend.setAttendanceTime(effectiveStime);
  1354. DingAttendanceinfoEntity endDingdingAttend = new DingAttendanceinfoEntity();
  1355. endDingdingAttend.setAttendanceTime(effectiveEtime);
  1356. dingAttendanceinfoEntities.add(startDingdingAttend);
  1357. dingAttendanceinfoEntities.add(endDingdingAttend);
  1358. }
  1359. // 在钉钉打卡记录不为空情况下查询下述
  1360. if (!ListUtils.isNullOrEmpty(dingAttendanceinfoEntities)) {
  1361. //正向遍历打卡记录 查询在有效打开记录区间内 最早的一次打卡记录
  1362. if (oConvertUtils.isNotEmpty(effectiveStime)) {
  1363. for (int i = 0; i < dingAttendanceinfoEntities.size(); i++) {
  1364. DingAttendanceinfoEntity dingAttendanceinfoEntity = dingAttendanceinfoEntities
  1365. .get(i);
  1366. Date temp = dingAttendanceinfoEntity.getAttendanceTime();
  1367. if (oConvertUtils.isNotEmpty(temp)
  1368. &&temp.compareTo(effectiveEtime) <=0
  1369. && (temp.compareTo(effectiveStime) >= 0)) {
  1370. actattendanceDate = dingAttendanceinfoEntity
  1371. .getAttendanceTime();
  1372. break;
  1373. }
  1374. }
  1375. }else {
  1376. //effectiveStime 值为空: 说明当天没有排班信息 或这天是休息查询这一天的最早打卡时间(必须是本天的最早开始时间)
  1377. yesterdayisyb = checkYesterdaytype(dto,uatdlist);
  1378. // 先校验上一天是否为夜班 如果是夜班 不执行下述操作
  1379. if (!yesterdayisyb) {
  1380. Date todayend = getexactDate(dto.getYmdDate(), "00:00",1, 0 );
  1381. for (int i = 0; i < dingAttendanceinfoEntities.size(); i++) {
  1382. DingAttendanceinfoEntity dingAttendanceinfoEntity = dingAttendanceinfoEntities
  1383. .get(i);
  1384. Date temp = dingAttendanceinfoEntity.getAttendanceTime();
  1385. if (oConvertUtils.isNotEmpty(temp)&&temp.before(todayend)) {
  1386. actattendanceDate = dingAttendanceinfoEntity.getAttendanceTime();
  1387. break;
  1388. }
  1389. }
  1390. }
  1391. }
  1392. //如果值班/加班 和正常工作时间连续了 则 先查询 有效结束打卡时间后 的最新一次打卡,
  1393. // 此处应该加限制 因为现在 加班时间有16:30~18:30 往后找 就找到了t1的07:15 去了
  1394. //如果这个时间没有, 则查询值班/加班 结束时间之前的最后一次打卡
  1395. // ----------值班情况处理 ---20180308---yangxi---add---start----------
  1396. if(!Globals.DUTYTYPE_zhiban.equals(oConvertUtils.getString(dto.getDutyType()))) {
  1397. if (dto.isJiabanContinuous()) {
  1398. Integer epunchMinute = oConvertUtils.getInt(dto.getEpunchMinute(),0);
  1399. Calendar calendar = Calendar.getInstance();
  1400. calendar.setTime(effectiveEtime);
  1401. calendar.add(Calendar.MINUTE, epunchMinute);
  1402. // 默认全勤处理加班
  1403. if(hasSpecialAttendInfo) {
  1404. DingAttendanceinfoEntity endDingdingAttend = new DingAttendanceinfoEntity();
  1405. endDingdingAttend.setAttendanceTime(effectiveEtime);
  1406. dingAttendanceinfoEntities.add(endDingdingAttend);
  1407. }
  1408. Date endmaxTime = calendar.getTime();
  1409. for (int i = 0; i < dingAttendanceinfoEntities.size(); i++) {
  1410. DingAttendanceinfoEntity dingAttendanceinfoEntity = dingAttendanceinfoEntities
  1411. .get(i);
  1412. Date temp = dingAttendanceinfoEntity.getAttendanceTime();
  1413. if (oConvertUtils.isNotEmpty(temp)
  1414. && (temp.compareTo(effectiveEtime) >= 0)
  1415. && (temp.compareTo(endmaxTime) <= 0)) {
  1416. actretreatDate =temp;
  1417. break;
  1418. }
  1419. }
  1420. }
  1421. //判断是否在超时加班时出勤,判断标准是超时加班时长内打卡至少一次
  1422. //如果有出勤,则timeoutOvertimeDuration=timeOutOvertimeHours(排班中超时时长);实际出勤中加上加班时长actualAttendanceDate += timeOutOvertimeHours
  1423. //zy20180413
  1424. String jiabanStarttimeStr = dto.getTimeOutOvertimeStime();
  1425. String jiabanEndtimeStr = dto.getTimeOutOvertimeEtime();
  1426. Date jiabanStarttime = getexactDate(dto.getYmdDate(), jiabanStarttimeStr, 0, 0);
  1427. Date jiabanEndtime = getexactDate(dto.getYmdDate(), jiabanEndtimeStr, 0, 90);//增加90分钟有效范围
  1428. // 如果超时加班跨天设置,则加一
  1429. if(jiabanStarttime.after(jiabanEndtime)) {
  1430. Calendar jiabanendCal = Calendar.getInstance();
  1431. jiabanendCal.setTime(jiabanEndtime);
  1432. jiabanendCal.add(Calendar.DATE, 1);
  1433. jiabanEndtime = jiabanendCal.getTime();
  1434. }
  1435. // // 默认全勤处理值班
  1436. // if(hm_specialAttendEntities.containsKey(dto.getUserid())) {
  1437. // DingAttendanceinfoEntity endDingdingAttend = new DingAttendanceinfoEntity();
  1438. // endDingdingAttend.setAttendanceTime(jiabanStarttime);
  1439. // dingAttendanceinfoEntities.add(endDingdingAttend);
  1440. // }
  1441. if (oConvertUtils.isNotEmpty(jiabanStarttimeStr)&&oConvertUtils.isNotEmpty(jiabanEndtimeStr)) {
  1442. for (int i = 0; i < dingAttendanceinfoEntities.size(); i++) {
  1443. DingAttendanceinfoEntity dingAttendanceinfoEntity = dingAttendanceinfoEntities
  1444. .get(i);
  1445. Date temp = dingAttendanceinfoEntity.getAttendanceTime();
  1446. if (oConvertUtils.isNotEmpty(temp)
  1447. &&temp.compareTo(jiabanEndtime) <=0
  1448. && (temp.compareTo(jiabanStarttime) >= 0)) {
  1449. //设置实际超时加班时间
  1450. dto.setTimeoutOvertimeDuration(dto.getTimeOutOvertimeHours());
  1451. //实际出勤时间加上超时加班时间
  1452. BigDecimal actattendTime = dto.getActualAttendanceDate();
  1453. if(actattendTime != null) {
  1454. dto.setActualAttendanceDate(actattendTime.add(dto.getTimeoutOvertimeDuration()));
  1455. }
  1456. break;
  1457. }
  1458. }
  1459. }
  1460. }
  1461. //反向遍历打卡记录, 寻找在有效打卡记录区间内 最后一次打卡
  1462. if (oConvertUtils.isNotEmpty(effectiveEtime)&&oConvertUtils.isEmpty(actretreatDate)) {
  1463. for (int i = (dingAttendanceinfoEntities.size() - 1); i >= 0; i--) {
  1464. DingAttendanceinfoEntity dingAttendanceinfoEntity = dingAttendanceinfoEntities
  1465. .get(i);
  1466. Date temp = dingAttendanceinfoEntity.getAttendanceTime();
  1467. if (oConvertUtils.isNotEmpty(temp)
  1468. &&temp.compareTo(effectiveStime) >=0
  1469. &&temp.compareTo(effectiveEtime) <=0) {
  1470. actretreatDate = temp;
  1471. break;
  1472. }
  1473. }
  1474. }
  1475. if (oConvertUtils.isEmpty(effectiveEtime)) {
  1476. // effectiveEtime 值为空: 说明当天没有排班信息 或这天是休息 查询这一天的最晚打卡时间
  1477. // 先校验上一天是否为夜班 如果是夜班 不执行下述操作
  1478. if (!yesterdayisyb){
  1479. Date todayendDate = getexactDate(dto.getYmdDate(), "00:00",1, 0);
  1480. for (int i = (dingAttendanceinfoEntities.size() - 1); i >= 0; i--) {
  1481. DingAttendanceinfoEntity dingAttendanceinfoEntity = dingAttendanceinfoEntities
  1482. .get(i);
  1483. Date temp = dingAttendanceinfoEntity.getAttendanceTime();
  1484. if (oConvertUtils.isNotEmpty(temp)&&temp.compareTo(todayendDate) <0) {
  1485. actretreatDate = temp;
  1486. break;
  1487. }
  1488. }
  1489. }
  1490. }
  1491. }
  1492. UserAttendanceDetailAdjustedEntity currDateAdjustEntity = getCurrDateAdjustEntity(adjustedEntities, dto);
  1493. dto.setActattendanceDate(actattendanceDate);
  1494. dto.setActretreatDate(actretreatDate);
  1495. //如果是通过页面编辑调用的该方法, 将实际打卡时间修改为页面填写的时间
  1496. if (oConvertUtils.isNotEmpty(detailEntity)) {
  1497. dto.setActattendanceDate(detailEntity.getAttendanceDate());
  1498. //如果用户选择的结束时间为空, 在dto 中设置结束时间等于开始时间 便于dto相关计算
  1499. Date retreatDate =detailEntity.getRetreatDate();
  1500. if (null==retreatDate) {
  1501. retreatDate = detailEntity.getAttendanceDate();
  1502. }
  1503. dto.setActretreatDate(retreatDate);
  1504. }else if(currDateAdjustEntity != null) {
  1505. dto.setPrimevalAttendanceDate(actattendanceDate);
  1506. dto.setPrimevalRetreatDate(actretreatDate);
  1507. dto.setActattendanceDate(currDateAdjustEntity.getAttendanceDate());
  1508. dto.setActretreatDate(currDateAdjustEntity.getRetreatDate());
  1509. }
  1510. // 值班天数 计算当月的班次中有值班时间的天数 累8计当前月的有值班时间的天数 值班按次计算,只要有实际出勤记录我们就计做一次值班;
  1511. Date ondutyStarttime = dto.getOndutyStarttime();
  1512. Date ondutyEndtime = dto.getOndutyEndtime();
  1513. if (oConvertUtils.isNotEmpty(ondutyStarttime)&&oConvertUtils.isNotEmpty(ondutyEndtime)) {
  1514. // for (int i = 0; i < dingAttendanceinfoEntities.size(); i++) {
  1515. // DingAttendanceinfoEntity dingAttendanceinfoEntity = dingAttendanceinfoEntities
  1516. // .get(i);
  1517. // Date temp = dingAttendanceinfoEntity.getAttendanceTime();
  1518. // if (oConvertUtils.isNotEmpty(temp)
  1519. // &&temp.compareTo(ondutyEndtime) <=0
  1520. // && (temp.compareTo(ondutyStarttime) >= 0)) {
  1521. // dto.setIhadDuty(true);
  1522. // break;
  1523. // }
  1524. // }
  1525. // 默认全勤处理加班
  1526. if(hasSpecialAttendInfo) {
  1527. dto.setIhadDuty(true);
  1528. }
  1529. // 根据出勤时间和退勤时间计算值班是否有效,原因是出勤时间和退勤时间可能是手动修改后的结果 zy 20180425
  1530. if (oConvertUtils.isNotEmpty(dto.getActattendanceDate())
  1531. && dto.getActattendanceDate().compareTo(ondutyEndtime) <=0
  1532. && (dto.getActattendanceDate().compareTo(ondutyStarttime) >= 0)) {
  1533. dto.setIhadDuty(true);
  1534. }
  1535. if (oConvertUtils.isNotEmpty(dto.getActretreatDate())
  1536. && dto.getActretreatDate().compareTo(ondutyEndtime) <=0
  1537. && (dto.getActretreatDate().compareTo(ondutyStarttime) >= 0)) {
  1538. dto.setIhadDuty(true);
  1539. }
  1540. }
  1541. // =====查询加班情况
  1542. List<OvertimeRecordEntity> overtimeRecordEntities =dto.getOvertimeRecordEntities();
  1543. if (!ListUtils.isNullOrEmpty(overtimeRecordEntities)) {
  1544. for (OvertimeRecordEntity entry:overtimeRecordEntities) {
  1545. //额外加班 餐补次数,需要 考虑 加班备案申请里 的 是否 提供餐补。 否 的时候,不能计入次数。
  1546. //只要有加班记录 就记作额外加班一次
  1547. //del-->如果有加班备案 且这个加班备案不是法定加班 校验在这个区间内是否有打卡记录 如果有 则 额外加班记一次 "0".equals(entry.getIfnational())
  1548. if ("1".equals(oConvertUtils.getString(entry.getIfmeal()))) {
  1549. dto.setExtraOvertime(1);
  1550. }
  1551. /*if (true) {
  1552. *//**加班开始时间*//*
  1553. Date overtimeStime = entry.getOvertimeStime();
  1554. *//**加班结束时间*//*
  1555. Date overtimeEtime= entry.getOvertimeEtime();
  1556. for (int i = 0; i < dingAttendanceinfoEntities.size(); i++) {
  1557. DingAttendanceinfoEntity dingAttendanceinfoEntity = dingAttendanceinfoEntities
  1558. .get(i);
  1559. Date temp = dingAttendanceinfoEntity.getAttendanceTime();
  1560. if (oConvertUtils.isNotEmpty(temp)
  1561. &&temp.compareTo(overtimeEtime) <=0
  1562. && (temp.compareTo(overtimeStime) >= 0)) {
  1563. //额外加班 餐补次数,需要 考虑 加班备案申请里 的 是否 提供餐补。 否 的时候,不能计入次数。
  1564. if ("1".equals(oConvertUtils.getString(entry.getIfmeal()))) {
  1565. dto.setExtraOvertime(1);
  1566. }
  1567. break;
  1568. }
  1569. }
  1570. //如果钉钉原始打卡记录为空, 在判断编辑页传入的开始打卡时间 和结束打卡时间 是否满足额外加班条件
  1571. if (ListUtils.isNullOrEmpty(dingAttendanceinfoEntities)) {
  1572. List<Date> tempdates = new ArrayList<Date>();
  1573. tempdates.add(dto.getActattendanceDate());
  1574. tempdates.add(dto.getActretreatDate());
  1575. for (int i = 0; i < tempdates.size(); i++) {
  1576. Date temp = tempdates.get(i);
  1577. if (oConvertUtils.isNotEmpty(temp)
  1578. &&temp.compareTo(overtimeEtime) <=0
  1579. && (temp.compareTo(overtimeStime) >= 0)) {
  1580. //额外加班 餐补次数,需要 考虑 加班备案申请里 的 是否 提供餐补。 否 的时候,不能计入次数。
  1581. if ("1".equals(oConvertUtils.getString(entry.getIfmeal()))) {
  1582. dto.setExtraOvertime(1);
  1583. }
  1584. break;
  1585. }
  1586. }
  1587. }
  1588. }*/
  1589. }
  1590. }
  1591. }
  1592. /**
  1593. * 判断上一天是否为夜班 是夜班为true 其他为false
  1594. * @author hualong.zhao
  1595. * @date 2017-12-5
  1596. * @param dto
  1597. * @param uatdlist
  1598. * @return
  1599. */
  1600. private boolean checkYesterdaytype(UserAttendanceDetailDto dto,
  1601. List<UserAttendanceDetailDto> uatdlist) {
  1602. boolean result = true;
  1603. for (int i = 0; i < uatdlist.size(); i++) {
  1604. UserAttendanceDetailDto tdto = uatdlist.get(i);
  1605. UserAttendanceDetailDto ydto = uatdlist.get(i);
  1606. if (tdto.getYmdDate().equals(dto.getYmdDate())) {
  1607. ydto = uatdlist.get(Math.max(0, i-1));
  1608. if (Globals.DUTYTYPE_yeban115.equals(oConvertUtils.getString(ydto.getDutyType()))) {
  1609. result = true;
  1610. }else {
  1611. result = false;
  1612. }
  1613. if (i==0) {
  1614. Date yesterday = getexactDate(dto.getYmdDate(), "00:00", -1, 0);
  1615. //月度首日 需要查询上一个月的最后一天 是否为夜班
  1616. List<UserAttendanceDetailDto> yestoryday = userAttendanceDetailDao.
  1617. getlistbyProjarrangeDetailid(null,dto.getUserid(),DataUtils.date2Str(yesterday, DataUtils.date_sdf));
  1618. if (!ListUtils.isNullOrEmpty(yestoryday)) {
  1619. ydto = yestoryday.get(0);
  1620. if (Globals.DUTYTYPE_yeban115.equals(oConvertUtils.getString(ydto.getDutyType()))) {
  1621. result = true;
  1622. }else {
  1623. result = false;
  1624. }
  1625. }
  1626. }
  1627. }
  1628. }
  1629. return result;
  1630. }
  1631. /**
  1632. * 获取有效结束打卡时间
  1633. *
  1634. *
  1635. * 如果是夜班,跨天的情况: 考勤机记录的本日后一天的认可范围内最晚刷卡时间,例如:7:30; 否则为 考勤机记录的本日最晚刷卡时间,例如:19:50
  1636. *
  1637. * 要考虑是否有连续加班或值班的情况,如果排班中的“正常工作下班时间”>=“加班或值班开始时间”,退勤时间为最晚的打卡时间;
  1638. * 否则为正常打卡结束时间范围内的最后时间; 要考虑夜班跨自然日的情况;
  1639. *
  1640. *
  1641. * 如果值班/加班 和正常工作时间没有连续 则查询有效结束打卡时间 之前的最后一次打卡时间
  1642. * 如果值班/加班 和正常工作时间连续了 则 先查询 有效结束打卡时间 的最新一次打卡, 如果这个时间没有, 则查询值班/加班 结束时间之前的最后一次打卡
  1643. *
  1644. *
  1645. * @author hualong.zhao
  1646. * @date 2017-11-23
  1647. * @param dto
  1648. * @return
  1649. */
  1650. private Date calculateEffectiveAttendanceEtime(UserAttendanceDetailDto dto) {
  1651. Date effectiveEnddate = dto.getYmdDate();
  1652. // 获取正常上班时间
  1653. String normalworkStime = oConvertUtils.getString(dto
  1654. .getNormalworkStime());
  1655. if (oConvertUtils.isEmpty(normalworkStime)) {
  1656. String dutyType = oConvertUtils.getString(dto.getDutyType());
  1657. if (Globals.DUTYTYPE_jiaban.equals(dutyType)||Globals.DUTYTYPE_zhiban.equals(dutyType)) {
  1658. normalworkStime = "00:00";
  1659. }
  1660. }
  1661. // 获取正常下班时间
  1662. String normalworkEtime = oConvertUtils.getString(dto
  1663. .getNormalworkEtime());
  1664. if (oConvertUtils.isEmpty(normalworkEtime)) {
  1665. String dutyType = oConvertUtils.getString(dto.getDutyType());
  1666. if (Globals.DUTYTYPE_jiaban.equals(dutyType)||Globals.DUTYTYPE_zhiban.equals(dutyType)) {
  1667. normalworkEtime = "23:59";
  1668. }else{
  1669. // 当他休息的时候
  1670. //计算加班的时候的实际出勤时间
  1671. return null;
  1672. }
  1673. }
  1674. Integer t1flag = 0;
  1675. if (oConvertUtils.isNotEmpty(normalworkEtime)
  1676. && oConvertUtils.isNotEmpty(normalworkStime)) {
  1677. t1flag = normalworkEtime.compareTo(normalworkStime) < 0 ? 1 : 0;
  1678. if (Globals.DUTYTYPE_yeban115.equals(oConvertUtils.getString(dto.getDutyType()))) {
  1679. t1flag = 1;
  1680. }
  1681. Integer epunchMinute = oConvertUtils.getInt(dto.getEpunchMinute(),
  1682. 0);
  1683. effectiveEnddate = getexactDate(dto.getYmdDate(), normalworkEtime,
  1684. t1flag, 0 + epunchMinute);
  1685. }
  1686. // 值班开始时间
  1687. String ondutyStime = oConvertUtils.getString(dto.getOndutyStime());
  1688. if (oConvertUtils.isNotEmpty(ondutyStime)) {
  1689. // 获取值班 的开始时间
  1690. Date ondutyStarttime = getexactDate(dto.getYmdDate(), ondutyStime, t1flag,0);
  1691. dto.setOndutyStarttime(ondutyStarttime);
  1692. }
  1693. //值班结束时间
  1694. String mondutyEtime = oConvertUtils.getString(dto.getOndutyEtime());
  1695. if (oConvertUtils.isNotEmpty(mondutyEtime)) {
  1696. // 获取值班 的结束时间
  1697. if (mondutyEtime.compareTo(ondutyStime)<0) {
  1698. Date ondutyEndtime = getexactDate(dto.getYmdDate(), mondutyEtime, t1flag+1,0);
  1699. dto.setOndutyEndtime(ondutyEndtime);
  1700. }else {
  1701. Date ondutyEndtime = getexactDate(dto.getYmdDate(), mondutyEtime, t1flag,0);
  1702. dto.setOndutyEndtime(ondutyEndtime);
  1703. }
  1704. }
  1705. // 加班开始时间
  1706. String timeOutOvertimeStime = oConvertUtils.getString(dto
  1707. .getTimeOutOvertimeStime());
  1708. Date overtimeStartdate = null;
  1709. if (oConvertUtils.isNotEmpty(timeOutOvertimeStime)) {
  1710. // 加班开始时间date
  1711. overtimeStartdate = getexactDate(dto.getYmdDate(), timeOutOvertimeStime, t1flag,0);
  1712. }
  1713. // 加班结束时间
  1714. String timeOutOvertimeEtime = oConvertUtils.getString(dto
  1715. .getTimeOutOvertimeEtime());
  1716. Date overtimeEnddate = null;
  1717. if (oConvertUtils.isNotEmpty(timeOutOvertimeEtime)) {
  1718. // 加班结束时间date
  1719. if (timeOutOvertimeEtime.compareTo(timeOutOvertimeStime)<0) {
  1720. overtimeEnddate = getexactDate(dto.getYmdDate(), timeOutOvertimeEtime, t1flag+1,0);
  1721. }else {
  1722. overtimeEnddate = getexactDate(dto.getYmdDate(), timeOutOvertimeEtime, t1flag,0);
  1723. }
  1724. }
  1725. // 最早加班/值班开始时间
  1726. Date jiabanstartDate = null;
  1727. Date jiabanendDate = null;
  1728. //如果值班时间不为空 则将此值置为值班时间
  1729. if (oConvertUtils.isNotEmpty(dto.getOndutyStarttime())) {
  1730. jiabanstartDate = dto.getOndutyStarttime();
  1731. jiabanendDate = dto.getOndutyEndtime();
  1732. }
  1733. //如果加班时间不为空 则将此值置为加班时间
  1734. if (oConvertUtils.isNotEmpty(overtimeStartdate)) {
  1735. jiabanstartDate = overtimeStartdate;
  1736. jiabanendDate = overtimeEnddate;
  1737. }
  1738. if (oConvertUtils.isNotEmpty(dto.getOndutyStarttime())&&oConvertUtils.isNotEmpty(overtimeStartdate)) {
  1739. jiabanstartDate = (dto.getOndutyStarttime().after(overtimeStartdate))?overtimeStartdate:dto.getOndutyStarttime();
  1740. jiabanendDate = (dto.getOndutyStarttime().after(overtimeStartdate))?overtimeEnddate:dto.getOndutyEndtime();
  1741. }
  1742. if (oConvertUtils.isNotEmpty(jiabanstartDate)
  1743. &&(oConvertUtils.isNotEmpty(jiabanendDate))
  1744. && (jiabanstartDate.compareTo(effectiveEnddate) <= 0)) {
  1745. effectiveEnddate = jiabanendDate;
  1746. dto.setJiabanContinuous(true);
  1747. } else {
  1748. dto.setJiabanContinuous(false);
  1749. }
  1750. // ----------值班情况处理 ---20180308---yangxi---add---start----------
  1751. if(Globals.DUTYTYPE_zhiban.equals(dto.getDutyType())) {
  1752. effectiveEnddate = dto.getOndutyEndtime();
  1753. }
  1754. // ----------值班情况处理 ---20180308---yangxi---add---end----------
  1755. // 有效结束打卡时间应该为59秒
  1756. Calendar calendar = Calendar.getInstance();
  1757. calendar.setTime(effectiveEnddate);
  1758. calendar.add(Calendar.SECOND, 59);
  1759. return calendar.getTime();
  1760. }
  1761. /**
  1762. *
  1763. * @author hualong.zhao
  1764. * @date 2017-11-23
  1765. * @param ymdDate
  1766. * 由年月日获取的Date类型的时间 基准时间
  1767. * @param time
  1768. * 小时:分钟
  1769. * @param t1
  1770. * 是否加一天
  1771. * @param addmins
  1772. * 时间波动
  1773. * @return
  1774. */
  1775. private Date getexactDate(Date ymdDate, String time, int t1, int addmins) {
  1776. Calendar effectivecal = Calendar.getInstance();
  1777. effectivecal.setTime(ymdDate);
  1778. if (oConvertUtils.isNotEmpty(time)) {
  1779. String[] temp = time.split(":");
  1780. // 将正常上班时间 设定至 时间戳上
  1781. effectivecal.set(Calendar.HOUR_OF_DAY, Integer.valueOf(temp[0]));
  1782. effectivecal.set(Calendar.MINUTE, Integer.valueOf(temp[1]));
  1783. }
  1784. effectivecal.add(Calendar.DATE, t1);
  1785. // 开始打卡分钟数
  1786. if (oConvertUtils.isNotEmpty(addmins)) {
  1787. effectivecal.add(Calendar.MINUTE, addmins);
  1788. }
  1789. return effectivecal.getTime();
  1790. }
  1791. /**
  1792. * 获取有效开始打卡时间
  1793. *
  1794. * 考勤机记录的本日认可范围内最早刷卡时间,例如:7:32
  1795. *
  1796. * @author hualong.zhao
  1797. * @date 2017-11-23
  1798. * @param dto
  1799. * @return
  1800. */
  1801. private Date calculateEffectiveAttendanceStime(UserAttendanceDetailDto dto) {
  1802. // 获取正常上班时间
  1803. String normalworkStime = oConvertUtils.getString(dto
  1804. .getNormalworkStime());
  1805. Date normalworkStartdate = dto.getYmdDate();
  1806. if (oConvertUtils.isEmpty(normalworkStime)) {
  1807. String dutyType = oConvertUtils.getString(dto.getDutyType());
  1808. if (Globals.DUTYTYPE_jiaban.equals(dutyType)||Globals.DUTYTYPE_zhiban.equals(dutyType)) {
  1809. normalworkStime = "00:00";
  1810. } else {
  1811. return null;
  1812. }
  1813. }
  1814. if (oConvertUtils.isNotEmpty(normalworkStime)) {
  1815. int spunchMinute = oConvertUtils.getInt(dto.getSpunchMinute(), 0);
  1816. normalworkStartdate = getexactDate(dto.getYmdDate(),
  1817. normalworkStime, 0, 0 - spunchMinute);
  1818. }
  1819. // ----------值班情况处理 ---20180308---yangxi---add---start----------
  1820. if(Globals.DUTYTYPE_zhiban.equals(dto.getDutyType())) {
  1821. normalworkStartdate = getexactDate(dto.getYmdDate(), dto.getOndutyStime(), 0, 0);
  1822. }
  1823. // ----------值班情况处理 ---20180308---yangxi---add---end----------
  1824. return normalworkStartdate;
  1825. }
  1826. /**
  1827. * 包括: 正常、法定假日、带薪假、病假、事假、婚假、丧假、陪产假; “正常”、“法定假日”按照每年的法定节假日信息设定并校验;
  1828. * 其他假期,需要根据已经确认的“休假申请”中日期及休假类型设定并校验;
  1829. *
  1830. * @author hualong.zhao
  1831. * @date 2017-11-23
  1832. * @param dto
  1833. * @return
  1834. */
  1835. private void calculateCurdateStatus(UserAttendanceDetailDto dto) {
  1836. String curdateStatus = Globals.ATTENDANCE_STATUS_EDIT_10;
  1837. // 当这一天为法定假日时 ,切这一天该员工有排班。 则认定为该员工为正常上班。可手动调整为法定假日。
  1838. List<HolidayEntity> userHolidayEntities = dto.getUserHolidayEntities();
  1839. if (!ListUtils.isNullOrEmpty(userHolidayEntities)) {
  1840. curdateStatus = userHolidayEntities.get(0).getHolidayType();
  1841. }
  1842. dto.setCurdateStatus(curdateStatus);
  1843. }
  1844. /**
  1845. * 检查某人某天是否有 固定周期临时借调
  1846. *
  1847. * @author hualong.zhao
  1848. * @date 2017-11-23
  1849. * @param dto
  1850. * @param snapRegularborrowEntities
  1851. */
  1852. private void checkIshavesnapRegularborrows(UserAttendanceDetailDto dto,
  1853. List<SnapRegularborrowEntity> snapRegularborrowEntities) {
  1854. Date curdate = dto.getYmdDate();
  1855. List<SnapRegularborrowEntity> uSingleborrowEntities = dto
  1856. .getSnapRegularborrowEntities();
  1857. // 遍历本月固定周期临时借调,
  1858. for (SnapRegularborrowEntity snapRegularborrowEntity : snapRegularborrowEntities) {
  1859. Date inTime = snapRegularborrowEntity.getInTime();
  1860. Date deadDate = snapRegularborrowEntity.getDeadDate();
  1861. // 如果当前时间在固定周期临时调度范围内
  1862. if (oConvertUtils.isNotEmpty(inTime)
  1863. && oConvertUtils.isNotEmpty(deadDate)
  1864. && (inTime.compareTo(curdate) <= 0 && curdate
  1865. .compareTo(deadDate) <= 0)) {
  1866. // 当天在固定周期的 调入日期 和终止日期之间
  1867. String fixedCycle = oConvertUtils
  1868. .getString(snapRegularborrowEntity.getFixedCycle());
  1869. // 固定周期内有这一天 星期N = 星期N
  1870. if (fixedCycle.contains(dto.getWeek())) {
  1871. uSingleborrowEntities.add(snapRegularborrowEntity);
  1872. }
  1873. }
  1874. }
  1875. dto.setSnapRegularborrowEntities(uSingleborrowEntities);
  1876. }
  1877. /**
  1878. * 检查某人某天是否有单次临时借调
  1879. *
  1880. * @author hualong.zhao
  1881. * @date 2017-11-23
  1882. * @param dto
  1883. * @param snapSingleborrowEntities
  1884. */
  1885. private void checkIshavesnapSingleborrows(UserAttendanceDetailDto dto,
  1886. List<SnapSingleborrowEntity> snapSingleborrowEntities) {
  1887. Date curdate = dto.getYmdDate();
  1888. List<SnapSingleborrowEntity> uSingleborrowEntities = dto
  1889. .getSnapSingleborrowEntities();
  1890. // 遍历本月单次临时借调,
  1891. for (SnapSingleborrowEntity snapSingleborrowEntity : snapSingleborrowEntities) {
  1892. Date inTime = snapSingleborrowEntity.getInTime();
  1893. Date deadDate = snapSingleborrowEntity.getDeadDate();
  1894. if (inTime.equals(curdate)
  1895. || (inTime.before(curdate) && curdate.before(deadDate))
  1896. || (deadDate.equals(curdate))) {
  1897. uSingleborrowEntities.add(snapSingleborrowEntity);
  1898. }
  1899. }
  1900. dto.setSnapSingleborrowEntities(uSingleborrowEntities);
  1901. }
  1902. /**
  1903. * 检查某人某天是否有加班备案记录
  1904. *
  1905. * @author hualong.zhao
  1906. * @date 2017-11-23
  1907. * @param dto
  1908. * @param overtimeRecordEntities
  1909. */
  1910. private void checkIshaveovertimeRecord(UserAttendanceDetailDto dto,
  1911. List<OvertimeRecordEntity> overtimeRecordEntities) {
  1912. Date curdate = dto.getYmdDate();
  1913. Calendar calendar = Calendar.getInstance();
  1914. calendar.setTime(curdate);
  1915. calendar.add(Calendar.DATE, 1);
  1916. Date tomDate = calendar.getTime();
  1917. List<OvertimeRecordEntity> uOvertimeRecordEntities = dto
  1918. .getOvertimeRecordEntities();
  1919. // 遍历本月的加班记录,
  1920. for (OvertimeRecordEntity overtimeRecordEntity : overtimeRecordEntities) {
  1921. Date stime = overtimeRecordEntity.getOvertimeStime();
  1922. // 如果加班开始时间在这一天内
  1923. if (oConvertUtils.isNotEmpty(stime) && curdate.compareTo(stime)<=0
  1924. && stime.compareTo(tomDate)<=0) {
  1925. // 将这一天的加班信息 记录至该天中
  1926. uOvertimeRecordEntities.add(overtimeRecordEntity);
  1927. }
  1928. }
  1929. dto.setOvertimeRecordEntities(uOvertimeRecordEntities);
  1930. }
  1931. /**
  1932. * 检查这一天是否有过请假
  1933. *
  1934. * @author hualong.zhao
  1935. * @date 2017-11-23
  1936. * @param dto
  1937. * @param userHolidayEntities
  1938. */
  1939. private void checkIshaveHolidaies(UserAttendanceDetailDto dto,
  1940. List<HolidayEntity> userHolidayEntities) {
  1941. //获取有效开始打卡时间
  1942. Date effectiveStime =dto.getEffectiveStime();
  1943. if (oConvertUtils.isEmpty(effectiveStime)) {
  1944. effectiveStime = dto.getYmdDate();
  1945. }
  1946. //获取有效结束打卡时间
  1947. Date effectiveEtime = dto.getEffectiveEtime();
  1948. if (oConvertUtils.isEmpty(effectiveEtime)) {
  1949. effectiveEtime = getexactDate(dto.getYmdDate(), "23:59",0, 0);
  1950. }
  1951. List<HolidayEntity> uHolidayEntities = new ArrayList<HolidayEntity>();
  1952. // 遍历本月的请假记录,
  1953. for (HolidayEntity holidayEntity : userHolidayEntities) {
  1954. Date startdate = holidayEntity.getHolidayStime();
  1955. Date enddate = holidayEntity.getHolidayEtime();
  1956. // 如果请假开始日期是当天 或者是在当天之前 且 结束日期是当天或当天之后, 则这一天为请假日期
  1957. if (oConvertUtils.isEmpty(startdate)||oConvertUtils.isEmpty(enddate)) {
  1958. //如果开始时间或者是结束时间为空 则认定为该数据为脏数据
  1959. continue;
  1960. }
  1961. // 当请假类型是病假和事假以外的情况
  1962. // 杨曦 20180417
  1963. if(!Globals.REST_TYPE_0.equals(holidayEntity.getHolidayType()) && !Globals.REST_TYPE_1.equals(holidayEntity.getHolidayType())) {
  1964. // 如果跨天,将有效打卡时间设置成前一天的23:59:59
  1965. SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
  1966. if(dateFormat.format(effectiveEtime).compareTo(dateFormat.format(effectiveStime)) > 0) {
  1967. Calendar cal = Calendar.getInstance();
  1968. cal.setTime(effectiveEtime);
  1969. cal.add(Calendar.DATE, -1);
  1970. cal.set(Calendar.HOUR_OF_DAY, 23);//时
  1971. cal.set(Calendar.MINUTE, 59);//分
  1972. cal.set(Calendar.SECOND, 59);//秒
  1973. effectiveEtime = cal.getTime();
  1974. }
  1975. }
  1976. if (effectiveStime.compareTo(enddate)<=0&&effectiveEtime.compareTo(startdate)>=0) {
  1977. // 将这一天的请假信息 记录至该天中
  1978. uHolidayEntities.add(holidayEntity);
  1979. }
  1980. }
  1981. dto.setUserHolidayEntities(uHolidayEntities);
  1982. }
  1983. private List<UserAttendanceDetailDto> getallUsefulFieldWithCache(HashMap<String, HashMap<String, Object>> hm_cache, UserAttendanceTotalEntity userAttendanceTotalEntity) throws Exception{
  1984. List<UserAttendanceDetailDto> uatdlist = new ArrayList<UserAttendanceDetailDto>();
  1985. List<UserAttendanceDetailDto> updatelist = new ArrayList<UserAttendanceDetailDto>();
  1986. String yearmonth = userAttendanceTotalEntity.getYearmonth();
  1987. String userid = userAttendanceTotalEntity.getUserId();
  1988. List<ProjarrangeDetailEntity> projarrangeDetailEntities = getUserProjarrangeDetailEntityWithCache(hm_cache, userid, yearmonth);
  1989. ArrayList<UserAttendanceDetailEntity> attendanceDetailEntities = new ArrayList<UserAttendanceDetailEntity>();
  1990. if (!ListUtils.isNullOrEmpty(projarrangeDetailEntities)) {
  1991. ProjarrangeDetailEntity projarrangeDetailEntity = projarrangeDetailEntities.get(0);
  1992. {
  1993. // 当前月无详细考勤记录数据
  1994. // 查询当前月的排班记录。
  1995. String ymddateString = null;
  1996. uatdlist = getlistbyProjarrangeDetailidWithCache(hm_cache, projarrangeDetailEntity.getId(), ymddateString);
  1997. // =====查询请假情况
  1998. List<HolidayEntity> userHolidayEntities = getUserHolidayEntitiesWithCache(hm_cache, userid, yearmonth);
  1999. // =====查询加班情况
  2000. List<OvertimeRecordEntity> overtimeRecordEntities = getOvertimeRecordEntitiesWithCache(hm_cache, userid, yearmonth);
  2001. // =====查询调度情况
  2002. // 01 临时借调(单次)申请表
  2003. List<SnapSingleborrowEntity> snapSingleborrowEntities = getSnapSingleborrowEntitiesWithCache(hm_cache, userid, yearmonth);
  2004. // 02 临时借调(固定周期)申请表
  2005. List<SnapRegularborrowEntity> snapRegularborrowEntities = getSnapRegularborrowEntitiesWithCache(hm_cache, userid, yearmonth);
  2006. //餐费补贴
  2007. List<MealsSubsidyEntity> mealsSubsidyEntities = getMealsSubsidyEntitiesWithCache(hm_cache);
  2008. //餐费扣除标准
  2009. List<MealsDeductEntity> mealsDeductEntities= getMealsDeductEntitiesWithCache(hm_cache);
  2010. //特殊考勤-手工考勤(默认全勤)的员工
  2011. List<TBusSpecialAttendEntity> specialAttendEntities = getSpecialAttendEntitiesWithCache(hm_cache, userid);
  2012. HashMap<String,TBusSpecialAttendEntity> hm_specialAttendEntities = new HashMap<String,TBusSpecialAttendEntity>();
  2013. if(specialAttendEntities != null && !specialAttendEntities.isEmpty()) {
  2014. for(TBusSpecialAttendEntity spe : specialAttendEntities) {
  2015. hm_specialAttendEntities.put(spe.getUserid(), spe);
  2016. }
  2017. }
  2018. if (!ListUtils.isNullOrEmpty(uatdlist)) {
  2019. for (UserAttendanceDetailDto dto : uatdlist) {
  2020. UserAttendanceDetailEntity detailEntity = getUserAttendanceDetailEntityfromList(dto,attendanceDetailEntities);
  2021. if ((!ListUtils.isNullOrEmpty(attendanceDetailEntities))&&null==detailEntity) {
  2022. continue;
  2023. }
  2024. dto.setUserid(userid);
  2025. dto.setAttendanceId(userAttendanceTotalEntity.getId());
  2026. if (oConvertUtils.isNotEmpty(dto.getYmdDate())) {
  2027. if (!ListUtils.isNullOrEmpty(overtimeRecordEntities)) {
  2028. checkIshaveovertimeRecord(dto,
  2029. overtimeRecordEntities);
  2030. }
  2031. if (!ListUtils.isNullOrEmpty(snapSingleborrowEntities)) {
  2032. checkIshavesnapSingleborrows(dto,
  2033. snapSingleborrowEntities);
  2034. }
  2035. if (!ListUtils.isNullOrEmpty(snapRegularborrowEntities)) {
  2036. checkIshavesnapRegularborrows(dto,
  2037. snapRegularborrowEntities);
  2038. }
  2039. //将某人某天的餐费补贴 信息 添加至dto 中
  2040. if (!ListUtils.isNullOrEmpty(mealsSubsidyEntities)) {
  2041. checkIshavemealsSubsidyEntities(dto,
  2042. mealsSubsidyEntities);
  2043. }
  2044. //将某人某天的餐费补贴 的餐费扣除标准 添加至dto 中
  2045. if (!ListUtils.isNullOrEmpty(mealsDeductEntities)) {
  2046. dto.setMealsDeductEntities(mealsDeductEntities);
  2047. }
  2048. }
  2049. //获取有效开始打卡时间
  2050. Date effectiveStime = calculateEffectiveAttendanceStime(dto);
  2051. dto.setEffectiveStime(effectiveStime);
  2052. //获取有效结束打卡时间
  2053. Date effectiveEtime = calculateEffectiveAttendanceEtime(dto);
  2054. dto.setEffectiveEtime(effectiveEtime);
  2055. if (!ListUtils.isNullOrEmpty(userHolidayEntities)) {
  2056. checkIshaveHolidaies(dto, userHolidayEntities);
  2057. }
  2058. // 获取当前状态;
  2059. calculateCurdateStatus(dto);
  2060. // 获取某人某天在某排班情况下的考勤记录
  2061. List<DingAttendanceinfoEntity> dingAttendanceinfoEntities = getDingAttendanceinfoEntitiesWithCache(hm_cache,dto);
  2062. Collections.sort(dingAttendanceinfoEntities);
  2063. // dingAttendanceinfoService
  2064. // .getDingAttendanceinfoEntities(dto);
  2065. List<UserAttendanceDetailAdjustedEntity> adjustedEntities = getAdjustedAttendEntitiesWithCache(hm_cache, dto);
  2066. // if("ff80808165eb2f2d01660e8b01f94905".equals(dto.getUserid())) {
  2067. // System.out.println("wu");
  2068. // }
  2069. calculateActAttendancetime(dto, dingAttendanceinfoEntities, adjustedEntities, uatdlist,detailEntity);
  2070. //设置基准时间
  2071. calculateDatumDate(hm_cache,dto);
  2072. // 获取实际出勤时间
  2073. calculateActualAttendanceDate(dto);
  2074. // 获取时间差值
  2075. calculateActualtimeDifference(dto);
  2076. // 获取借调信息
  2077. calculateBorrowsInfo(dto);
  2078. //获取迟到/早退/旷工信息
  2079. calculateBelateAndLeaveEarlyAndabsenteeism(dto);
  2080. //获取加班信息
  2081. calculateOvertime(hm_cache,dto,userAttendanceTotalEntity);
  2082. //计算各种津贴
  2083. calculateSubsidy(dto);
  2084. if (oConvertUtils.isNotEmpty(detailEntity)) {
  2085. updatelist.add(dto);
  2086. }
  2087. }
  2088. } else {
  2089. // 当前人员本月份排班列表为空
  2090. }
  2091. }
  2092. }
  2093. if (!ListUtils.isNullOrEmpty(attendanceDetailEntities)) {
  2094. return updatelist ;
  2095. }else {
  2096. return uatdlist;
  2097. }
  2098. }
  2099. /**
  2100. * @param hm_cache
  2101. * @param userid
  2102. * @return
  2103. */
  2104. private List<UserAttendanceDetailAdjustedEntity> getAdjustedAttendEntitiesWithCache(
  2105. HashMap<String, HashMap<String, Object>> hm_cache,UserAttendanceDetailDto dto) {
  2106. HashMap<String, Object> hm = hm_cache.get("getAdjustedAttendEntitiesWithCache");
  2107. Date curdate = dto.getYmdDate();
  2108. String strDateFormat = "yyyy-MM";
  2109. SimpleDateFormat sdf = new SimpleDateFormat(strDateFormat);
  2110. List<UserAttendanceDetailAdjustedEntity> list = null;
  2111. if(hm == null) {
  2112. hm = new HashMap<>();
  2113. hm_cache.put("getAdjustedAttendEntitiesWithCache", hm);
  2114. String hql = "from UserAttendanceDetailAdjustedEntity where ymd_date like '" +sdf.format(curdate)+"%'";
  2115. List<UserAttendanceDetailAdjustedEntity> entitiesFromDB = findHql(hql);
  2116. for(UserAttendanceDetailAdjustedEntity entity : entitiesFromDB) {
  2117. String userInEntity = entity.getUserId();
  2118. if(hm.containsKey(userInEntity)) {
  2119. List<UserAttendanceDetailAdjustedEntity> entitylist = (List<UserAttendanceDetailAdjustedEntity>)hm.get(userInEntity);
  2120. entitylist.add(entity);
  2121. }else {
  2122. List<UserAttendanceDetailAdjustedEntity> newlist = new ArrayList<>();
  2123. newlist.add(entity);
  2124. hm.put(userInEntity, newlist);
  2125. }
  2126. }
  2127. }
  2128. return (List<UserAttendanceDetailAdjustedEntity>)hm.get(dto.getUserid());
  2129. }
  2130. /**
  2131. * @param hm_cache
  2132. * @param ymddateString
  2133. * @param ymddateString2
  2134. * @return
  2135. */
  2136. private List<UserAttendanceDetailDto> getlistbyProjarrangeDetailidWithCache(
  2137. HashMap<String, HashMap<String, Object>> hm_cache, String projarrangeDetailEntityId, String ymddateString) {
  2138. HashMap<String, Object> hm = hm_cache.get("getlistbyProjarrangeDetailidWithCache");
  2139. if(hm == null) {
  2140. hm = new HashMap<>();
  2141. hm_cache.put("getlistbyProjarrangeDetailidWithCache", hm);
  2142. List<UserAttendanceDetailDto> entitiesFromDB = userAttendanceDetailDao.getlistbyProjarrangeDetailid(null,null,ymddateString);
  2143. for(UserAttendanceDetailDto entity : entitiesFromDB) {
  2144. String id = entity.getProjarrangeDetailid();
  2145. if(hm.containsKey(id)) {
  2146. List<UserAttendanceDetailDto> entitylist = (List<UserAttendanceDetailDto>)hm.get(id);
  2147. entitylist.add(entity);
  2148. }else {
  2149. List<UserAttendanceDetailDto> newlist = new ArrayList<>();
  2150. newlist.add(entity);
  2151. hm.put(id, newlist);
  2152. }
  2153. }
  2154. }
  2155. return (List<UserAttendanceDetailDto>)hm.get(projarrangeDetailEntityId);
  2156. }
  2157. /**
  2158. * @param dto
  2159. * @return
  2160. */
  2161. private List<DingAttendanceinfoEntity> getDingAttendanceinfoEntitiesWithCache(HashMap<String, HashMap<String, Object>> hm_cache,UserAttendanceDetailDto dto) {
  2162. HashMap<String, Object> hm = hm_cache.get("getDingAttendanceinfoEntitiesWithCache");
  2163. Date curdate = dto.getYmdDate();
  2164. String strDateFormat = "yyyy-MM";
  2165. SimpleDateFormat sdf = new SimpleDateFormat(strDateFormat);
  2166. Calendar calendar = Calendar.getInstance();
  2167. calendar.setTime(curdate);
  2168. calendar.add(Calendar.DATE, 2);
  2169. Date tomdate = calendar.getTime();
  2170. if(hm == null) {
  2171. hm = new HashMap<>();
  2172. hm_cache.put("getDingAttendanceinfoEntitiesWithCache", hm);
  2173. CriteriaQuery cq = new CriteriaQuery(DingAttendanceinfoEntity.class);
  2174. cq.like("attendanceTime", sdf.format(curdate)+"%");
  2175. cq.add();
  2176. // cq.between("attendanceTime", curdate, tomdate);
  2177. // cq.add();
  2178. cq.addOrder("attendanceTime", SortDirection.asc);
  2179. String hql = "from DingAttendanceinfoEntity where attendanceTime like '" +sdf.format(curdate)+"%'";
  2180. List<DingAttendanceinfoEntity> entitiesFromDB = findHql(hql);
  2181. //getListByCriteriaQuery(cq, false);
  2182. for(DingAttendanceinfoEntity entity : entitiesFromDB) {
  2183. String userInEntity = entity.getUserId();
  2184. if(hm.containsKey(userInEntity)) {
  2185. List<DingAttendanceinfoEntity> entitylist = (List<DingAttendanceinfoEntity>)hm.get(userInEntity);
  2186. entitylist.add(entity);
  2187. }else {
  2188. List<DingAttendanceinfoEntity> newlist = new ArrayList<>();
  2189. newlist.add(entity);
  2190. hm.put(userInEntity, newlist);
  2191. }
  2192. }
  2193. }
  2194. List<DingAttendanceinfoEntity> allList = (List<DingAttendanceinfoEntity>)hm.get(dto.getUserid());
  2195. if(allList == null) {
  2196. return new ArrayList<DingAttendanceinfoEntity>();
  2197. }
  2198. List<DingAttendanceinfoEntity> selectList = new ArrayList<>();
  2199. for(DingAttendanceinfoEntity attInAll : allList) {
  2200. Date attendanceTime = attInAll.getAttendanceTime();
  2201. if(attendanceTime.after(curdate) && attendanceTime.before(tomdate)) {
  2202. selectList.add(attInAll);
  2203. }
  2204. }
  2205. return selectList;
  2206. }
  2207. /**
  2208. * @param hm_cache
  2209. * @return
  2210. */
  2211. private List<TBusSpecialAttendEntity> getSpecialAttendEntitiesWithCache(HashMap<String, HashMap<String, Object>> hm_cache,String userid) {
  2212. // TODO Auto-generated method stub
  2213. HashMap<String, Object> hm = hm_cache.get("getSpecialAttendEntitiesWithCache");
  2214. List<TBusSpecialAttendEntity> list = null;
  2215. if(hm == null) {
  2216. hm = new HashMap<>();
  2217. hm_cache.put("getSpecialAttendEntitiesWithCache", hm);
  2218. CriteriaQuery specialcq = new CriteriaQuery(TBusSpecialAttendEntity.class);
  2219. specialcq.eq("attendtype", Globals.Special_Attend_Type_All_IN);
  2220. specialcq.add();
  2221. List<TBusSpecialAttendEntity> entitiesFromDB = getListByCriteriaQuery(specialcq, false);
  2222. for(TBusSpecialAttendEntity entity : entitiesFromDB) {
  2223. String userInEntity = entity.getUserid();
  2224. if(hm.containsKey(userInEntity)) {
  2225. List<TBusSpecialAttendEntity> entitylist = (List<TBusSpecialAttendEntity>)hm.get(userInEntity);
  2226. entitylist.add(entity);
  2227. }else {
  2228. List<TBusSpecialAttendEntity> newlist = new ArrayList<>();
  2229. newlist.add(entity);
  2230. hm.put(userInEntity, newlist);
  2231. }
  2232. }
  2233. }
  2234. return (List<TBusSpecialAttendEntity>)hm.get(userid);
  2235. }
  2236. /**
  2237. * @param hm_cache
  2238. * @return
  2239. */
  2240. private List<MealsDeductEntity> getMealsDeductEntitiesWithCache(HashMap<String, HashMap<String, Object>> hm_cache) {
  2241. // TODO Auto-generated method stub
  2242. HashMap<String, Object> hm = hm_cache.get("getMealsDeductEntitiesWithCache");
  2243. List<MealsDeductEntity> list = null;
  2244. if(hm == null) {
  2245. hm = new HashMap<>();
  2246. hm_cache.put("getMealsDeductEntitiesWithCache", hm);
  2247. CriteriaQuery mdcq = new CriteriaQuery(MealsDeductEntity.class);
  2248. mdcq.eq("deleteFlag", "0");
  2249. mdcq.add();
  2250. mdcq.eq("status", "0");
  2251. mdcq.add();
  2252. List<MealsDeductEntity> entitiesFromDB = getListByCriteriaQuery(mdcq, false);
  2253. hm.put("ALL", entitiesFromDB);
  2254. }
  2255. return list = (List<MealsDeductEntity>)hm.get("ALL");
  2256. }
  2257. /**
  2258. * @param hm_cache
  2259. * @return
  2260. */
  2261. private List<MealsSubsidyEntity> getMealsSubsidyEntitiesWithCache(HashMap<String, HashMap<String, Object>> hm_cache) {
  2262. HashMap<String, Object> hm = hm_cache.get("getMealsSubsidyEntitiesWithCache");
  2263. List<MealsSubsidyEntity> list = null;
  2264. if(hm == null) {
  2265. hm = new HashMap<>();
  2266. hm_cache.put("getMealsSubsidyEntitiesWithCache", hm);
  2267. CriteriaQuery mscq = new CriteriaQuery(MealsSubsidyEntity.class);
  2268. mscq.eq("deleteFlag", "0");
  2269. mscq.add();
  2270. mscq.eq("status", "0");
  2271. mscq.add();
  2272. List<MealsSubsidyEntity> entitiesFromDB = getListByCriteriaQuery(mscq, false);
  2273. hm.put("ALL", entitiesFromDB);
  2274. }
  2275. return (List<MealsSubsidyEntity>)hm.get("ALL");
  2276. }
  2277. /**
  2278. * @param hm_cache
  2279. * @param userid
  2280. * @param yearmonth
  2281. * @return
  2282. * @throws Exception
  2283. */
  2284. private List<SnapRegularborrowEntity> getSnapRegularborrowEntitiesWithCache(
  2285. HashMap<String, HashMap<String, Object>> hm_cache, String userid, String yearmonth) throws Exception {
  2286. HashMap<String, Object> hm = hm_cache.get("getSnapRegularborrowEntitiesWithCache");
  2287. List<SnapRegularborrowEntity> list = null;
  2288. if(hm == null) {
  2289. hm = new HashMap<>();
  2290. hm_cache.put("getSnapRegularborrowEntitiesWithCache", hm);
  2291. CriteriaQuery cq = new CriteriaQuery(
  2292. SnapRegularborrowEntity.class);
  2293. cq.eq("yearmonth", yearmonth);
  2294. cq.add();
  2295. List<SnapRegularborrowEntity> entitiesFromDB = snapRegularborrowService
  2296. .getSnapRegularborrowEntities(null, yearmonth);
  2297. for(SnapRegularborrowEntity entity : entitiesFromDB) {
  2298. String userInEntity = entity.getUserid();
  2299. if(hm.containsKey(userInEntity)) {
  2300. List<SnapRegularborrowEntity> entitylist = (List<SnapRegularborrowEntity>)hm.get(userInEntity);
  2301. entitylist.add(entity);
  2302. }else {
  2303. List<SnapRegularborrowEntity> newlist = new ArrayList<>();
  2304. newlist.add(entity);
  2305. hm.put(userInEntity, newlist);
  2306. }
  2307. }
  2308. }
  2309. return (List<SnapRegularborrowEntity>)hm.get(userid);
  2310. }
  2311. /**
  2312. * @param hm_cache
  2313. * @param userid
  2314. * @param yearmonth
  2315. * @return
  2316. * @throws Exception
  2317. */
  2318. private List<SnapSingleborrowEntity> getSnapSingleborrowEntitiesWithCache(
  2319. HashMap<String, HashMap<String, Object>> hm_cache, String userid, String yearmonth) throws Exception {
  2320. HashMap<String, Object> hm = hm_cache.get("getSnapSingleborrowEntitiesWithCache");
  2321. List<SnapSingleborrowEntity> list = null;
  2322. if(hm == null) {
  2323. hm = new HashMap<>();
  2324. hm_cache.put("getSnapSingleborrowEntitiesWithCache", hm);
  2325. CriteriaQuery cq = new CriteriaQuery(
  2326. SnapSingleborrowEntity.class);
  2327. cq.eq("yearmonth", yearmonth);
  2328. cq.add();
  2329. List<SnapSingleborrowEntity> entitiesFromDB = snapSingleborrowService
  2330. .getSnapSingleborrowEntities(null, yearmonth);
  2331. for(SnapSingleborrowEntity entity : entitiesFromDB) {
  2332. String userInEntity = entity.getUserid();
  2333. if(hm.containsKey(userInEntity)) {
  2334. List<SnapSingleborrowEntity> entitylist = (List<SnapSingleborrowEntity>)hm.get(userInEntity);
  2335. entitylist.add(entity);
  2336. }else {
  2337. List<SnapSingleborrowEntity> newlist = new ArrayList<>();
  2338. newlist.add(entity);
  2339. hm.put(userInEntity, newlist);
  2340. }
  2341. }
  2342. }
  2343. return (List<SnapSingleborrowEntity>)hm.get(userid);
  2344. }
  2345. /**
  2346. * @param hm_cache
  2347. * @param userid
  2348. * @param yearmonth
  2349. * @return
  2350. * @throws Exception
  2351. */
  2352. private List<OvertimeRecordEntity> getOvertimeRecordEntitiesWithCache(
  2353. HashMap<String, HashMap<String, Object>> hm_cache, String userid, String yearmonth) throws Exception {
  2354. HashMap<String, Object> hm = hm_cache.get("getOvertimeRecordEntitiesWithCache");
  2355. List<OvertimeRecordEntity> list = null;
  2356. if(hm == null) {
  2357. hm = new HashMap<>();
  2358. hm_cache.put("getOvertimeRecordEntitiesWithCache", hm);
  2359. CriteriaQuery cq = new CriteriaQuery(
  2360. OvertimeRecordEntity.class);
  2361. cq.eq("yearmonth", yearmonth);
  2362. cq.add();
  2363. List<OvertimeRecordEntity> entitiesFromDB = overtimeRecordService.getOvertimeRecordEntities(null, yearmonth);
  2364. for(OvertimeRecordEntity entity : entitiesFromDB) {
  2365. String userInEntity = entity.getUserid();
  2366. if(hm.containsKey(userInEntity)) {
  2367. List<OvertimeRecordEntity> entitylist = (List<OvertimeRecordEntity>)hm.get(userInEntity);
  2368. entitylist.add(entity);
  2369. }else {
  2370. List<OvertimeRecordEntity> newlist = new ArrayList<>();
  2371. newlist.add(entity);
  2372. hm.put(userInEntity, newlist);
  2373. }
  2374. }
  2375. }
  2376. return (List<OvertimeRecordEntity>)hm.get(userid);
  2377. }
  2378. /**
  2379. * @param hm_cache
  2380. * @param userid
  2381. * @param yearmonth
  2382. * @return
  2383. * @throws Exception
  2384. */
  2385. private List<HolidayEntity> getUserHolidayEntitiesWithCache(HashMap<String, HashMap<String, Object>> hm_cache, String userid,
  2386. String yearmonth) throws Exception {
  2387. HashMap<String, Object> hm = hm_cache.get("getUserHolidayEntitiesWithCache");
  2388. if(hm == null) {
  2389. hm = new HashMap<>();
  2390. hm_cache.put("getUserHolidayEntitiesWithCache", hm);
  2391. List<HolidayEntity> userHolidayEntities = holidayService
  2392. .getUserHolidayEntities(null, yearmonth);
  2393. for(HolidayEntity entity : userHolidayEntities) {
  2394. String userInEntity = entity.getUserid();
  2395. if(hm.containsKey(userInEntity)) {
  2396. List<HolidayEntity> entitylist = (List<HolidayEntity>)hm.get(userInEntity);
  2397. entitylist.add(entity);
  2398. }else {
  2399. List<HolidayEntity> newlist = new ArrayList<>();
  2400. newlist.add(entity);
  2401. hm.put(userInEntity, newlist);
  2402. }
  2403. }
  2404. }
  2405. return (List<HolidayEntity>)hm.get(userid);
  2406. }
  2407. /**
  2408. * @param hm_cache
  2409. * @param userid
  2410. * @param yearmonth
  2411. * @return
  2412. */
  2413. @SuppressWarnings("unchecked")
  2414. private List<ProjarrangeDetailEntity> getUserProjarrangeDetailEntityWithCache(
  2415. HashMap<String, HashMap<String, Object>> hm_cache, String userid, String yearmonth) {
  2416. HashMap<String, Object> hm = hm_cache.get("getUserProjarrangeDetailEntityWithCache");
  2417. List<ProjarrangeDetailEntity> list = null;
  2418. if(hm == null) {
  2419. hm = new HashMap<>();
  2420. hm_cache.put("getUserProjarrangeDetailEntityWithCache", hm);
  2421. CriteriaQuery cq = new CriteriaQuery(
  2422. ProjarrangeDetailEntity.class);
  2423. cq.eq("yearmonth", yearmonth);
  2424. cq.add();
  2425. List<ProjarrangeDetailEntity> projarrangeDetailEntities = getListByCriteriaQuery(
  2426. cq, false);
  2427. for(ProjarrangeDetailEntity entity : projarrangeDetailEntities) {
  2428. String userInEntity = entity.getUserid();
  2429. if(hm.containsKey(userInEntity)) {
  2430. List<ProjarrangeDetailEntity> entitylist = (List<ProjarrangeDetailEntity>)hm.get(userInEntity);
  2431. entitylist.add(entity);
  2432. }else {
  2433. List<ProjarrangeDetailEntity> newlist = new ArrayList<>();
  2434. newlist.add(entity);
  2435. hm.put(userInEntity, newlist);
  2436. }
  2437. }
  2438. }
  2439. return (List<ProjarrangeDetailEntity>)hm.get(userid);
  2440. }
  2441. private List<OvertimeRecordEntity> getOvertimeRecordEntities(String userid,
  2442. String yearmonth) throws Exception {
  2443. List<OvertimeRecordEntity> resultEntities = new ArrayList<OvertimeRecordEntity>();
  2444. CriteriaQuery cq = new CriteriaQuery(OvertimeRecordEntity.class);
  2445. cq.eq("deleteFlag", "0");
  2446. cq.add();
  2447. if (oConvertUtils.isNotEmpty(userid)) {
  2448. cq.eq("userid", userid);
  2449. cq.add();
  2450. }
  2451. if (oConvertUtils.isNotEmpty(yearmonth)) {
  2452. Calendar cal = Calendar.getInstance();// 获取当前日期
  2453. cal.set(Integer.valueOf(yearmonth.split("-")[0]),
  2454. Integer.valueOf(yearmonth.split("-")[1]) - 2, 1);
  2455. Date startdate = cal.getTime();// 上个月的一号
  2456. cal.add(Calendar.MONTH, 2);
  2457. Date enddate = cal.getTime();// 下个月的一号
  2458. cq.between("overtimeStime", startdate, enddate);
  2459. cq.add();
  2460. }
  2461. resultEntities = getListByCriteriaQuery(cq, false);
  2462. return resultEntities;
  2463. }
  2464. public List<HolidayEntity> getUserHolidayEntities(String userid,
  2465. String yearmonth) throws Exception {
  2466. List<HolidayEntity> resulEntities = new ArrayList<HolidayEntity>();
  2467. CriteriaQuery cq = new CriteriaQuery(HolidayEntity.class);
  2468. cq.eq("bpmStatus", WorkFlowGlobals.BPM_BUS_STATUS_3);
  2469. cq.add();
  2470. cq.eq("deleteFlag", "0");
  2471. cq.add();
  2472. if (oConvertUtils.isNotEmpty(userid)) {
  2473. cq.eq("userid", userid);
  2474. cq.add();
  2475. }
  2476. if (oConvertUtils.isNotEmpty(yearmonth)) {
  2477. Calendar cal = Calendar.getInstance();// 获取当前日期
  2478. cal.set(Integer.valueOf(yearmonth.split("-")[0]), Integer.valueOf(yearmonth.split("-")[1]) - 1, 1);
  2479. cal.set(Calendar.HOUR_OF_DAY, 0);
  2480. cal.set(Calendar.MINUTE, 0);
  2481. cal.set(Calendar.SECOND, 0);
  2482. cal.add(Calendar.SECOND, -1);
  2483. Date startdate = cal.getTime();// 上个月的一号
  2484. cal.add(Calendar.MONTH, 1);
  2485. cal.set(Calendar.HOUR_OF_DAY, 23);
  2486. cal.set(Calendar.MINUTE, 59);
  2487. cal.set(Calendar.SECOND, 59);
  2488. Date enddate = cal.getTime();// 下个月的一号
  2489. cq.between("holidayStime", startdate, enddate);
  2490. cq.add();
  2491. }
  2492. resulEntities = getListByCriteriaQuery(cq, false);
  2493. return resulEntities;
  2494. }
  2495. public List<SnapSingleborrowEntity> getSnapSingleborrowEntities(
  2496. String userid, String yearmonth) throws Exception {
  2497. List<SnapSingleborrowEntity> resulEntities = new ArrayList<SnapSingleborrowEntity>();
  2498. //需求
  2499. // 由A部门调到B部门 调出日5号 算在A部门 调入日六号 算在B部门 终止日8 号 算在B部门
  2500. CriteriaQuery cq = new CriteriaQuery(SnapSingleborrowEntity.class);
  2501. cq.eq("bpmStatus", WorkFlowGlobals.BPM_BUS_STATUS_3);
  2502. cq.add();
  2503. cq.eq("deleteFlag", "0");
  2504. cq.add();
  2505. if (oConvertUtils.isNotEmpty(userid)) {
  2506. cq.eq("userid", userid);
  2507. cq.add();
  2508. }
  2509. if (oConvertUtils.isNotEmpty(yearmonth)) {
  2510. Calendar cal = Calendar.getInstance();
  2511. cal.set(Integer.valueOf(yearmonth.split("-")[0]),
  2512. Integer.valueOf(yearmonth.split("-")[1]) - 2, 1);
  2513. Date startdate = cal.getTime();// 上个月的一号
  2514. cal.add(Calendar.MONTH, 2);
  2515. Date enddate = cal.getTime();// 下个月的一号
  2516. cq.between("outTime", startdate, enddate);
  2517. cq.add();
  2518. cq.isNotNull("deadDate");
  2519. cq.add();
  2520. }
  2521. resulEntities = getListByCriteriaQuery(cq, false);
  2522. return resulEntities;
  2523. }
  2524. public List<SnapRegularborrowEntity> getSnapRegularborrowEntities(
  2525. String userid, String yearmonth) throws Exception {
  2526. List<SnapRegularborrowEntity> resulEntities = new ArrayList<SnapRegularborrowEntity>();
  2527. //需求
  2528. // 由A部门调到B部门 调出日5号 算在A部门 调入日六号 算在B部门 终止日8 号 算在B部门
  2529. CriteriaQuery cq = new CriteriaQuery(SnapRegularborrowEntity.class);
  2530. cq.eq("bpmStatus", WorkFlowGlobals.BPM_BUS_STATUS_3);
  2531. cq.add();
  2532. cq.eq("deleteFlag", "0");
  2533. cq.add();
  2534. if (oConvertUtils.isNotEmpty(userid)) {
  2535. cq.eq("userid", userid);
  2536. cq.add();
  2537. }
  2538. if (oConvertUtils.isNotEmpty(yearmonth)) {
  2539. Calendar cal = Calendar.getInstance();
  2540. cal.set(Integer.valueOf(yearmonth.split("-")[0]),
  2541. Integer.valueOf(yearmonth.split("-")[1]) - 1, 1);
  2542. Date startdate = cal.getTime();// 这个月的一号
  2543. cal.add(Calendar.MONTH, 1);
  2544. Date enddate = cal.getTime();// 下个月的一号
  2545. cq.le("inTime", enddate);
  2546. cq.add();
  2547. cq.ge("deadDate", startdate);
  2548. cq.between("outTime", startdate, enddate);
  2549. cq.add();
  2550. }
  2551. resulEntities = getListByCriteriaQuery(cq, false);
  2552. return resulEntities;
  2553. }
  2554. public List<DingAttendanceinfoEntity> getDingAttendanceinfoEntities(
  2555. UserAttendanceDetailDto dto) throws Exception {
  2556. List<DingAttendanceinfoEntity> resultlist = new ArrayList<DingAttendanceinfoEntity>();
  2557. Date curdate = dto.getYmdDate();
  2558. Calendar calendar = Calendar.getInstance();
  2559. calendar.setTime(curdate);
  2560. calendar.add(Calendar.DATE, 2);
  2561. Date tomdate = calendar.getTime();
  2562. CriteriaQuery cq = new CriteriaQuery(DingAttendanceinfoEntity.class);
  2563. cq.eq("userId", dto.getUserid());
  2564. cq.add();
  2565. cq.between("attendanceTime", curdate, tomdate);
  2566. cq.add();
  2567. cq.addOrder("attendanceTime", SortDirection.asc);
  2568. cq.add();
  2569. resultlist = getListByCriteriaQuery(cq, false);
  2570. return resultlist;
  2571. }
  2572. @Override
  2573. public List<UserAttendanceDetailDto> getallUsefulField(UserAttendanceTotalEntity userAttendanceTotalEntity,List<UserAttendanceDetailEntity> attendanceDetailEntities ,Date ymdDate)
  2574. throws Exception {
  2575. List<UserAttendanceDetailDto> uatdlist = new ArrayList<UserAttendanceDetailDto>();
  2576. List<UserAttendanceDetailDto> updatelist = new ArrayList<UserAttendanceDetailDto>();
  2577. String yearmonth = userAttendanceTotalEntity.getYearmonth();
  2578. String userid = userAttendanceTotalEntity.getUserId();
  2579. {
  2580. // 查询当前员工在当前处理月度的【项目排班详细】
  2581. CriteriaQuery cq = new CriteriaQuery(
  2582. ProjarrangeDetailEntity.class);
  2583. cq.eq("userid", userid);
  2584. cq.add();
  2585. cq.eq("yearmonth", yearmonth);
  2586. cq.add();
  2587. // 通过上述三个条件的筛选, 原则上而言, 应该是有且只有一条记录
  2588. List<ProjarrangeDetailEntity> projarrangeDetailEntities = getListByCriteriaQuery(
  2589. cq, false);
  2590. if (!ListUtils.isNullOrEmpty(projarrangeDetailEntities)) {
  2591. ProjarrangeDetailEntity projarrangeDetailEntity = projarrangeDetailEntities.get(0);
  2592. {
  2593. // 当前月无详细考勤记录数据
  2594. // 查询当前月的排班记录。
  2595. String ymddateString = null;
  2596. if (oConvertUtils.isNotEmpty(ymdDate)) {
  2597. ymddateString = DataUtils.date2Str(ymdDate, DataUtils.date_sdf);
  2598. }
  2599. uatdlist = userAttendanceDetailDao.getlistbyProjarrangeDetailid(projarrangeDetailEntity.getId(),null,ymddateString);
  2600. // =====查询请假情况
  2601. List<HolidayEntity> userHolidayEntities = getUserHolidayEntities(userid, yearmonth);
  2602. // =====查询加班情况
  2603. List<OvertimeRecordEntity> overtimeRecordEntities = getOvertimeRecordEntities(userid, yearmonth);
  2604. // =====查询调度情况
  2605. // 01 临时借调(单次)申请表
  2606. List<SnapSingleborrowEntity> snapSingleborrowEntities = getSnapSingleborrowEntities(userid, yearmonth);
  2607. // 02 临时借调(固定周期)申请表
  2608. List<SnapRegularborrowEntity> snapRegularborrowEntities = getSnapRegularborrowEntities(userid, yearmonth);
  2609. CriteriaQuery mscq = new CriteriaQuery(MealsSubsidyEntity.class);
  2610. mscq.eq("deleteFlag", "0");
  2611. mscq.add();
  2612. mscq.eq("status", "0");
  2613. mscq.add();
  2614. //餐费补贴
  2615. List<MealsSubsidyEntity> mealsSubsidyEntities=getListByCriteriaQuery(mscq, false);
  2616. CriteriaQuery mdcq = new CriteriaQuery(MealsDeductEntity.class);
  2617. mdcq.eq("deleteFlag", "0");
  2618. mdcq.add();
  2619. mdcq.eq("status", "0");
  2620. mdcq.add();
  2621. //餐费扣除标准
  2622. List<MealsDeductEntity> mealsDeductEntities=getListByCriteriaQuery(mdcq, false);
  2623. //特殊考勤-手工考勤(默认全勤)的员工
  2624. // CriteriaQuery specialcq = new CriteriaQuery(TBusSpecialAttendEntity.class);
  2625. // specialcq.eq("attendtype", Globals.Special_Attend_Type_All_IN);
  2626. // specialcq.add();
  2627. // List<TBusSpecialAttendEntity> specialAttendEntities = getListByCriteriaQuery(specialcq, false);
  2628. // HashMap<String,TBusSpecialAttendEntity> hm_specialAttendEntities = new HashMap<String,TBusSpecialAttendEntity>();
  2629. // if(specialAttendEntities != null && !specialAttendEntities.isEmpty()) {
  2630. // for(TBusSpecialAttendEntity spe : specialAttendEntities) {
  2631. // hm_specialAttendEntities.put(spe.getUserid(), spe);
  2632. // }
  2633. // }
  2634. if (null==attendanceDetailEntities) {
  2635. attendanceDetailEntities = new ArrayList<UserAttendanceDetailEntity>();
  2636. }
  2637. if (!ListUtils.isNullOrEmpty(uatdlist)) {
  2638. for (UserAttendanceDetailDto dto : uatdlist) {
  2639. UserAttendanceDetailEntity detailEntity = getUserAttendanceDetailEntityfromList(dto,attendanceDetailEntities);
  2640. if ((!ListUtils.isNullOrEmpty(attendanceDetailEntities))&&null==detailEntity) {
  2641. continue;
  2642. }
  2643. dto.setUserid(userid);
  2644. dto.setAttendanceId(userAttendanceTotalEntity.getId());
  2645. if (oConvertUtils.isNotEmpty(dto.getYmdDate())) {
  2646. if (!ListUtils.isNullOrEmpty(overtimeRecordEntities)) {
  2647. checkIshaveovertimeRecord(dto,
  2648. overtimeRecordEntities);
  2649. }
  2650. if (!ListUtils.isNullOrEmpty(snapSingleborrowEntities)) {
  2651. checkIshavesnapSingleborrows(dto,
  2652. snapSingleborrowEntities);
  2653. }
  2654. if (!ListUtils.isNullOrEmpty(snapRegularborrowEntities)) {
  2655. checkIshavesnapRegularborrows(dto,
  2656. snapRegularborrowEntities);
  2657. }
  2658. //将某人某天的餐费补贴 信息 添加至dto 中
  2659. if (!ListUtils.isNullOrEmpty(mealsSubsidyEntities)) {
  2660. checkIshavemealsSubsidyEntities(dto,
  2661. mealsSubsidyEntities);
  2662. }
  2663. //将某人某天的餐费补贴 的餐费扣除标准 添加至dto 中
  2664. if (!ListUtils.isNullOrEmpty(mealsDeductEntities)) {
  2665. dto.setMealsDeductEntities(mealsDeductEntities);
  2666. }
  2667. }
  2668. //获取有效开始打卡时间
  2669. Date effectiveStime = calculateEffectiveAttendanceStime(dto);
  2670. dto.setEffectiveStime(effectiveStime);
  2671. //获取有效结束打卡时间
  2672. Date effectiveEtime = calculateEffectiveAttendanceEtime(dto);
  2673. dto.setEffectiveEtime(effectiveEtime);
  2674. if (!ListUtils.isNullOrEmpty(userHolidayEntities)) {
  2675. checkIshaveHolidaies(dto, userHolidayEntities);
  2676. }
  2677. // 获取当前状态;
  2678. calculateCurdateStatus(dto);
  2679. // 获取某人某天在某排班情况下的考勤记录
  2680. List<DingAttendanceinfoEntity> dingAttendanceinfoEntities = getDingAttendanceinfoEntities(dto);
  2681. calculateActAttendancetime(dto, dingAttendanceinfoEntities, null,uatdlist,detailEntity);
  2682. //设置基准时间
  2683. calculateDatumDate(null,dto);
  2684. // 获取实际出勤时间
  2685. calculateActualAttendanceDate(dto);
  2686. // 获取时间差值
  2687. calculateActualtimeDifference(dto);
  2688. // 获取借调信息
  2689. calculateBorrowsInfo(dto);
  2690. //获取迟到/早退/旷工信息
  2691. calculateBelateAndLeaveEarlyAndabsenteeism(dto);
  2692. //获取加班信息
  2693. calculateOvertime(null,dto,userAttendanceTotalEntity);
  2694. //计算各种津贴
  2695. calculateSubsidy(dto);
  2696. if (oConvertUtils.isNotEmpty(detailEntity)) {
  2697. updatelist.add(dto);
  2698. }
  2699. if (oConvertUtils.isNotEmpty(ymdDate)) {
  2700. AttendanceDetailJsonObj jsonObj = getjsonObjfromDto(dto);
  2701. dto.setJsonObj(jsonObj);
  2702. }
  2703. }
  2704. } else {
  2705. // 当前人员本月份排班列表为空
  2706. }
  2707. }
  2708. }
  2709. }
  2710. if (!ListUtils.isNullOrEmpty(attendanceDetailEntities)) {
  2711. return updatelist ;
  2712. }else {
  2713. return uatdlist;
  2714. }
  2715. }
  2716. /**
  2717. * 通过考勤详情列表 获取考勤详情信息
  2718. * @author hualong.zhao
  2719. * @date 2017-12-5
  2720. * @param dto
  2721. * @param attendanceDetailEntities
  2722. * @return
  2723. */
  2724. private UserAttendanceDetailEntity getUserAttendanceDetailEntityfromList(UserAttendanceDetailDto dto,
  2725. List<UserAttendanceDetailEntity> attendanceDetailEntities){
  2726. UserAttendanceDetailEntity resultentry = null;
  2727. if (!ListUtils.isNullOrEmpty(attendanceDetailEntities)) {
  2728. for (UserAttendanceDetailEntity entry:attendanceDetailEntities) {
  2729. if (dto.getYmdDate().equals(entry.getYmdDate())) {
  2730. resultentry = entry;
  2731. break;
  2732. }
  2733. }
  2734. }
  2735. return resultentry;
  2736. }
  2737. /**
  2738. * 检查某人某天的餐费补贴
  2739. * @author hualong.zhao
  2740. * @date 2017-12-2
  2741. * @param dto
  2742. * @param mealsSubsidyEntities
  2743. */
  2744. private void checkIshavemealsSubsidyEntities(UserAttendanceDetailDto dto,
  2745. List<MealsSubsidyEntity> mealsSubsidyEntities) {
  2746. List<MealsSubsidyEntity> dtomealsSubsidyEntities = dto
  2747. .getMealsSubsidyEntities();
  2748. /** 班次餐补ID */
  2749. String dutyMealid = oConvertUtils.getString(dto.getDutyMealid());
  2750. if (oConvertUtils.isNotEmpty(dutyMealid)) {
  2751. for (MealsSubsidyEntity entity : mealsSubsidyEntities) {
  2752. if (dutyMealid.contains(entity.getId())) {
  2753. if (Globals.SUBSIDY_TYPE_BCCB.equals(oConvertUtils.getString(entity.getSubsidyType()))) {
  2754. dtomealsSubsidyEntities.add(entity);
  2755. }
  2756. }
  2757. }
  2758. }
  2759. dto.setMealsSubsidyEntities(dtomealsSubsidyEntities);
  2760. }
  2761. /**
  2762. * 计算津贴
  2763. * 夜班最多可提供两次餐补 , 餐补类型【夜班白班津贴】 和【夜班夜班津贴】 由班次表 动态配置
  2764. * 日班提供两次餐补,
  2765. * 常班提供一次餐补,
  2766. * 扣除规则:
  2767. * 如果是夜班时 ,根据迟到时间, 判断是否给与第一次餐补【夜班夜班津贴】
  2768. * 如果是夜班时 ,根据早退时间, 判断是否给与第二次餐补【夜班白班津贴】
  2769. * 如果是日班时 ,根据总的欠勤数, 判断扣除几顿
  2770. *
  2771. * 如果是常班时,根据总的欠勤数,判断是否给与餐补
  2772. * 2018年1月12日 需求变更: 当员工当天没有打卡记录的时候, 该员工餐补不提供
  2773. * @author hualong.zhao
  2774. * @date 2017-12-2
  2775. * @param dto
  2776. */
  2777. private void calculateSubsidy(UserAttendanceDetailDto dto) {
  2778. /**夜班白班津贴*/
  2779. Integer dayShiftSubsidy = 0 ;
  2780. /**夜班夜班津贴*/
  2781. Integer nightShiftSubsidy = 0;
  2782. /**日班*/
  2783. Integer dayShift = 0;
  2784. /**常班*/
  2785. Integer regularShift = 0;
  2786. /** 餐补补贴次数~餐补idmap */
  2787. HashMap<String, MealsSubsidyEntity> mealsmap = new HashMap<>();
  2788. //餐费补贴
  2789. List<MealsSubsidyEntity> dtomealsSubsidyEntities = dto.getMealsSubsidyEntities();
  2790. //餐费扣除标准
  2791. List<MealsDeductEntity> mealsDeductEntities=dto.getMealsDeductEntities();
  2792. // 请假 /休息 补贴清零 旷工一天 补贴清空 迟到早退 根据欠勤分钟数 按照餐费扣除标准 进行扣除 只记录 查询 判断 班次餐补 加班情况下 只考虑按此给0 or 1
  2793. if (dto.getLongHoliday()) {
  2794. if(dto.getActualAttendanceDate() == null || dto.getActualAttendanceDate().compareTo(BigDecimal.ZERO)<=0) {
  2795. dto.setDayShiftSubsidy(dayShiftSubsidy);
  2796. dto.setNightShiftSubsidy(nightShiftSubsidy);
  2797. dto.setDayShift(dayShift);
  2798. dto.setRegularShift(regularShift);
  2799. return;
  2800. }
  2801. }
  2802. if((Globals.DUTYTYPE_xiuxi.equals(oConvertUtils.getString(dto.getDutyType())))) {
  2803. dto.setDayShiftSubsidy(dayShiftSubsidy);
  2804. dto.setNightShiftSubsidy(nightShiftSubsidy);
  2805. dto.setDayShift(dayShift);
  2806. dto.setRegularShift(regularShift);
  2807. return;
  2808. }
  2809. if (!ListUtils.isNullOrEmpty(dtomealsSubsidyEntities)) {
  2810. for (MealsSubsidyEntity entry:dtomealsSubsidyEntities) {
  2811. String shiftSubsidyType = oConvertUtils.getString(entry.getShiftSubsidyType());
  2812. if (Globals.SHIFT_SUBSIDY_TYPE_YEBANJINTIEWAN.equals(shiftSubsidyType)) {
  2813. if (Globals.DUTYTYPE_yeban115.equals(oConvertUtils.getString(dto.getDutyType()))) {
  2814. nightShiftSubsidy = 1 ;
  2815. mealsmap.put("nightShiftSubsidy", entry);
  2816. }
  2817. }
  2818. if (Globals.SHIFT_SUBSIDY_TYPE_BAIBANJINTIEZAO.equals(shiftSubsidyType)) {
  2819. if (Globals.DUTYTYPE_yeban115.equals(oConvertUtils.getString(dto.getDutyType()))) {
  2820. dayShiftSubsidy = 1 ;
  2821. mealsmap.put("dayShiftSubsidy", entry);
  2822. }
  2823. }
  2824. if (Globals.SHIFT_SUBSIDY_TYPE_RIBAN.equals(shiftSubsidyType)) {
  2825. if (Globals.DUTYTYPE_riban11h.equals(oConvertUtils.getString(dto.getDutyType()))) {
  2826. dayShift = 2;
  2827. mealsmap.put("dayShift", entry);
  2828. }
  2829. }
  2830. if (Globals.SHIFT_SUBSIDY_TYPE_CHANGBAN.equals(shiftSubsidyType)) {
  2831. if (Globals.DUTYTYPE_CHANGBAN8H.equals(oConvertUtils.getString(dto.getDutyType()))) {
  2832. regularShift = 1 ;
  2833. mealsmap.put("regularShift", entry);
  2834. }
  2835. }
  2836. }
  2837. }
  2838. //如果扣费规则不为空
  2839. if (!ListUtils.isNullOrEmpty(mealsDeductEntities)) {
  2840. /**迟到分钟数*/
  2841. int belatemins = dto.getBelatemins();
  2842. /**早退分钟数*/
  2843. int leaveEarlymins = dto.getLeaveEarlymins();
  2844. int thinsorsickmins = dto.getSickLeaveMins().intValue()+dto.getThingLeaveMins().intValue();
  2845. int qqmins =belatemins + leaveEarlymins+thinsorsickmins ;
  2846. String durationCode = dto.getDurationCode();
  2847. //根据餐费扣除标准 扣除餐补
  2848. for (MealsDeductEntity entity : mealsDeductEntities) {
  2849. if (Globals.SUBSIDY_TYPE_BCCB.equals(oConvertUtils.getString(entity.getSubsidyType()))) {
  2850. Integer leftHours = entity.getLeftHours();
  2851. Integer rightHours = entity.getRightHours();
  2852. /**扣除数*/
  2853. BigDecimal deductNum = entity.getDeductNum();
  2854. if (oConvertUtils.isNotEmpty(leftHours)&&oConvertUtils.isNotEmpty(rightHours)) {
  2855. leftHours = leftHours*60;
  2856. rightHours = rightHours*60;
  2857. if (Globals.DUTYTYPE_yeban115.equals(oConvertUtils.getString(dto.getDutyType()))) {
  2858. int iamlate = belatemins ;
  2859. //迟到满足扣除标准
  2860. if ("1".equals(oConvertUtils.getString(durationCode))) {
  2861. //当天请假是前半夜假期
  2862. iamlate += thinsorsickmins;
  2863. }
  2864. if (iamlate>=leftHours&&iamlate<rightHours) {
  2865. if (null != deductNum) {
  2866. try {
  2867. int deductNumint =deductNum.intValue();
  2868. nightShiftSubsidy = nightShiftSubsidy - deductNumint;
  2869. } catch (Exception e) {
  2870. }
  2871. }
  2872. }
  2873. int iamleaveEarly = leaveEarlymins;
  2874. if ("1".equals(oConvertUtils.getString(durationCode))) {
  2875. //当天请假是后半夜假期
  2876. iamleaveEarly += thinsorsickmins;
  2877. }
  2878. //早退满足扣除标准
  2879. if (iamleaveEarly>=leftHours&&iamleaveEarly<rightHours) {
  2880. if (null != deductNum) {
  2881. try {
  2882. int deductNumint =deductNum.intValue();
  2883. dayShiftSubsidy = dayShiftSubsidy - deductNumint;
  2884. } catch (Exception e) {
  2885. }
  2886. }
  2887. }
  2888. /**
  2889. * 迟到 or 早退 超过x 小时满足扣除两顿时 , 两顿餐补都扣除。
  2890. */
  2891. if (qqmins>=leftHours&&qqmins<rightHours) {
  2892. try {
  2893. int deductNumint =deductNum.intValue();
  2894. if (deductNumint>=2) {
  2895. nightShiftSubsidy = 0;
  2896. dayShiftSubsidy = 0;
  2897. }
  2898. } catch (Exception e) {
  2899. }
  2900. }
  2901. }else {
  2902. /**
  2903. * 迟到满足扣除标准
  2904. * 如果是日班时 ,根据总的欠勤数, 判断扣除几顿
  2905. * 如果是常班时,根据总的欠勤数,判断是否给与餐补
  2906. *
  2907. * 欠勤分钟数 应该添加 当天申请的事假 or 病假的分钟数
  2908. */
  2909. if (qqmins>=leftHours&&qqmins<rightHours) {
  2910. if (null != deductNum) {
  2911. try {
  2912. int deductNumint =deductNum.intValue();
  2913. if (Globals.DUTYTYPE_riban11h.equals(oConvertUtils.getString(dto.getDutyType()))) {
  2914. dayShift = dayShift - deductNumint;
  2915. }
  2916. if (Globals.DUTYTYPE_CHANGBAN8H.equals(oConvertUtils.getString(dto.getDutyType()))) {
  2917. regularShift = regularShift - deductNumint;
  2918. }
  2919. } catch (Exception e) {
  2920. }
  2921. }
  2922. }
  2923. }
  2924. }
  2925. }
  2926. }
  2927. }
  2928. //实际上班时间
  2929. Date actattendanceDate = dto.getActattendanceDate();
  2930. //实际下班时间
  2931. Date actretreatDate= dto.getActretreatDate();
  2932. // 当员工当天没有打卡记录的时候, 该员工餐补不提供
  2933. if (oConvertUtils.isEmpty(actattendanceDate)&&oConvertUtils.isEmpty(actretreatDate)) {
  2934. dayShiftSubsidy = 0;
  2935. nightShiftSubsidy = 0;
  2936. regularShift = 0;
  2937. dayShift = 0;
  2938. }
  2939. //对餐补进行非负处理 最小值为零
  2940. dayShiftSubsidy = dayShiftSubsidy<0?0:dayShiftSubsidy;
  2941. nightShiftSubsidy = nightShiftSubsidy<0?0:nightShiftSubsidy;
  2942. regularShift = regularShift<0?0:regularShift;
  2943. dayShift = dayShift<0?0:dayShift;
  2944. //夜班白班津贴
  2945. if (0 != dayShiftSubsidy) {
  2946. MealsSubsidyEntity entity = mealsmap.get("dayShiftSubsidy");
  2947. if (entity != null) {
  2948. dto.setDayShiftSubsidyId(entity.getId());
  2949. }
  2950. }
  2951. //夜班夜班津贴
  2952. if (0!=nightShiftSubsidy) {
  2953. MealsSubsidyEntity entity = mealsmap.get("nightShiftSubsidy");
  2954. if (entity != null) {
  2955. dto.setNightShiftSubsidyId(entity.getId());
  2956. }
  2957. }
  2958. // 日班
  2959. if (0!=dayShift) {
  2960. MealsSubsidyEntity entity = mealsmap.get("dayShift");
  2961. if (entity != null) {
  2962. dto.setDayShiftId(entity.getId());
  2963. }
  2964. }
  2965. //常班
  2966. if (0!=regularShift) {
  2967. MealsSubsidyEntity entity = mealsmap.get("regularShift");
  2968. if (entity != null) {
  2969. dto.setRegularShiftId(entity.getId());
  2970. }
  2971. }
  2972. //如果同一天 已经有了 班次 餐补, 再次出现 加班 备案 餐补时, 这天的加班备案餐补 次数 不能计入 总数。按0处理。
  2973. dto.setDayShiftSubsidy(dayShiftSubsidy);
  2974. dto.setNightShiftSubsidy(nightShiftSubsidy);
  2975. dto.setDayShift(dayShift);
  2976. dto.setRegularShift(regularShift);
  2977. }
  2978. /**
  2979. * 计算当天的加班时间(必须在计算当天实际出勤时长的方法之后执行)
  2980. * @author hualong.zhao
  2981. * @param hm_cache
  2982. * @date 2017-12-1
  2983. * @param dto
  2984. * @param userAttendanceTotalEntity
  2985. */
  2986. private void calculateOvertime(HashMap<String, HashMap<String, Object>> hm_cache, UserAttendanceDetailDto dto, UserAttendanceTotalEntity userAttendanceTotalEntity) {
  2987. /**国定加班时长*/
  2988. BigDecimal nationalOvertimeDuration = BigDecimal.ZERO;
  2989. /**特殊加班费*/
  2990. BigDecimal specialOvertime = BigDecimal.ZERO;
  2991. List<OvertimeRecordEntity> list = dto.getOvertimeRecordEntities();
  2992. /**
  2993. * 国定加班时长 包括两部分: 1. 排班中按照不同的班次及法定假日计算当月的法定假日; 2. 当月加班备案中申请的国定加班时长
  2994. * A=法定假日当天排班的基准时长累计; B=当月加班备案中国定加班时长累计; 国定加班时长 = A+B;
  2995. */
  2996. if (!ListUtils.isNullOrEmpty(list)) {
  2997. //检索加班
  2998. for (OvertimeRecordEntity entry:list) {
  2999. BigDecimal overtimeBigDecimal = entry.getOvertimeHours();
  3000. if (null==overtimeBigDecimal) {
  3001. overtimeBigDecimal = BigDecimal.ZERO;
  3002. }
  3003. if ("1".equals(oConvertUtils.getString(entry.getIfnational()))) {
  3004. nationalOvertimeDuration =overtimeBigDecimal;
  3005. }else {
  3006. specialOvertime=overtimeBigDecimal;
  3007. }
  3008. }
  3009. }
  3010. // if("000000006120dd1c01612cf52162014f".equals(dto.getUserid())) {
  3011. // System.out.println();
  3012. // }
  3013. //计算115夜班前半夜或者后半夜是国定假的情况
  3014. BigDecimal halfNationOvertime = calculateHalfNationalOvertime(hm_cache, dto,true);
  3015. if(halfNationOvertime.compareTo(BigDecimal.ZERO)>0 && halfNationOvertime.compareTo(new BigDecimal(11.5*60))<0) {
  3016. nationalOvertimeDuration = nationalOvertimeDuration.add(halfNationOvertime);
  3017. //把超时加班中计算的部分去掉,设置的是负数
  3018. // BigDecimal timeoverDuration = userAttendanceTotalEntity.getTimeoutOvertimeDuration_orig();
  3019. // if(timeoverDuration == null) {
  3020. // timeoverDuration = BigDecimal.ZERO;
  3021. // }
  3022. // timeoverDuration = timeoverDuration.subtract(halfNationOvertime);
  3023. // userAttendanceTotalEntity.setTimeoutOvertimeDuration_orig(timeoverDuration);
  3024. }else {
  3025. //如果是全天都在国定时间内,将这一天的实际出勤时间计入国定加班时长 zy 20180416
  3026. if ((Globals.dtype_2.equals(oConvertUtils.getString(dto.getDtype())))) {
  3027. // nationalOvertimeDuration = dto.getDatumDate();
  3028. nationalOvertimeDuration = dto.getActualAttendanceDate();
  3029. }
  3030. }
  3031. dto.setNationalOvertimeDuration(nationalOvertimeDuration);
  3032. dto.setSpecialOvertime(specialOvertime);
  3033. }
  3034. /**
  3035. * 计算前半夜或者后半夜是国定加班的情况
  3036. * @param hm_cache
  3037. * @param dto
  3038. */
  3039. private BigDecimal calculateHalfNationalOvertime(HashMap<String, HashMap<String, Object>> hm_cache, UserAttendanceDetailDto dto, boolean isAccordingActualAttendance) {
  3040. if (!Globals.DUTYTYPE_yeban115.equals(dto.getDutyType())) {
  3041. return BigDecimal.ZERO;
  3042. }
  3043. if (!oConvertUtils.isNotEmpty(dto.getNormalworkStime())||!oConvertUtils.isNotEmpty(dto.getNormalworkEtime())) {
  3044. return BigDecimal.ZERO;
  3045. }
  3046. /**理应工作开始时间*/
  3047. Date workStarttime =getexactDate(dto.getYmdDate(), dto.getNormalworkStime(), 0, 0);
  3048. Calendar workStartCalendar = Calendar.getInstance();
  3049. workStartCalendar.setTime(workStarttime);
  3050. /**理应工作结束时间*/
  3051. Date workendtime = getexactDate(dto.getYmdDate(), dto.getNormalworkEtime(), 1, 0);
  3052. Calendar workEndCalendar = Calendar.getInstance();
  3053. workEndCalendar.setTime(workendtime);
  3054. List<CalendarEntity> calendarList = new ArrayList<>();
  3055. if(hm_cache == null) {
  3056. String calendarHql = "from CalendarEntity where (year =? and month =? and day = ? ) or (year =? and month =? and day = ?5)";
  3057. calendarList = calendarService.findHql(calendarHql, workStartCalendar.get(Calendar.YEAR), workStartCalendar.get(Calendar.MONTH)+1, workStartCalendar.get(Calendar.DATE)
  3058. ,workEndCalendar.get(Calendar.YEAR), workEndCalendar.get(Calendar.MONTH)+1, workEndCalendar.get(Calendar.DATE));
  3059. }else {
  3060. CalendarEntity calStart = getCalendarListWithCache(hm_cache, workStartCalendar.get(Calendar.YEAR), workStartCalendar.get(Calendar.MONTH)+1, workStartCalendar.get(Calendar.DATE));
  3061. CalendarEntity calEnd = getCalendarListWithCache(hm_cache, workEndCalendar.get(Calendar.YEAR), workEndCalendar.get(Calendar.MONTH)+1, workEndCalendar.get(Calendar.DATE));
  3062. if(calStart != null) {
  3063. calendarList.add(calStart);
  3064. }
  3065. if(calEnd != null) {
  3066. calendarList.add(calEnd);
  3067. }
  3068. }
  3069. if(calendarList.size() != 2) {
  3070. return BigDecimal.ZERO;
  3071. }
  3072. if(Globals.dtype_2.equals(calendarList.get(0).getDtype()) && Globals.dtype_2.equals(calendarList.get(1).getDtype())) {
  3073. return new BigDecimal(11.5*60); //都是国定假
  3074. }else if(!Globals.dtype_2.equals(calendarList.get(0).getDtype()) && !Globals.dtype_2.equals(calendarList.get(1).getDtype())) {
  3075. return BigDecimal.ZERO;
  3076. }
  3077. // if("000000006120dd1c01612cf5232001d6".equals(dto.getUserid())) {
  3078. // System.out.println();
  3079. // }
  3080. Date nationTypeDate = null;
  3081. if(Globals.dtype_2.equals(calendarList.get(0).getDtype())){
  3082. nationTypeDate = calendarList.get(0).getYmdDate();
  3083. }else {
  3084. nationTypeDate = calendarList.get(1).getYmdDate();
  3085. }
  3086. // 前半夜结束时间
  3087. Date standardAttendEndDate = new Date(workendtime.getYear(), workendtime.getMonth(), workendtime.getDate());
  3088. Calendar standardAttendEndCalendar = Calendar.getInstance();
  3089. standardAttendEndCalendar.setTime(standardAttendEndDate);
  3090. // 后半夜开始时间,有半小时休息。00:30分开始
  3091. Calendar standardHalfTwoCalendar = Calendar.getInstance();
  3092. standardHalfTwoCalendar.setTime(standardAttendEndDate);
  3093. standardHalfTwoCalendar.add(Calendar.MINUTE, 30);
  3094. // 实际打卡开始时间
  3095. Date actattendanceDate = workStarttime;
  3096. // 实际打卡结束时间
  3097. Date actretreatDate = workendtime;
  3098. if(isAccordingActualAttendance) {
  3099. actattendanceDate = dto.getActattendanceDate();
  3100. actretreatDate = dto.getActretreatDate();
  3101. if(actattendanceDate == null || actretreatDate == null || actattendanceDate.equals(actretreatDate)) {
  3102. return BigDecimal.ZERO;
  3103. }
  3104. if(actattendanceDate.compareTo(workStarttime) < 0) {
  3105. actattendanceDate = workStarttime;
  3106. }
  3107. if(actretreatDate.compareTo(workendtime) > 0) {
  3108. actretreatDate = workendtime;
  3109. }
  3110. }
  3111. //差值
  3112. int nationalDateDiffint = 0;
  3113. if(nationTypeDate.compareTo(new Date(workStarttime.getYear(), workStarttime.getMonth(), workStarttime.getDate())) == 0) {
  3114. // “考勤出勤时间”
  3115. Calendar actattendanceCalendar = Calendar.getInstance();
  3116. actattendanceCalendar.setTime(actattendanceDate);
  3117. //差值
  3118. nationalDateDiffint = DataUtils.dateDiff('m', standardAttendEndCalendar,actattendanceCalendar);
  3119. }else {
  3120. // “考勤出勤时间”
  3121. Calendar actretreatCalendar = Calendar.getInstance();
  3122. actretreatCalendar.setTime(actretreatDate);
  3123. //差值
  3124. nationalDateDiffint = DataUtils.dateDiff('m',actretreatCalendar, standardHalfTwoCalendar);
  3125. }
  3126. return new BigDecimal(Math.abs(nationalDateDiffint));
  3127. }
  3128. /**
  3129. * @param hm_cache
  3130. * @param i
  3131. * @param j
  3132. * @param k
  3133. * @return
  3134. */
  3135. private CalendarEntity getCalendarListWithCache(HashMap<String, HashMap<String, Object>> hm_cache, int year, int month,
  3136. int day) {
  3137. HashMap<String, Object> hm = hm_cache.get("getCalendarListWithCache");
  3138. if(hm == null) {
  3139. hm = new HashMap<>();
  3140. hm_cache.put("getCalendarListWithCache", hm);
  3141. String calendarHql = "from CalendarEntity where 1=1";
  3142. List<CalendarEntity> listDB = calendarService.findHql(calendarHql);
  3143. for(CalendarEntity entity : listDB) {
  3144. String userInEntity = entity.getYear()+"_"+entity.getMonth()+"_"+entity.getDay();
  3145. hm.put(userInEntity, entity);
  3146. }
  3147. }
  3148. return (CalendarEntity)hm.get(year+"_"+month+"_"+day);
  3149. }
  3150. // 计算时间差值 “实际出勤时间”与“基准时间”的差值; 实际出勤时间(每日)【时间小于等于 基准出勤时间】-基准时间(每日)【排班时间的N个小时】
  3151. private void calculateActualtimeDifference(UserAttendanceDetailDto dto) {
  3152. BigDecimal timeDifference = BigDecimal.ZERO;
  3153. // 加班值班的时候为零
  3154. String dutyType = oConvertUtils.getString(dto.getDutyType());
  3155. if (Globals.DUTYTYPE_xiuxi.equals(dutyType)||Globals.DUTYTYPE_jiaban.equals(dutyType)||Globals.DUTYTYPE_zhiban.equals(dutyType)) {
  3156. }else {
  3157. // 基准时间
  3158. BigDecimal datumDate = dto.getDatumDate();
  3159. BigDecimal actualAttendanceDate =dto.getActualAttendanceDate();
  3160. if (datumDate==null) {
  3161. datumDate = BigDecimal.ZERO;
  3162. }
  3163. if (actualAttendanceDate==null) {
  3164. actualAttendanceDate = BigDecimal.ZERO;
  3165. }
  3166. //实际打卡开始时间
  3167. Date actattendanceDate = dto.getActattendanceDate();
  3168. //实际打卡结束时间
  3169. Date actretreatDate = dto.getActretreatDate();
  3170. if (oConvertUtils.isNotEmpty(actattendanceDate)&&
  3171. oConvertUtils.isNotEmpty(actretreatDate)&&
  3172. actattendanceDate.equals(actretreatDate)) {
  3173. }else {
  3174. timeDifference = actualAttendanceDate.subtract(datumDate);
  3175. }
  3176. }
  3177. // 設置时间差值
  3178. dto.setTimeDifference(timeDifference);
  3179. }
  3180. /**
  3181. * 保存考勤调整记录
  3182. * @param entity
  3183. * @param userAttendanceTotalEntity
  3184. */
  3185. private void saveOrUpdateAdjustEntity(UserAttendanceDetailEntity entity, UserAttendanceTotalEntity userAttendanceTotalEntity) {
  3186. String detailId = entity.getId();
  3187. if(detailId == null) {
  3188. return;
  3189. }
  3190. List<UserAttendanceDetailAdjustedEntity> adjustedEntitiesInDB = findByProperty(UserAttendanceDetailAdjustedEntity.class
  3191. , "attendanceDetailId", detailId);
  3192. UserAttendanceDetailAdjustedEntity adjustedEntity = null;
  3193. if(adjustedEntitiesInDB == null || adjustedEntitiesInDB.isEmpty()) {
  3194. adjustedEntity = new UserAttendanceDetailAdjustedEntity();
  3195. }else {
  3196. adjustedEntity = adjustedEntitiesInDB.get(0);
  3197. }
  3198. adjustedEntity.setAttendanceDate(entity.getAttendanceDate());
  3199. adjustedEntity.setRetreatDate(entity.getRetreatDate());
  3200. adjustedEntity.setStatus(entity.getStatus());
  3201. adjustedEntity.setFineTuningType(entity.getFineTuningType());
  3202. adjustedEntity.setTimeFineTuning(entity.getTimeFineTuning());
  3203. adjustedEntity.setAdjustReason(entity.getAdjustReason());
  3204. adjustedEntity.setJsonObj(entity.getJsonObj());
  3205. adjustedEntity.setUserId(userAttendanceTotalEntity.getUserId());
  3206. adjustedEntity.setAttendanceDetailId(detailId);
  3207. adjustedEntity.setAttendanceId(userAttendanceTotalEntity.getId());
  3208. adjustedEntity.setTimeDifference(entity.getTimeDifference());
  3209. //设置 国定加班时长
  3210. adjustedEntity.setNationalOvertimeDuration(entity.getNationalOvertimeDuration());
  3211. //设置 特殊加班时长
  3212. adjustedEntity.setSpecialOvertime(entity.getSpecialOvertime());
  3213. adjustedEntity.setAttendanceMins(entity.getActualAttendanceDate());
  3214. adjustedEntity.setActualAttendanceDate(entity.getActualAttendanceDate());
  3215. adjustedEntity.setTimeoutOvertimeDuration(entity.getTimeoutOvertimeDuration());
  3216. adjustedEntity.setYmdDate(entity.getYmdDate());
  3217. saveOrUpdate(adjustedEntity);
  3218. }
  3219. }