using Entity.Sugar;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EasyBL
{
public class AttendanceMethods
{
///
/// 彈性工時計算
///
///
///
/// 依序:工作起、工作迄、是否遲到
public Tuple GetFlexTime(AttendanceRule attendanceRule, string SignIn)
{
var UseStartTime = @""; //實際使用上班時間。
var UseEndTime = @""; //實際使用上班時間。
var AnyBuffer = true;
var WorkDelay = false;
if (string.IsNullOrWhiteSpace(attendanceRule.WorkStartBuffer))
{
AnyBuffer = false;
}
//檢查有無buffer
if (AnyBuffer)
{
var SignInTime = Convert.ToDateTime(SignIn);
var StandardWorkStart = Convert.ToDateTime(attendanceRule.WorkStart);
var StandardWorkEnd = Convert.ToDateTime(attendanceRule.WorkEnd);
var BufferedWorkStart = Convert.ToDateTime(attendanceRule.WorkStartBuffer + ":59");
//-1: t1 早於 t2。 0: t1 與 t2 相同。 1: t1 晚於 t2。
var CheckStandardThreadhold = DateTime.Compare(SignInTime, StandardWorkStart) > 0;
if (CheckStandardThreadhold)
{
var CheckBufferThreadhold = DateTime.Compare(SignInTime, BufferedWorkStart);
switch (CheckBufferThreadhold)
{
case 1:
WorkDelay = true;
var TotalBufferHour = ExecDateDiff(StandardWorkStart, BufferedWorkStart);
StandardWorkEnd = StandardWorkEnd.AddHours(TotalBufferHour);
if (attendanceRule.DelayBuffer > 0)
{
BufferedWorkStart = BufferedWorkStart.AddMinutes(-1 * attendanceRule.DelayBuffer);
StandardWorkEnd = StandardWorkEnd.AddMinutes(-1 * attendanceRule.DelayBuffer);
}
UseEndTime = StandardWorkEnd.ToString("HH:mm");
UseStartTime = BufferedWorkStart.ToString("HH:mm");
break;
case 0:
case -1:
var WorkStartBuffer = ExecDateDiff(StandardWorkStart, SignInTime);
WorkDelay = false;
UseEndTime = StandardWorkEnd.AddHours(WorkStartBuffer).ToString("HH:mm");
UseStartTime = StandardWorkStart.AddHours(WorkStartBuffer).ToString("HH:mm");
break;
default:
break;
}
}
else
{
WorkDelay = false;
UseEndTime = attendanceRule.WorkEnd;
UseStartTime = attendanceRule.WorkStart;
}
}
//無緩衝
else
{
WorkDelay = DateTime.Compare(Convert.ToDateTime(SignIn), Convert.ToDateTime(attendanceRule.WorkStart)) > 0;
UseStartTime = attendanceRule.WorkStart;
UseEndTime = attendanceRule.WorkEnd;
}
return new Tuple(UseStartTime, UseEndTime, WorkDelay);
}
///
/// 計算工作時間。
/// 必須SignOut、SignIn有時間,SignOut晚於SignIn、TimeA(工作時間起)和TimeP(工作時間迄)
///
///
///
///
public double GetWorkingHour(string sSignTime, OTB_EIP_Attendance info)
{
var WorkingHour = 0.0;
var CheckAvaliableTime = !string.IsNullOrWhiteSpace(info.SignOut) && !string.IsNullOrWhiteSpace(info.SignIn);
var HasDiffTime = ExecDateDiff(Convert.ToDateTime(info.SignIn), Convert.ToDateTime(info.SignOut)) > 0;
var HasWorkTime = !string.IsNullOrWhiteSpace(info.TimeA) && !string.IsNullOrWhiteSpace(info.TimeP);
if (CheckAvaliableTime && HasDiffTime && HasWorkTime)
{
var StandardWorkStart = Convert.ToDateTime(info.TimeA);
var StandardWorkEnd = Convert.ToDateTime(info.TimeP);
var SignInTime = Convert.ToDateTime(info.SignIn);
if (SignInTime.Second > 0) //取最小量
SignInTime = SignInTime.AddSeconds(-1 * SignInTime.Second);
var SignOutTime = Convert.ToDateTime(sSignTime);
if (SignOutTime.Second > 0) //取最大量
SignOutTime = SignOutTime.AddSeconds(-1 * SignOutTime.Second);
var ActualStartTime = new DateTime();
var ActualEndTime = new DateTime();
//實際認列開始工作時間。過早一律認列上班時間
var WorkStartThreadhold = DateTime.Compare(SignInTime, StandardWorkStart);
//實際認列結束工作時間。
var WorkEndThreadhold = DateTime.Compare(SignOutTime, StandardWorkEnd);
switch (WorkStartThreadhold)
{
//刷進時間 晚於 變動上班時間
case 1:
ActualStartTime = SignInTime;
break;
//刷進時間 早於(等於) 變動上班時間
case 0:
case -1:
ActualStartTime = StandardWorkStart;
break;
default:
break;
}
switch (WorkEndThreadhold)
{
case 1:
case 0:
ActualEndTime = StandardWorkEnd;
break;
case -1:
ActualEndTime = SignOutTime;
break;
default:
break;
}
//實際工作起 早於 實際工作迄(前面條件會變更)
var TotalWorkTimeThreadhold = DateTime.Compare(ActualStartTime, ActualEndTime);
switch (TotalWorkTimeThreadhold)
{
case 1:
case 0:
WorkingHour = 0;
break;
case -1:
WorkingHour = Math.Round(ExecDateDiff(ActualStartTime, ActualEndTime), 2, MidpointRounding.AwayFromZero);
break;
default:
break;
}
}
return WorkingHour;
}
///
/// 計算考勤
///
/// 卡中資料
/// 出勤規則
/// 打卡日期
///
public List CalculateAttendance(string[] AllLineDatas, List AttendanceRules, DateTime CardDate)
{
var saCardAttendanceInfo = new List();
//讀取打卡信息
foreach (string str in AllLineDatas)
{
//打卡日期,卡號 , 刷卡時間,姓名 ,組織
//20190701,0410164401,14:03:39,陳OO ,TE
var strInfo = str.Split(',');
var sOrgID = strInfo[4].ToString().Trim();
if (string.IsNullOrEmpty(sOrgID))
{
continue;
}
var sCardDate = strInfo[0].ToString().Trim();
var sCardId = strInfo[1].ToString().Trim();
var sSignTime = strInfo[2].ToString().Trim();
var sCardUserName = strInfo[3].ToString().Trim();
var sTimeA = @"09:00"; //標準上班時間
var sTimeP = @"17:30"; //標準下班時間
var sTimeAE = ""; //允許最彈性下班時間
var UseStartTime = @""; //實際使用上班時間。
var UseEndTime = @""; //實際使用上班時間。
var AnyBuffer = true;
var ApplyRule = AttendanceRules.Where(ar => ar.OrgID == sOrgID).FirstOrDefault();
if (ApplyRule != null)
{
sTimeA = ApplyRule.WorkStart;
sTimeP = ApplyRule.WorkEnd;
sTimeAE = ApplyRule.WorkStartBuffer;
}
if (string.IsNullOrWhiteSpace(sTimeAE))
{
AnyBuffer = false;
sTimeAE = sTimeP;
}
if (saCardAttendanceInfo.Any(x => x.CardId == sCardId))
{
//如果存在則更新打卡信息
foreach (OTB_EIP_Attendance info in saCardAttendanceInfo)
{
if (info.CardId == sCardId)
{
info.SignOut = sSignTime;
var TotalWorkingHours = GetWorkingHour(sSignTime, info);
var bStatusP = DateTime.Compare(Convert.ToDateTime(info.TimeP), Convert.ToDateTime(sSignTime)) > 0;
info.Hours = TotalWorkingHours.ToString();
info.StatusP = bStatusP;
break;
}
}
}
//不存在則新增
else
{
var FlexTime = GetFlexTime(ApplyRule, sSignTime);
var oAttendanceInfo = new OTB_EIP_Attendance
{
OrgID = sOrgID,
CardDate = CardDate,
CardId = sCardId,
TimeA = FlexTime.Item1,
TimeP = FlexTime.Item2,
CardUserName = sCardUserName,
Hours = "0",
SignIn = sSignTime,
SignOut = ""
};
oAttendanceInfo.StatusA = FlexTime.Item3;
oAttendanceInfo.StatusP = false;
oAttendanceInfo.Memo = "";
oAttendanceInfo.CreateDate = DateTime.Now;
saCardAttendanceInfo.Add(oAttendanceInfo);
}
}
return saCardAttendanceInfo;
}
///
/// 取得考勤規則
///
///
/// 至少要4個
///
public List GetAttendanceRule(SqlSugarClient db, List ConfigSettings)
{
var AttendanceRule = new List();
try
{
do
{
//WebConfig依序:上班開始時間、上班結束時間、最晚上班時間(工作緩衝時間)、遲到緩衝時間(分)
//var ConfigSettings = new List() { Common.ConfigGetValue("", "WorkTimePMKey"), Common.ConfigGetValue("", "WorkTimeAMKey")
// ,Common.ConfigGetValue("", "LatestShiftTimeKey"), Common.ConfigGetValue("", "DelayBufferTimeKey") };
var AllOrgIDs = db.Queryable().Select(it => it.OrgID).ToList().Distinct();
if(!ConfigSettings.Any())
{
ConfigSettings = new List { "WorkTimePM", "WorkTimeAM", "LatestShiftTime", "DelayBufferTime" };
}
var spWorkTimePMKey = new SugarParameter("@WorkTimePM", ConfigSettings[0]);
var spDWorkTimeAMKey = new SugarParameter("@WorkTimeAM", ConfigSettings[1]);
var spLatestShiftTimeKey = new SugarParameter("@LatestShiftTime", ConfigSettings[2]);
var spDelayBufferKey = new SugarParameter("@DelayBuffer", ConfigSettings[3]);
var AllOfSystemSettings = db.Ado.SqlQuery(@"select *from OTB_SYS_SystemSetting where Effective ='Y'
and SettingItem in (@WorkTimePM, @WorkTimeAM, @LatestShiftTime, @DelayBuffer )", spWorkTimePMKey, spDWorkTimeAMKey, spLatestShiftTimeKey, spDelayBufferKey).ToArray();
//
foreach (var OrgID in AllOrgIDs)
{
var attendanceRule = new AttendanceRule() { OrgID = OrgID };
foreach (var Key in ConfigSettings)
{
var MatchedRule = AllOfSystemSettings.Where(s => s.OrgID == OrgID && s.SettingItem == Key).FirstOrDefault();
if (MatchedRule != null && !string.IsNullOrWhiteSpace(MatchedRule.SettingValue))
{
var SplittedTime = MatchedRule.SettingValue.Split(new char[] { '~' }, StringSplitOptions.RemoveEmptyEntries);
switch (Key)
{
case "WorkTimePM":
attendanceRule.WorkStart = SplittedTime[0].PadLeft(5, '0');//開始時間
attendanceRule.WorkTimePMDeadLine = MatchedRule.SettingValue;
break;
case "WorkTimeAM":
attendanceRule.WorkEnd = SplittedTime[1].PadLeft(5, '0');//結束時間
attendanceRule.WorkTimeAMDeadLine = MatchedRule.SettingValue;
break;
case "LatestShiftTime":
attendanceRule.WorkStartBuffer = SplittedTime[0].PadLeft(5, '0');
break;
case "DelayBufferTime":
var DelayBuffer = 0;
var CheckIntValue = int.TryParse(MatchedRule.SettingValue, out DelayBuffer);
attendanceRule.DelayBuffer = DelayBuffer;
break;
default:
break;
}
}
}
AttendanceRule.Add(attendanceRule);
}
} while (false);
}
catch (Exception error)
{
throw error;
}
return AttendanceRule;
}
///
/// 程序执行时间测试
///
/// 开始时间
/// 结束时间
/// 返回(秒)单位,比如: 0.00239秒
private double ExecDateDiff(DateTime dateBegin, DateTime dateEnd)
{
var ts1 = new TimeSpan(dateBegin.Ticks);
var ts2 = new TimeSpan(dateEnd.Ticks);
var ts3 = ts1.Subtract(ts2).Duration();
//你想转的格式
return ts3.TotalHours;
}
}
}