public int AddPunchCardLog(PunchCardLog newData, bool normal)   //true正常打卡新增/false編輯新增
        {
            int count = 0;
            var query = _DbContext.punchcardlogs.Where(b => b.accountID == newData.accountID && b.logDate == newData.logDate);

            if (query.Count() > 0)
            {
                return(1062);    //該日期已有紀錄
            }
            _DbContext.punchcardlogs.Add(newData);
            count = _DbContext.SaveChanges();

            if (count == 1 && !normal)
            {
                var dic   = new Dictionary <string, string> {
                };
                var opLog = new OperateLog()
                {
                    operateID = newData.lastOperaAccID, employeeID = newData.accountID,
                    active    = "新增", category = "打卡紀錄", createTime = definePara.dtNow()
                };
                toNameFn.AddUpPunchCardLog_convertToDic(ref dic, newData);
                opLog.content = toNameFn.AddUpPunchCardLog_convertToText(dic);
                saveOperateLog(opLog);    //紀錄操作紀錄
            }
            return(count);
        }
        public void AddNullPunchLog(int accID, int departID, DateTime targetDate)
        {
            var thisAccDetail = _DbContext.employeedetails.FirstOrDefault(b => b.accountID == accID);

            if (thisAccDetail != null)
            {
                if (targetDate < thisAccDetail.startWorkDate)    //避免處理報到日之前的日期
                {
                    return;
                }
            }

            var count        = 0;
            var nullPunchLog = new PunchCardLog();

            nullPunchLog.accountID    = accID;
            nullPunchLog.departmentID = departID;
            nullPunchLog.logDate      = targetDate;
            nullPunchLog.punchStatus  = 16;     //0x10=>16:缺卡 / 0x20=>32:曠職
            nullPunchLog.createTime   = definePara.dtNow();
            try{
                _DbContext.punchcardlogs.Add(nullPunchLog);
                count = _DbContext.SaveChanges();
            }catch (Exception e) {
                count = ((MySqlException)e.InnerException).Number;
            }
        }
        public void AddPunchLogWarnAndMessage(PunchCardLog log)
        {
            var context = _DbContext.punchlogwarns.FirstOrDefault(b => b.punchLogID == log.ID);

            if (context == null)
            {
                var query = (from a in _DbContext.accounts
                             join b in _DbContext.punchcardlogs on a.ID equals b.accountID
                             join c in _DbContext.departments on b.departmentID equals c.ID into tmp
                             from d in tmp.DefaultIfEmpty()
                             where b.ID == log.ID
                             select new{ a.userName, b.accountID,
                                         principalID = (d == null? 0:d.principalID) }).FirstOrDefault();

                var warnLog = new PunchLogWarn();
                warnLog.accountID   = log.accountID;
                warnLog.principalID = query.principalID;
                warnLog.punchLogID  = log.ID;
                warnLog.warnStatus  = 0;
                warnLog.createTime  = definePara.dtNow();

                _DbContext.punchlogwarns.Add(warnLog);
                if (_DbContext.SaveChanges() > 0)
                {
                    systemSendMessage(query.userName, query.accountID, "punch");
                }
            }
        }
        //---------------------------------------------------------------------------------------
        public object getTodayPunchStatus()     //look my today PunchStatus
        {
            PunchCardNeedParam logParam = new PunchCardNeedParam();

            logParam.thisWorkTime = Repository.GetThisWorkTime((int)loginID);
            logParam.workDateTime = Repository.workTimeProcess(logParam.thisWorkTime);
            PunchCardLog[] dataLogArr = Repository.GetTodayPunchLog((int)loginID, logParam, 0);
            PunchCardLog   dataLog;

            if (dataLogArr[1] != null && dataLogArr[1].onlineTime.Year > 1)
            {
                dataLog = dataLogArr[1];
            }
            else if (dataLogArr[0] != null)
            {
                dataLog = dataLogArr[0];
            }
            else
            {
                dataLog = new PunchCardLog();
            }
            DateTime onlineDt  = dataLog.onlineTime;
            DateTime offlineDt = dataLog.offlineTime;

            return(rAjaxResult(
                       new {
                onlineTime = onlineDt.Year == 1? null : (object)onlineDt,
                offlineTime = offlineDt.Year == 1? null : (object)offlineDt,
            }
                       ));
        }
        public void delPunchLogWarnAndMessage(PunchCardLog log)
        {
            var context = _DbContext.punchlogwarns.FirstOrDefault(b => b.punchLogID == log.ID);

            if (context != null)
            {
                _DbContext.punchlogwarns.Remove(context);
                _DbContext.SaveChanges();
            }
        }
        private void calWorkTimeByID(PunchCardLog log, WorkTimeRule thisWorkTime)
        {
            var targetDate      = log.logDate;
            var startDT         = targetDate.AddDays(1 - targetDate.Day).Date;
            var endDT           = startDT.AddMonths(1).AddDays(-1).Date;
            var thisMonthAllLog = Repository.GetPunchLogByDateByID(log.accountID, startDT, endDT);
            var otApplies       = Repository.GetOvertimeApplyByDateByID(log.accountID, startDT, endDT);

            countWorkTime(thisMonthAllLog, otApplies, thisWorkTime, startDT);
        }
        //正常打卡
        public int punchCardProcess(PunchCardLog logData, WorkTimeRule thisWorkTime, int action, int employeeID)
        {
            WorkDateTime wt = workTimeProcess(thisWorkTime);
            //需new一個出來 用原本的logData會等於context,一旦修改logData之後query後的context也會是修改後的(雖然沒儲存所以資料庫沒變)
            PunchCardLog newLogData;
            int          resultCount = 0; //0:操作異常 1:成功

            if (logData == null)          //今日皆未打卡
            {
                newLogData = new PunchCardLog()
                {
                    accountID      = employeeID, departmentID = (int)loginDepartmentID, logDate = wt.sWorkDt.Date,
                    lastOperaAccID = (int)loginID, onlineTime = definePara.dtNow(), createTime = definePara.dtNow()
                };
            }
            else   //今日有打過卡 or 電腦生成(跨日才有可能遇到)
            {
                newLogData              = new PunchCardLog();
                newLogData.ID           = logData.ID;
                newLogData.accountID    = logData.accountID;
                newLogData.departmentID = logData.departmentID;
                newLogData.logDate      = logData.logDate;
                newLogData.onlineTime   = logData.onlineTime;
                newLogData.offlineTime  = logData.offlineTime;
                newLogData.punchStatus  = logData.punchStatus;
                newLogData.createTime   = logData.createTime;

                newLogData.lastOperaAccID = (int)loginID;
                newLogData.updateTime     = definePara.dtNow();

                if (newLogData.onlineTime.Year == 1 && newLogData.offlineTime.Year == 1)
                {
                    newLogData.onlineTime = definePara.dtNow();
                }
                else
                {
                    newLogData.offlineTime = definePara.dtNow();
                }
            }
            newLogData.punchStatus = getStatusCode(wt, newLogData);
            resultCount            = newLogData.ID == 0? Repository.AddPunchCardLog(newLogData, true) : Repository.UpdatePunchCard(newLogData, true);
            if (resultCount == 1)     //一定要新增log成功 不然會沒logID
            {
                if (newLogData.punchStatus > psCode.normal && newLogData.punchStatus != psCode.takeLeave)
                {
                    Repository.AddPunchLogWarnAndMessage(newLogData);
                }
                else if (newLogData.punchStatus == psCode.normal)
                {
                    Repository.delPunchLogWarnAndMessage(newLogData);
                }
            }
            return(resultCount);
        }
        public int forceUpdatePunchCardLog(PunchCardLog updatePunchLog, string from)
        {
            if (updatePunchLog.ID == 0 || (updatePunchLog.onlineTime.Year == 1 && updatePunchLog.offlineTime.Year == 1))
            {
                return(2); //此打卡紀錄不合法
            }
            updatePunchLog.accountID = Repository.GetThisLogAccID(updatePunchLog.ID);
            WorkTimeRule thisWorkTime = Repository.GetThisWorkTime(updatePunchLog.accountID);

            return(punchCardFn.forcePunchLogProcess(updatePunchLog, thisWorkTime, "update", from));
        }
        public int forceAddPunchCardLog(PunchCardLog newPunchLog)
        {
            if (newPunchLog.accountID == 0 ||
                (newPunchLog.onlineTime.Year == 1 && newPunchLog.offlineTime.Year == 1))
            {
                return(2);  //此打卡紀錄不合法
            }
            WorkTimeRule thisWorkTime = Repository.GetThisWorkTime(newPunchLog.accountID);

            return(punchCardFn.forcePunchLogProcess(newPunchLog, thisWorkTime, "add"));
        }
        public int addPunchCardLog(int action, int employeeID = 0)
        {
            if (employeeID == 0)
            {
                employeeID = (int)loginID;
            }
            WorkTimeRule thisWorkTime = Repository.GetThisWorkTime(employeeID);
            PunchCardLog logData      = Repository.GetTodayPunchLog(employeeID, thisWorkTime);

            return(punchCardFn.punchCardProcess(logData, thisWorkTime, action, employeeID));
        }
        public object addPunchCardLog(int action, int employeeID = 0)   //action 0:正常打卡/打下班卡 1:提早上班
        {
            if (employeeID == 0)
            {
                employeeID = (int)loginID;
            }
            var logParam = new PunchCardNeedParam();

            logParam.thisWorkTime = Repository.GetThisWorkTime(employeeID);
            logParam.workDateTime = Repository.workTimeProcess(logParam.thisWorkTime);
            PunchCardLog[] punchLogArr = Repository.GetTodayPunchLog(employeeID, logParam, action);
            logParam.punchCardLog = punchLogArr[0];
            if (punchLogArr[1] != null && punchLogArr[1].onlineTime.Year > 1)
            {
                //提前打卡後 將以該工作日為基礎
                logParam.workDateTime = Repository.workTimeProcess(logParam.thisWorkTime, punchLogArr[1]);
                logParam.punchCardLog = punchLogArr[1];
            }
            if (definePara.dtNow() >= logParam.workDateTime.ePunchDT)    //at ambiguous time
            {
                if (_session.GetInt32("againRequest") == null || _session.GetInt32("againRequest") == 0)
                {
                    _session.SetInt32("againRequest", 1);
                    var wt       = logParam.workDateTime;
                    var dtFormat = "yyyy/MM/dd HH:mm";
                    var offline  = wt.sWorkDt.ToString(dtFormat) + " ~ " + wt.eWorkDt.ToString(dtFormat);
                    var online   = wt.sWorkDt.AddDays(1).ToString(dtFormat) + " ~ " + wt.eWorkDt.AddDays(1).ToString(dtFormat);
                    return(new cusResult <dynamic> {
                        resCode = 1, result = 2, resultMsg = $"{offline}T{online}"
                    });
                }
                _session.SetInt32("againRequest", 0);
            }
            if (action == 1)
            {
                PunchCardLog newLogData = new PunchCardLog();
                if (punchLogArr[1] == null)
                {
                    newLogData.logDate = logParam.workDateTime.sWorkDt.Date.AddDays(1);
                }
                else
                {
                    newLogData.ID      = punchLogArr[1].ID;
                    newLogData.logDate = punchLogArr[1].logDate;
                }
                logParam.punchCardLog = newLogData;
            }
            var result = punchCardFn.punchCardProcess(logParam, action, employeeID);

            return(cudAjaxResult(result));
        }
        public object forceAddPunchCardLog(PunchCardLog newPunchLog)
        {
            if (newPunchLog.accountID == 0 ||
                (newPunchLog.onlineTime.Year == 1 && newPunchLog.offlineTime.Year == 1))
            {
                return(cudAjaxResult(MessageCode.PunchCardDT_Illegal)); //此打卡時間紀錄不合法
            }
            var logParam = new PunchCardNeedParam();

            logParam.punchCardLog = newPunchLog;
            logParam.thisWorkTime = Repository.GetThisWorkTime(newPunchLog.accountID);
            var result = punchCardFn.forcePunchLogProcess(logParam, "add");

            return(cudAjaxResult(result));
        }
        public object forceUpdatePunchCardLog(PunchCardLog updatePunchLog, string from)
        {
            if (updatePunchLog.ID == 0 || (updatePunchLog.onlineTime.Year == 1 && updatePunchLog.offlineTime.Year == 1))
            {
                return(cudAjaxResult(MessageCode.PunchCardDT_Illegal)); //此打卡時間紀錄不合法
            }
            updatePunchLog.accountID = Repository.GetThisLogAccID(updatePunchLog.ID);
            var logParam = new PunchCardNeedParam();

            logParam.punchCardLog = updatePunchLog;
            logParam.thisWorkTime = Repository.GetThisWorkTime(updatePunchLog.accountID);
            var result = punchCardFn.forcePunchLogProcess(logParam, "update", from);

            return(cudAjaxResult(result));
        }
        public void processPunchlogWarn(PunchCardLog log, WorkTimeRule thisWorkTime)    //排程用
        {
            WorkDateTime wt = workTimeProcess(thisWorkTime, log);

            if (definePara.dtNow() < wt.ePunchDT)
            {
                return;
            }
            log.punchStatus    = getStatusCode(wt, log);
            log.lastOperaAccID = 0;
            Repository.UpdatePunchCard(log, true);
            if (log.punchStatus > 1 && log.punchStatus != psCode.takeLeave)
            {
                Repository.AddPunchLogWarnAndMessage(log);
            }
        }
        public int UpdatePunchCard(PunchCardLog updateData, bool normal)    //true正常打卡新增/false編輯新增
        {
            var oDic  = new Dictionary <string, string> {
            };
            var nDic  = new Dictionary <string, string> {
            };
            var opLog = new OperateLog()
            {
                operateID = updateData.lastOperaAccID, employeeID = updateData.accountID,
                active    = "更新", category = "打卡紀錄", createTime = definePara.dtNow()
            };
            int count = 0;
            var query = _DbContext.punchcardlogs.Where(b => b.accountID == updateData.accountID &&
                                                       b.logDate == updateData.logDate && b.ID != updateData.ID);

            if (query.Count() > 0)
            {
                return(1062);    //該日期已有紀錄
            }
            PunchCardLog context = _DbContext.punchcardlogs.FirstOrDefault(b => b.ID == updateData.ID);

            if (context != null)
            {
                toNameFn.AddUpPunchCardLog_convertToDic(ref oDic, context);

                context.logDate        = updateData.logDate;
                context.onlineTime     = updateData.onlineTime;
                context.offlineTime    = updateData.offlineTime;
                context.punchStatus    = updateData.punchStatus;
                context.lastOperaAccID = updateData.lastOperaAccID;
                context.updateTime     = updateData.updateTime;
                count = _DbContext.SaveChanges();
            }
            if (count == 1 && !normal)
            {
                toNameFn.AddUpPunchCardLog_convertToDic(ref nDic, context);
                opLog.content = toNameFn.AddUpPunchCardLog_convertToText(nDic, oDic);
                saveOperateLog(opLog);    //紀錄操作紀錄
            }
            return(count);
        }
        //---------------------------------------------------------------------------------------
        public object getTodayPunchStatus()     //look my today PunchStatus
        {
            WorkTimeRule thisWorkTime = Repository.GetThisWorkTime((int)loginID);
            var          dataLog      = Repository.GetTodayPunchLog((int)loginID, thisWorkTime);

            if (dataLog == null)
            {
                dataLog = new PunchCardLog();
            }
            dynamic onlineTime  = dataLog.onlineTime;
            dynamic offlineTime = dataLog.offlineTime;

            if (onlineTime.Year == 1)
            {
                onlineTime = false;
            }
            if (offlineTime.Year == 1)
            {
                offlineTime = false;
            }
            return(new {
                onlineTime = onlineTime, offlineTime = offlineTime,
            });
        }
        public WorkDateTime workTimeProcess(WorkTimeRule thisWorkTime, PunchCardLog customLog = null)
        {
            var wt = new WorkDateTime();

            wt.sWorkDt  = definePara.dtNow().Date; //online work dateTime
            wt.eWorkDt  = definePara.dtNow().Date; //offline work dateTime
            wt.sPunchDT = definePara.dtNow().Date; //可打卡時間
            wt.ePunchDT = definePara.dtNow().Date; //
            var sRest_start = new TimeSpan(0);
            var eRest_sRest = new TimeSpan(0);

            if (customLog != null)
            {
                if (customLog.logDate.Year != 1)
                {
                    wt.sWorkDt = wt.eWorkDt = wt.sPunchDT = wt.ePunchDT = customLog.logDate.Date;
                }
                else if (customLog.onlineTime.Year != 1)
                {
                    wt.sWorkDt = wt.eWorkDt = wt.sPunchDT = wt.ePunchDT = customLog.onlineTime.Date;
                }
                else if (customLog.offlineTime.Year != 1)
                {
                    wt.sWorkDt = wt.eWorkDt = wt.sPunchDT = wt.ePunchDT = customLog.offlineTime.Date;
                }
            }
            if (thisWorkTime != null)
            {
                var eWork_sWork = thisWorkTime.endTime - thisWorkTime.startTime;
                eWork_sWork      = eWork_sWork.TotalSeconds < 0? eWork_sWork.Add(new TimeSpan(1, 0, 0, 0)) : eWork_sWork;
                wt.addEtHour     = (int)(24 * 60 + wt.lessStHour - eWork_sWork.TotalMinutes); //單位改為分鐘
                sRest_start      = thisWorkTime.sRestTime - thisWorkTime.startTime;
                sRest_start      = sRest_start.TotalSeconds < 0? sRest_start.Add(new TimeSpan(1, 0, 0, 0)) : sRest_start;
                eRest_sRest      = thisWorkTime.eRestTime - thisWorkTime.sRestTime;
                eRest_sRest      = eRest_sRest.TotalSeconds < 0? eRest_sRest.Add(new TimeSpan(1, 0, 0, 0)) : eRest_sRest;
                wt.type          = thisWorkTime.type;
                wt.workAllTime   = false;
                wt.sWorkDt       = wt.sWorkDt + thisWorkTime.startTime;
                wt.eWorkDt       = wt.eWorkDt + thisWorkTime.endTime;
                wt.eWorkDt       = wt.eWorkDt <= wt.sWorkDt ? wt.eWorkDt.AddDays(1) : wt.eWorkDt;
                wt.sPunchDT      = wt.sWorkDt.AddMinutes(wt.lessStHour);
                wt.ePunchDT      = wt.eWorkDt.AddMinutes(wt.addEtHour);
                wt.elasticityMin = thisWorkTime.elasticityMin;
                if (customLog == null)
                {
                    if (definePara.dtNow() >= wt.ePunchDT)
                    {
                        wt.sPunchDT = wt.sPunchDT.AddDays(1);
                        wt.ePunchDT = wt.ePunchDT.AddDays(1);
                        wt.sWorkDt  = wt.sPunchDT.AddMinutes((wt.lessStHour * -1));
                        wt.eWorkDt  = wt.ePunchDT.AddMinutes((wt.addEtHour * -1));
                    }
                    else if (definePara.dtNow() < wt.sPunchDT)
                    {
                        wt.sPunchDT = wt.sPunchDT.AddDays(-1);
                        wt.ePunchDT = wt.ePunchDT.AddDays(-1);
                        wt.sWorkDt  = wt.sPunchDT.AddMinutes((wt.lessStHour * -1));
                        wt.eWorkDt  = wt.ePunchDT.AddMinutes((wt.addEtHour * -1));
                    }
                }
            }
            else
            {
                wt.workAllTime = true;
                wt.eWorkDt     = wt.eWorkDt.AddDays(1);
                wt.ePunchDT    = wt.ePunchDT.AddDays(1);
            }
            wt.sRestDt = wt.sWorkDt.AddMinutes(sRest_start.TotalMinutes);
            wt.eRestDt = wt.sRestDt.AddMinutes(eRest_sRest.TotalMinutes);
            return(wt);
        }
        public int forcePunchLogProcess(PunchCardLog processLog, WorkTimeRule thisWorkTime, string action, string from = "")
        {
            WorkDateTime wt        = workTimeProcess(thisWorkTime, processLog);
            var          et_big_st = thisWorkTime.endTime >= thisWorkTime.startTime? true: false;

            processLog.logDate        = wt.sWorkDt.Date;
            processLog.lastOperaAccID = (int)loginID;
            if (action == "update")
            {
                processLog.updateTime = definePara.dtNow();
            }
            else
            {
                processLog.createTime = definePara.dtNow();
            }

            if (processLog.onlineTime.Year != 1)
            {
                if (processLog.onlineTime < wt.sPunchDT)     //2300-0800 if write 0000-0800
                {
                    processLog.onlineTime = processLog.onlineTime.AddDays(1);
                }
                if (processLog.onlineTime >= wt.ePunchDT)     //0000-0800 if write 2355-0800
                {
                    processLog.onlineTime = processLog.onlineTime.AddDays(-1);
                }
            }
            if (processLog.offlineTime.Year != 1)
            {
                if (processLog.offlineTime <= wt.sWorkDt)    //2300-0800 if write 2300-0800
                {
                    processLog.offlineTime = processLog.offlineTime.AddDays(1);
                }
            }
            if (et_big_st && processLog.onlineTime.Year != 1 && processLog.offlineTime.Year != 1)
            {
                if (processLog.onlineTime >= processLog.offlineTime)
                {
                    processLog.onlineTime = processLog.onlineTime.AddDays(-1);
                }
            }
            else if (!et_big_st && processLog.onlineTime.Year != 1 && processLog.offlineTime.Year != 1)
            {
                if (processLog.offlineTime <= processLog.onlineTime)
                {
                    processLog.offlineTime = processLog.offlineTime.AddDays(1);
                }
            }

            processLog.punchStatus = getStatusCode(wt, processLog);
            int result = action == "update"? Repository.UpdatePunchCard(processLog, false) : Repository.AddPunchCardLog(processLog, false);

            if (result == 1)
            {
                if (processLog.punchStatus > psCode.normal && processLog.punchStatus != psCode.takeLeave)
                {
                    Repository.AddPunchLogWarnAndMessage(processLog);
                }
                if (action == "update" && from == "applySign")
                {
                    Repository.UpdatePunchLogWarn(processLog.ID);
                }
            }
            return(result);
        }
        public void AddUpPunchCardLog_convertToDic(ref Dictionary <string, string> Dic, PunchCardLog data)
        {
            var code   = new punchStatusCode();
            var status = " ";

            data   = (data == null? new PunchCardLog() : data);
            status = (data.punchStatus & code.lateIn) > 0 ? status += "遲到/" : status;
            status = (data.punchStatus & code.earlyOut) > 0 ? status += "早退/" : status;
            status = (data.punchStatus & code.overtime) > 0 ? status += "加班/" : status;
            status = (data.punchStatus & code.hadLost) > 0 ? status += "缺卡/" : status;
            status = (data.punchStatus & code.takeLeave) > 0 ? status += "請假/" : status;
            status = (data.punchStatus & code.noWork) > 0 ? status += "曠職" : status;
            status = (data.punchStatus & code.normal) > 0 && status == " " ? status += "正常" : status;
            status = status[status.Length - 1] == '/' ? status.Substring(0, status.Length - 1) :status;
            Dic.Add("operateID", data.lastOperaAccID.ToString());
            Dic.Add("accID", data.accountID.ToString());
            Dic.Add("logDate", data.logDate.ToString("yyyy-MM-dd"));
            Dic.Add("onTime", data.onlineTime.Year == 1?"無" : data.onlineTime.ToString("HH:mm:ss"));
            Dic.Add("offTime", data.offlineTime.Year == 1?"無" : data.offlineTime.ToString("HH:mm:ss"));
            Dic.Add("status", status);
        }
Esempio n. 20
0
        public void punchLogWithTakeLeave(LeaveOfficeApply restLog)
        {
            var restST   = restLog.startTime;
            var restET   = restLog.endTime;
            var wtLength = 720;         //工作時間長度 unit:minute
            //因工作時間可能跨日 不能直接用restST.Date EX: 2300-0800 休下半天0400-0800
            var workDate = restST.Date; //工作天日期(logDate)
            var wtRule   = (from a in _DbContext.accounts
                            join b in _DbContext.worktimerules on a.timeRuleID equals b.ID
                            where a.ID == restLog.accountID
                            select b).FirstOrDefault();

            if (wtRule != null)
            {
                if (wtRule.endTime < wtRule.startTime)
                {
                    wtLength = (int)(wtRule.endTime.Add(new TimeSpan(24, 0, 0)) - wtRule.startTime).TotalMinutes;
                }
                else
                {
                    wtLength = (int)(wtRule.endTime - wtRule.startTime).TotalMinutes;
                }
                var restSTime = new TimeSpan(restST.Hour, restST.Minute, restST.Second);
                workDate = (wtRule.startTime > restSTime)? workDate.AddDays(-1) : workDate;
            }

            do
            {
                var log = _DbContext.punchcardlogs.FirstOrDefault(b =>
                                                                  b.accountID == restLog.accountID && b.logDate == workDate);
                if (log != null)
                {
                    log.lastOperaAccID = restLog.lastOperaAccID;
                    log.updateTime     = definePara.dtNow();
                    WorkDateTime wt = punchCardFn.workTimeProcess(wtRule, log);
                    log.punchStatus = punchCardFn.getStatusCode(wt, log);
                    if (restLog.applyStatus != 1)
                    {
                        if (wtRule != null)
                        {
                            var logEndTime = log.logDate + wtRule.endTime;
                            logEndTime = (wtRule.endTime <= wtRule.startTime)? logEndTime.AddDays(1) : logEndTime;
                            if (definePara.dtNow() <= logEndTime && log.onlineTime.Year == 1 && log.offlineTime.Year == 1)
                            {
                                _DbContext.Remove(log);
                            }
                        }
                        else
                        {
                            if (log.logDate > definePara.dtNow())
                            {
                                _DbContext.Remove(log);
                            }
                        }
                    }
                    _DbContext.SaveChanges();
                }
                else
                {
                    if (restLog.applyStatus == 1)
                    {
                        var          applyAcc = _DbContext.accounts.FirstOrDefault(b => b.ID == restLog.accountID);
                        var          departID = applyAcc == null? 0 : applyAcc.departmentID;
                        PunchCardLog newLog   = new PunchCardLog {
                            accountID = restLog.accountID, departmentID = departID,
                            logDate   = workDate, createTime = definePara.dtNow(),
                        };
                        WorkDateTime wt = punchCardFn.workTimeProcess(wtRule, newLog);
                        newLog.punchStatus = punchCardFn.getStatusCode(wt, newLog, restLog);
                        _DbContext.punchcardlogs.Add(newLog);
                        _DbContext.SaveChanges();
                    }
                }

                if (restST.AddMinutes(wtLength) < restET)
                {
                    restST   = restST.AddDays(1);
                    workDate = workDate.AddDays(1);
                }
                else
                {
                    restST = restST.AddMinutes(wtLength);
                }
            }while(restST < restET);
        }
        //正常打卡
        public int punchCardProcess(PunchCardNeedParam logParam, int action, int employeeID)
        {
            WorkTimeRule thisWorkTime = logParam.thisWorkTime;
            PunchCardLog logData      = logParam.punchCardLog;
            WorkDateTime wt           = logParam.workDateTime;
            //需new一個出來 用原本的logData會等於context,一旦修改logData之後query後的context也會是修改後的(雖然沒儲存所以資料庫沒變)
            PunchCardLog newLogData;
            DateTime     dtNow       = definePara.dtNow();
            int          resultCount = 0; //0:操作異常 1:成功

            if (action == 1)              //action = 1 提早打上班卡
            {
                newLogData = new PunchCardLog()
                {
                    ID             = logData.ID,
                    accountID      = employeeID,
                    departmentID   = (int)loginDepartmentID,
                    logDate        = logData.logDate,
                    lastOperaAccID = (int)loginID,
                    onlineTime     = dtNow,
                    createTime     = dtNow
                };
            }
            else if (action == 0 && logData == null)    //action = 0  正常打卡或打下班卡
            //
            {
                newLogData = new PunchCardLog()
                {
                    accountID      = employeeID,
                    departmentID   = (int)loginDepartmentID,
                    logDate        = wt.sWorkDt.Date,
                    lastOperaAccID = (int)loginID,
                    createTime     = dtNow
                };
                if (dtNow >= wt.ePunchDT)    //在模糊區段 打下班卡
                {
                    newLogData.offlineTime = dtNow;
                }
                else    //非模糊區段 若上班卡沒打會先打上班卡 之後需要打一次下班卡
                {
                    newLogData.onlineTime = dtNow;
                }
            }
            else
            {
                newLogData                = new PunchCardLog();
                newLogData.ID             = logData.ID;
                newLogData.accountID      = logData.accountID;
                newLogData.departmentID   = logData.departmentID;
                newLogData.logDate        = logData.logDate;
                newLogData.onlineTime     = logData.onlineTime;
                newLogData.offlineTime    = logData.offlineTime;
                newLogData.punchStatus    = logData.punchStatus;
                newLogData.createTime     = logData.createTime;
                newLogData.lastOperaAccID = (int)loginID;
                newLogData.updateTime     = dtNow;
                if (dtNow >= wt.ePunchDT || logData.onlineTime.Year > 1)
                {
                    newLogData.offlineTime = dtNow;
                }
                else
                {
                    newLogData.onlineTime = dtNow;
                }
            }
            logParam.punchCardLog  = newLogData;
            logParam.workDateTime  = workTimeProcess(thisWorkTime, newLogData);
            newLogData.punchStatus = getStatusCode(logParam);
            resultCount            = newLogData.ID == 0? Repository.AddPunchCardLog(newLogData, true) : Repository.UpdatePunchCard(newLogData, true);
            if (resultCount == 1)     //一定要新增log成功 不然會沒logID
            {
                if (newLogData.punchStatus > psCode.normal && newLogData.punchStatus != psCode.takeLeave)
                {
                    Repository.AddPunchLogWarnAndMessage(newLogData);
                }
                else if (newLogData.punchStatus == psCode.normal)
                {
                    Repository.delPunchLogWarnAndMessage(newLogData);
                }
                if (action == 1)     //提早打上班卡 通知主管
                {
                    var accDetail = Repository.GetAccountDetail(newLogData.accountID);
                    var userName  = (string)accDetail.GetType().GetProperty("userName").GetValue(accDetail);
                    //obj.GetType().GetProperty(key).GetValue(obj);
                    Repository.systemSendMessage(userName, newLogData.accountID, "earlyPunch");
                }
            }
            return(resultCount);
        }
        public int getStatusCode(PunchCardNeedParam logParam, LeaveOfficeApply leave = null)
        {
            WorkDateTime wt          = logParam.workDateTime;
            PunchCardLog processLog  = logParam.punchCardLog;
            var          fullDayRest = false; //請整天假
            var          statusCode  = 0;     //statusCode:  0x01:正常 0x02:遲到 0x04:早退 0x08:加班 0x10:缺卡 0x20:曠職 0x40:請假

            if (wt.workAllTime)
            {
                return(psCode.normal);
            }
            var elasticityMin = wt.elasticityMin;   //彈性時間
            List <LeaveOfficeApply> thisLeave = new List <LeaveOfficeApply>();

            //if(leave == null){
            thisLeave = Repository.GetThisTakeLeave(processLog.accountID, wt.sWorkDt, wt.eWorkDt);
            //}else{
            //    thisLeave.Add(leave);
            //}
            if (thisLeave.Count > 0)
            {
                var allWorkLen = (wt.eWorkDt - wt.sWorkDt).TotalMinutes;
                var restLen    = (wt.eRestDt - wt.sRestDt).TotalMinutes;
                var workLen    = allWorkLen - restLen;
                var sum        = 0.0;
                foreach (var tmp in thisLeave)
                {
                    sum        += (tmp.endTime - tmp.startTime).TotalMinutes;
                    fullDayRest = (tmp.startTime <= wt.sWorkDt && tmp.endTime >= wt.eWorkDt)? true : false;
                }
                fullDayRest = sum >= workLen? true : fullDayRest;
                statusCode |= psCode.takeLeave;
            }

            if (processLog.onlineTime.Year == 1 && processLog.offlineTime.Year == 1)
            {
                if (definePara.dtNow() >= wt.ePunchDT)
                {
                    statusCode = fullDayRest? statusCode : (statusCode | psCode.noWork);
                }
                else
                {
                    if (definePara.dtNow() >= wt.eWorkDt)
                    {
                        statusCode = fullDayRest? statusCode : (statusCode | psCode.hadLost);
                    }
                }
            }
            else if (processLog.onlineTime.Year > 1 && processLog.offlineTime.Year > 1)
            {
                var newStartWt = wt.sWorkDt.AddMinutes(elasticityMin + 1);   //+1因遲到以時分為主 09:00:59 也不算遲到
                statusCode = processLog.onlineTime >= newStartWt? (statusCode | psCode.lateIn) : statusCode;
                var timeLen = (int)((processLog.onlineTime - wt.sWorkDt).TotalMinutes);
                timeLen    = (timeLen <0 || timeLen> elasticityMin)? 0: timeLen; //上班打卡超過彈性時間 下班就已下班時間為準
                statusCode = processLog.offlineTime < wt.eWorkDt.AddMinutes(timeLen)? (statusCode | psCode.earlyOut):statusCode;
                if (statusCode == psCode.takeLeave && (statusCode & psCode.lateIn) == 0 && (statusCode & psCode.earlyOut) == 0)
                {
                    statusCode = (statusCode | psCode.normal);
                }
            }
            else
            {
                if (processLog.onlineTime.Year > 1) //只有填上班
                {
                    var newStartWt = wt.sWorkDt.AddMinutes(elasticityMin + 1);
                    statusCode = processLog.onlineTime >= newStartWt? (statusCode | psCode.lateIn) : statusCode;
                    statusCode = definePara.dtNow() >= wt.ePunchDT ? (statusCode | psCode.hadLost) : statusCode; //打不到下班卡了
                }
                else                                                                                             //只有填下班
                {
                    statusCode |= psCode.hadLost;
                    statusCode  = processLog.offlineTime < wt.eWorkDt ? (statusCode | psCode.earlyOut) : statusCode;
                }
            }
            return(statusCode == 0? (psCode.normal) : statusCode);
        }
 public WorkDateTime workTimeProcess(WorkTimeRule thisWorkTime, PunchCardLog customLog = null)
 {
     return(Repository.workTimeProcess(thisWorkTime, customLog));
 }
        public WorkDateTime workTimeProcess(WorkTimeRule thisWorkTime, PunchCardLog customLog = null)
        {
            var wt    = new WorkDateTime();
            var dtNow = definePara.dtNow();

            wt.sWorkDt = dtNow.Date;  //online work dateTime
            wt.eWorkDt = dtNow.Date;  //offline work dateTime
            var eWork_sWork = new TimeSpan(0);
            var sRest_start = new TimeSpan(0);
            var eRest_sRest = new TimeSpan(0);

            if (customLog != null)
            {
                if (customLog.logDate.Year != 1)
                {
                    wt.sWorkDt = wt.eWorkDt = customLog.logDate.Date;
                }
                else if (customLog.onlineTime.Year != 1)
                {
                    wt.sWorkDt = wt.eWorkDt = customLog.onlineTime.Date;
                }
                else if (customLog.offlineTime.Year != 1)
                {
                    wt.sWorkDt = wt.eWorkDt = customLog.offlineTime.Date;
                }
            }
            if (thisWorkTime != null)
            {
                eWork_sWork = thisWorkTime.endTime - thisWorkTime.startTime;
                eWork_sWork = eWork_sWork.TotalSeconds < 0? eWork_sWork.Add(new TimeSpan(1, 0, 0, 0)) : eWork_sWork;
                // wt.addEtHour = (int)(24*60 + wt.lessStHour - eWork_sWork.TotalMinutes);   //單位改為分鐘
                sRest_start      = thisWorkTime.sRestTime - thisWorkTime.startTime;
                sRest_start      = sRest_start.TotalSeconds < 0? sRest_start.Add(new TimeSpan(1, 0, 0, 0)) : sRest_start;
                eRest_sRest      = thisWorkTime.eRestTime - thisWorkTime.sRestTime;
                eRest_sRest      = eRest_sRest.TotalSeconds < 0? eRest_sRest.Add(new TimeSpan(1, 0, 0, 0)) : eRest_sRest;
                wt.type          = thisWorkTime.type;
                wt.workAllTime   = false;
                wt.sWorkDt       = wt.sWorkDt + thisWorkTime.startTime;
                wt.eWorkDt       = wt.eWorkDt + thisWorkTime.endTime;
                wt.eWorkDt       = wt.eWorkDt <= wt.sWorkDt ? wt.eWorkDt.AddDays(1) : wt.eWorkDt;
                wt.sPunchDT      = wt.sWorkDt.AddMinutes(wt.lessStHour);
                wt.ePunchDT      = wt.eWorkDt.AddMinutes(wt.addEtHour);
                wt.elasticityMin = thisWorkTime.elasticityMin;
                if (customLog == null)
                {
                    if (dtNow < wt.sPunchDT && dtNow < wt.ePunchDT.AddDays(-1)) //2300-0800 0830打卡
                    {
                        wt.sWorkDt  = wt.sWorkDt.AddDays(-1);
                        wt.eWorkDt  = wt.eWorkDt.AddDays(-1);
                        wt.sPunchDT = wt.sWorkDt.AddMinutes(wt.lessStHour);
                        wt.ePunchDT = wt.eWorkDt.AddMinutes(wt.addEtHour);
                    }
                    else if (dtNow < wt.sPunchDT && dtNow >= wt.ePunchDT.AddDays(-1))
                    {
                        //ambiguous
                        //目前工作日判斷,把位於模糊區域的時間,以某工作日的加班來處理
                        wt.sWorkDt  = wt.sWorkDt.AddDays(-1);
                        wt.eWorkDt  = wt.eWorkDt.AddDays(-1);
                        wt.sPunchDT = wt.sWorkDt.AddMinutes(wt.lessStHour);
                        wt.ePunchDT = wt.eWorkDt.AddMinutes(wt.addEtHour);
                    }
                    else if (dtNow >= wt.ePunchDT && dtNow >= wt.sPunchDT.AddDays(1))   //0000-0800 2330打卡
                    {
                        wt.sWorkDt  = wt.sWorkDt.AddDays(1);
                        wt.eWorkDt  = wt.eWorkDt.AddDays(1);
                        wt.sPunchDT = wt.sWorkDt.AddMinutes(wt.lessStHour);
                        wt.ePunchDT = wt.eWorkDt.AddMinutes(wt.addEtHour);
                    }
                    else if (dtNow >= wt.ePunchDT && dtNow < wt.sPunchDT.AddDays(1))
                    {
                        //ambiguous
                        //目前工作日判斷,把位於模糊區域的時間,以某工作日的加班來處理
                        //不處理
                    }
                }
            }
            else
            {
                wt.workAllTime = true;
                wt.sPunchDT    = wt.sWorkDt;
                wt.eWorkDt     = wt.sWorkDt.AddDays(1);
                wt.ePunchDT    = wt.eWorkDt;
            }
            wt.sRestDt = wt.sWorkDt.AddMinutes(sRest_start.TotalMinutes);
            wt.eRestDt = wt.sRestDt.AddMinutes(eRest_sRest.TotalMinutes);
            return(wt);
        }
        public bool chkApplyOvertimeData(OvertimeApply data)
        {
            var result   = true;
            var punchLog = _DbContext.punchcardlogs.FirstOrDefault(b => b.accountID == data.accountID && b.logDate == data.workDate);

            if (punchLog == null)
            {
                result = false;
            }
            else
            {
                result = punchLog.onlineTime.Year > 1 && punchLog.offlineTime.Year > 1? result : false;
            }
            //計算加班長度
            WorkTimeRule thisWorkTime = pRepository.GetThisWorkTime(data.accountID);
            PunchCardLog tmpLog       = new PunchCardLog()
            {
                logDate = data.workDate
            };
            WorkDateTime workTime       = punchCardFn.workTimeProcess(thisWorkTime, tmpLog);
            var          sRestTime      = thisWorkTime.sRestTime;
            var          eRestTime      = thisWorkTime.eRestTime;
            var          restTimeMinute = 0;
            var          restlength     = TimeSpan.Zero;

            if (eRestTime < sRestTime)
            {
                restlength = eRestTime.Add(new TimeSpan(24, 0, 0)) - sRestTime;
            }
            else
            {
                restlength = eRestTime - sRestTime;
            }
            restTimeMinute = (int)restlength.TotalMinutes;
            var st         = data.startDateTime;
            var et         = data.endDateTime;
            var overLength = 0; //加班長度

            if (st <= workTime.sRestDt && et >= workTime.eRestDt)
            {
                overLength = (int)((et - st).TotalMinutes) - restTimeMinute;
            }
            else if (st < workTime.sRestDt && et <= workTime.eRestDt)
            {
                if (et < workTime.sRestDt)
                {
                    overLength = (int)(et - st).TotalMinutes;
                }
                else
                {
                    overLength = (int)(workTime.sRestDt - st).TotalMinutes;
                }
            }
            else if (st >= workTime.sRestDt && et > workTime.eRestDt)
            {
                if (st > workTime.eRestDt)
                {
                    overLength = (int)(et - st).TotalMinutes;
                }
                else
                {
                    overLength = (int)(et - workTime.eRestDt).TotalMinutes;
                }
            }
            overLength      = (overLength / 30) * 30; //以半小時的倍數為準
            result          = overLength >= 30? result : false;
            data.timeLength = overLength;
            return(result);
        }