Files
thinkyu/Web/App_Code/BatchService.cs
T
sryang 577060bc78 chore: 首次簽入 Thinkyu ASP.NET 專案
- 加入 Visual Studio / ASP.NET .gitignore
- 排除建置輸出、IDE 設定、NuGet packages、大型 MSI 安裝檔
2026-09-10 09:42:37 +08:00

329 lines
13 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Script.Services;
using System.Web.Services;
using Wellan.Common;
using Wellan.Data;
using System.Data;
using System.Net.Mail;
using System.Text;
using System.IO;
/// <summary>
/// BatchService 的摘要描述
/// </summary>
[WebService(Namespace = "http://thinkyu.com/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService]
public class BatchService : System.Web.Services.WebService
{
public BatchService()
{
//如果使用設計的元件,請取消註解下列一行
//InitializeComponent();
}
private WQuery SetupQuery()
{
var ConnectionConfigName = WConfig.GetConnectionConfigName();
WConnectionString.ConnectionConfigFile = WConfig.GetConnectionConfig();
var ConnectionString = WConnectionString.GetConnectionString(ConnectionConfigName);
var ConnectionType = WConnectionString.GetConnectionType(ConnectionConfigName);
var Query = new WQuery(ConnectionType, ConnectionString);
WGuard1.SetQuery(ConnectionType, ConnectionString);
return Query;
}
private void CheckPunchCard(DateTime date, ref List<打卡異常Item> employeeWarning, ref List<通知督導Item> supervisorWarning)
{
/*
差勤異常通知之定義及需求如下
一、差勤異常定義:
1.無上下班打卡紀錄,且無"出差" 或 "請假" 申請紀錄
2.出勤時數不足8小時(出勤時數指"打卡+出差+請假")
註:此處出差或請假申請只要申請人送單即可算
二、系統需求
1.差勤月報表:有異常者,於備註顯示 "出勤異常"
2.寄送異常通知:有出勤異常則於隔日通知個人,專案管理人統一於每月30日收到所有專案人員差勤異常通知
3.打卡限定:不能連續七日打卡
*/
TimeCalc timeCalc = new TimeCalc();
var Query = SetupQuery();
var bhrdDao = new BhrdDAC(Query);
var rparDao = new RparDAC(Query);
var bsgpDao = new BsgpDAC(Query);
var cmd1 = Query.NewCommand(
@"SELECT A.BPENO, A.BPNME, A.BPEML, A.BPEM2, B.RCC01, B.RCC02, B.RCC07, B.RCC08 ,
C.RAPYN, D.BPPYM
FROM BPSNView A
LEFT JOIN RCRD B ON A.BPENO = B.RCUSR AND B.RCDAT = @DATE
LEFT JOIN RASN C ON A.BPENO = C.RANUM AND (C.RAEDT IS NULL OR (C.RASDT <= @DATE AND C.RAEDT >= @DATE))
LEFT JOIN BPAA D ON C.RAPYN=D.BPPYN
WHERE dbo.EmployeeOnboard(BPENO, @DATE) = 1
");
Query.AddParam(cmd1, "DATE", date);
DataTable tableRcrd = Query.Select(cmd1);
foreach (DataRow rowRcrd in tableRcrd.Rows)
{
var bpeno = WDAC.GetStringValue(rowRcrd["BPENO"]); // 員工編號
var bpnme = WDAC.GetStringValue(rowRcrd["BPNME"]); // 員工姓名
var bpeml = WDAC.GetStringValue(rowRcrd["BPEML"]); // 郵箱1
var bpem2 = WDAC.GetStringValue(rowRcrd["BPEM2"]); // 郵箱2
var rcc01 = WDAC.GetStringValue(rowRcrd["RCC01"]); // 上班打卡
var rcc02 = WDAC.GetStringValue(rowRcrd["RCC02"]); // 下班打卡
var rcc07 = WDAC.GetStringValue(rowRcrd["RCC07"]); // 外出打卡
var rcc08 = WDAC.GetStringValue(rowRcrd["RCC08"]); // 返回打卡
var isDuty = !bhrdDao.IsHoliday(bpeno, date); // 是否需上班
var rapyn = WDAC.GetStringValue(rowRcrd["RAPYN"]); // 派駐專案
var rapym = WDAC.GetStringValue(rowRcrd["BPPYM"]); // 派駐專案名稱
打卡檢查Item checkResult = rparDao.IsPunchcardNormal(date, bpeno, rapyn, isDuty, rcc01, rcc02, rcc07, rcc08);
if (!checkResult.正常)
{
var supervisorItem = supervisorWarning.FirstOrDefault(x => x.專案年度號 == rapyn);
if (supervisorItem == null)
{
supervisorItem = new 通知督導Item()
{
專案年度號 = rapyn,
專案名稱 = rapym
};
// 取得簽核人員第一關與第三關
// BSNME 姓名, BSEML 郵箱
var tableBsgp = bsgpDao.SelectByLevel(rapyn, "差勤", 1);
foreach (DataRow rowBsgp in tableBsgp.Rows)
{
if (supervisorItem.督導List.Find(p => p.督導郵箱 == WDAC.GetStringValue(rowBsgp["BSEML"])) == null)
{
supervisorItem.督導List.Add(new 督導Item()
{
督導姓名 = WDAC.GetStringValue(rowBsgp["BSNME"]),
督導郵箱 = WDAC.GetStringValue(rowBsgp["BSEML"])
});
}
}
tableBsgp = bsgpDao.SelectByLevel(rapyn, "差勤", 3);
foreach (DataRow rowBsgp in tableBsgp.Rows)
{
if (supervisorItem.督導List.Find(p => p.督導郵箱 == WDAC.GetStringValue(rowBsgp["BSEML"])) == null)
{
supervisorItem.督導List.Add(new 督導Item()
{
督導姓名 = WDAC.GetStringValue(rowBsgp["BSNME"]),
督導郵箱 = WDAC.GetStringValue(rowBsgp["BSEML"])
});
}
}
supervisorWarning.Add(supervisorItem);
}
var abnormalItem = new 打卡異常Item()
{
員工編號 = bpeno,
姓名 = bpnme,
日期 = date,
郵箱_1 = bpeml,
// 郵箱_2 = bpem2,
異常訊息 = checkResult.異常訊息
};
supervisorItem.異常List.Add(abnormalItem);
employeeWarning.Add(abnormalItem);
}
}
}
private void CheckPunchCardMonth(DateTime month, ref List<打卡異常Item> employeeWarning, ref List<通知督導Item> supervisorWarning)
{
DateTime date = new DateTime(month.Year, month.Month, 1);
DateTime endDate = date.AddMonths(1);
DateTime today = DateTime.UtcNow.AddHours(8).Date;
while (date < endDate && date < today)
{
CheckPunchCard(date, ref employeeWarning, ref supervisorWarning);
date = date.AddDays(1);
}
}
[WebMethod(EnableSession = true)]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = false)]
public GetDataResponse DoBatchJob(string apiKey, string jobName, string test)
{
WQuery Query = SetupQuery();
if (apiKey != "5D5F88D286A6479889B9DD986419A99C")
{
return new GetDataResponse()
{
Result = 400,
Message = "Unauthorized"
};
}
var today = DateTime.UtcNow.AddHours(8).Date.AddDays(-1);
List<打卡異常Item> employeeWarning = new List<打卡異常Item>();
List<通知督導Item> supervisorWarning = new List<通知督導Item>();
switch (jobName.ToUpper())
{
case "CHECKPUNCHCARD": // 考勤檢查通知個人
CheckPunchCard(today, ref employeeWarning, ref supervisorWarning);
// 發郵件給個人
foreach (var w in employeeWarning)
{
var d = String.Format("{0:yyyy-MM-dd}", w.日期);
MailMessage mm = new MailMessage();
mm.Subject = String.Format("{0} 打卡異常通知", d);
if (!string.IsNullOrEmpty(w.郵箱_1))
{
mm.To.Add(new MailAddress(w.郵箱_1));
}
else
{
continue;
}
mm.BodyEncoding = Encoding.UTF8;
mm.IsBodyHtml = true;
mm.Body = File.ReadAllText(HttpContext.Current.Server.MapPath("~/Template/出勤異常通知.html"))
.Replace("{日期}", d)
.Replace("{異常狀況}", w.異常訊息)
;
// 發送郵件
try
{
Wellan.Service.WMailSender.GetInstance().Send(
mm
, string.Format("打卡異常通知 人員:{0} {1} 日期:{2} 異常:{3}", w.員工編號, w.姓名, d, w.異常訊息));
}
catch
{ }
}
return new GetDataResponse()
{
Result = 0,
// Data = Newtonsoft.Json.JsonConvert.SerializeObject(supervisorWarning)
Data = "OK"
};
case "CHECKPUNCHCARDMONTH": // 考勤檢查通知督導
if (today.AddDays(1).Day != 1 && string.Compare(test, "true") != 0)
{
return new GetDataResponse()
{
Result = 401,
Data = "Not the end of month"
};
}
CheckPunchCardMonth(today, ref employeeWarning, ref supervisorWarning);
byte[] UTF8BOM = new byte[] { 0xEF, 0xBB, 0xBF };
foreach (var w in supervisorWarning)
{
if (w.督導List == null || w.督導List.Count == 0)
{
continue;
}
MailMessage mm = new MailMessage();
mm.Subject = String.Format("{0:yyyy-MM} {1} {2} 專案打卡異常通知", today, w.專案年度號, w.專案名稱);
foreach (var s in w.督導List)
{
if (!string.IsNullOrEmpty(s.督導郵箱)) { mm.To.Add(new MailAddress(s.督導郵箱)); }
}
mm.BodyEncoding = Encoding.UTF8;
mm.IsBodyHtml = true;
mm.Body = File.ReadAllText(HttpContext.Current.Server.MapPath("~/Template/出勤異常督導通知.html"))
.Replace("{年月}", today.ToString("yyyy-MM"))
.Replace("{專案編號}", w.專案年度號)
.Replace("{專案名稱}", w.專案名稱)
;
MemoryStream 出勤異常明細 = new MemoryStream();
出勤異常明細.Write(UTF8BOM, 0, UTF8BOM.Length);
byte[] b = Encoding.UTF8.GetBytes("\"日期\",\"員工編號\",\"姓名\",\"異常訊息\"\r\n");
出勤異常明細.Write(b, 0, b.Length);
foreach (var wp in w.異常List)
{
b = Encoding.UTF8.GetBytes(string.Format("\"{0:yyyy-MM-dd}\",=T(\"{1}\"),\"{2}\",\"{3}\"\r\n"
, wp.日期, wp.員工編號, wp.姓名, wp.異常訊息));
出勤異常明細.Write(b, 0, b.Length);
}
出勤異常明細.Position = 0;
mm.Attachments.Add(new Attachment(出勤異常明細, string.Format(
"打卡異常_{0:yyyy-MM}_{1}_{2}.csv", today, w.專案年度號, w.專案名稱)));
// 發送郵件
try
{
Wellan.Service.WMailSender.GetInstance().Send(
mm
, string.Format("{0:yyyy-MM} {1} {2} 專案打卡異常通知", today, w.專案年度號, w.專案名稱));
}
catch
{ }
}
return new GetDataResponse()
{
Result = 0,
// Data = Newtonsoft.Json.JsonConvert.SerializeObject(supervisorWarning)
Data = "OK"
};
default:
return new GetDataResponse()
{
Result = 401,
Message = "jobName required"
};
}
}
}
[Serializable]
public class 打卡異常Item
{
public string 員工編號 { get; set; }
public string 姓名 { get; set; }
public DateTime 日期 { get; set; }
public string 郵箱_1 { get; set; }
public string 郵箱_2 { get; set; }
public string 異常訊息 { get; set; }
}
public class 督導Item
{
public string 督導姓名 { get; set; }
public string 督導郵箱 { get; set; }
}
public class 通知督導Item
{
public string 專案年度號 { get; set; }
public string 專案名稱 { get; set; }
public List<督導Item> 督導List { get; set; }
public List<打卡異常Item> 異常List { get; set; }
public 通知督導Item()
{
督導List = new List<督導Item>();
異常List = new List<打卡異常Item>();
}
}