| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445 |
- using Microsoft.EntityFrameworkCore;
- using Quartz;
- using System;
- using System.Collections.Generic;
- using System.Data;
- using System.IO;
- using System.Linq;
- using System.Threading.Tasks;
- using wispro.sp.entity;
- using wispro.sp.utility;
- namespace wispro.sp.api.Job
- {
- /// <summary>
- /// 批量更新绩效数据任务
- /// 先从IPEasy批量下载报表数据,然后与本月数据比对更新
- /// 对于报表中不存在的记录,再使用网页抓取方式单独更新
- /// </summary>
- public class BatchUpdateJXDataJob : IJob
- {
- private spDbContext spDb = new spDbContext();
- string strLogFile = null;
- public Task Execute(IJobExecutionContext context)
- {
- strLogFile = null;
- Log($"{DateTime.Now}\t批量更新任务开始");
- try
- {
- // 1. 获取本月需要更新的绩效记录
- var lstItem = spDb.PerformanceItems.Where<PerformanceItem>(p =>
- ((p.AgentFeedbackMemo != "已算绩效" || p.AgentFeedbackMemo == null)
- && p.CalMonth.Status == 0 &&
- !p.CaseNo.StartsWith("J")))
- .Include(p => p.Reviewer)
- .Include(p => p.CalMonth)
- .Include(p => p.Customer)
- .Include(p => p.ItemStaffs).ThenInclude(p => p.DoPerson)
- .ToList<PerformanceItem>();
- if (lstItem == null || lstItem.Count == 0)
- {
- Log($"{DateTime.Now}\t没有需要更新的数据");
- return Task.CompletedTask;
- }
- Log($"{DateTime.Now}\t共需要更新 {lstItem.Count} 条记录");
- // 2. 从IPEasy批量下载报表数据(两个报表)
- DataTable batchData1 = null;
- DataTable batchData2 = null;
-
- try
- {
- Log($"{DateTime.Now}\t开始从IPEasy下载批量报表数据【每月绩效统计--上个月递交完成案件】...");
- batchData1 = IPEasyUtility.DownloadReport("每月绩效统计--上个月递交完成案件", true);
-
- if (batchData1 != null && batchData1.Rows.Count > 0)
- {
- Log($"{DateTime.Now}\t报表1下载成功,共 {batchData1.Rows.Count} 条数据");
- }
- else
- {
- Log($"{DateTime.Now}\t报表1下载失败或无数据");
- }
- }
- catch (Exception ex)
- {
- Log($"{DateTime.Now}\t报表1下载异常: {ex.Message}");
- }
- try
- {
- Log($"{DateTime.Now}\t开始从IPEasy下载批量报表数据【每月绩效统计--中国一次OA授权表】...");
- batchData2 = IPEasyUtility.DownloadReport("每月绩效统计--中国一次OA授权表", true);
-
- if (batchData2 != null && batchData2.Rows.Count > 0)
- {
- Log($"{DateTime.Now}\t报表2下载成功,共 {batchData2.Rows.Count} 条数据");
- }
- else
- {
- Log($"{DateTime.Now}\t报表2下载失败或无数据");
- }
- }
- catch (Exception ex)
- {
- Log($"{DateTime.Now}\t报表2下载异常: {ex.Message}");
- }
- // 3. 合并两个报表数据到统一字典
- Dictionary<string, DataRow> batchDataDict = new Dictionary<string, DataRow>();
-
- // 3.1 处理报表1数据
- if (batchData1 != null && batchData1.Rows.Count > 0)
- {
- foreach (DataRow row in batchData1.Rows)
- {
- try
- {
- string caseNo = row["我方文号"].ToString().Trim();
- string doItem = row["处理事项"].ToString().Trim();
- string key = $"{caseNo}|{doItem}";
- batchDataDict[key] = row;
- }
- catch { }
- }
- Log($"{DateTime.Now}\t报表1数据已加入索引,当前共 {batchDataDict.Count} 个唯一案件");
- }
- // 3.2 处理报表2数据(中国一次OA授权表)
- if (batchData2 != null && batchData2.Rows.Count > 0)
- {
- foreach (DataRow row in batchData2.Rows)
- {
- try
- {
- string caseNo = row["我方文号"].ToString().Trim();
- // 一次OA授权表的处理事项固定为"发明一次OA授权"
- string doItem = "发明一次OA授权";
- string key = $"{caseNo}|{doItem}";
- batchDataDict[key] = row;
- }
- catch { }
- }
- Log($"{DateTime.Now}\t报表2数据已加入索引,当前共 {batchDataDict.Count} 个唯一案件");
- }
- Log($"{DateTime.Now}\t批量数据索引创建完成,总共 {batchDataDict.Count} 个唯一案件");
- // 4. 逐条处理绩效记录
- int totalCount = lstItem.Count;
- int batchMatchCount = 0;
- int singleFetchCount = 0;
- int errorCount = 0;
- for (int i = 0; i < totalCount; i++)
- {
- var item = lstItem[i];
- //调查案不更新
- if (item.CaseNo.Trim().StartsWith("S"))
- {
- Log($"{DateTime.Now}\t[{i + 1}/{totalCount}]\t{item.CaseNo}\t专案忽略!");
- continue;
- }
- System.Threading.Thread.Sleep(100);
- try
- {
- string key = $"{item.CaseNo}|{item.DoItem}";
- bool updated = false;
- // 先尝试从批量数据中匹配
- if (batchDataDict.ContainsKey(key))
- {
- try
- {
- DataRow matchedRow = batchDataDict[key];
- UpdateFromDataRow(item, matchedRow, spDb);
- batchMatchCount++;
- updated = true;
- Log($"{DateTime.Now}\t[{i + 1}/{totalCount}]\t{item.CaseNo}\t批量匹配成功");
- }
- catch (Exception ex)
- {
- Log($"{DateTime.Now}\t[{i + 1}/{totalCount}]\t{item.CaseNo}\t批量更新失败: {ex.Message},尝试单条抓取");
- }
- }
- // 如果批量匹配失败,使用单条抓取
- if (!updated)
- {
- int iTryCount = 0;
- TryAgain:
- try
- {
- iTryCount++;
- UpdateFromIPEasy(item, spDb);
- singleFetchCount++;
- Log($"{DateTime.Now}\t[{i + 1}/{totalCount}]\t{item.CaseNo}\t单条抓取成功");
- }
- catch (Exception ex)
- {
- if (iTryCount <= 3)
- {
- goto TryAgain;
- }
- errorCount++;
- Log($"{DateTime.Now}\t[{i + 1}/{totalCount}]\t{item.CaseNo}\t更新失败: {ex.Message}");
- }
- }
- }
- catch (Exception ex)
- {
- errorCount++;
- Log($"{DateTime.Now}\t[{i + 1}/{totalCount}]\t{item.CaseNo}\t处理异常: {ex.Message}");
- }
- }
- // 5. 输出统计信息
- Log($"{DateTime.Now}\t批量更新任务完成");
- Log($"{DateTime.Now}\t总记录数: {totalCount}");
- Log($"{DateTime.Now}\t批量匹配更新: {batchMatchCount} ({(batchMatchCount * 100.0 / totalCount):F2}%)");
- Log($"{DateTime.Now}\t单条抓取更新: {singleFetchCount} ({(singleFetchCount * 100.0 / totalCount):F2}%)");
- Log($"{DateTime.Now}\t更新失败: {errorCount} ({(errorCount * 100.0 / totalCount):F2}%)");
- }
- catch (Exception ex)
- {
- Log($"{DateTime.Now}\t批量更新任务异常: {ex.ToString()}");
- }
- return Task.CompletedTask;
- }
- /// <summary>
- /// 从DataRow更新绩效记录(批量数据)
- /// </summary>
- private void UpdateFromDataRow(PerformanceItem item, DataRow row, spDbContext spDb)
- {
- var appealAJXS = spDb.AppealTypes.FirstOrDefault(p => p.Name.Contains("案件系数"));
- var appealCLSXXS = spDb.AppealTypes.FirstOrDefault(p => p.Name.Contains("处理事项系数"));
- var caseXS = (spDb.AppealRecords.FirstOrDefault(p => p.ItemId == item.Id && p.TypeId == appealAJXS.Id && p.State == 1) == null);
- var doItemXS = (spDb.AppealRecords.FirstOrDefault(p => p.ItemId == item.Id && p.TypeId == appealCLSXXS.Id && p.State == 1) == null);
- // 处理事项系数
- if (row.Table.Columns.Contains("处理事项系数") && doItemXS)
- {
- string doItemCoef = row["处理事项系数"].ToString().Trim();
- if (!string.IsNullOrEmpty(doItemCoef) && item.DoItemCoefficient != doItemCoef)
- {
- item.DoItemCoefficient = doItemCoef;
- }
- }
- // 翻译字数
- if (row.Table.Columns.Contains("翻译字数"))
- {
- string wordCountStr = row["翻译字数"].ToString().Trim();
- if (!string.IsNullOrEmpty(wordCountStr))
- {
- if (int.TryParse(wordCountStr, out int wordCount))
- {
- if (wordCount != item.WordCount)
- {
- item.WordCount = wordCount;
- }
- }
- }
- }
- // 核稿人
- if (row.Table.Columns.Contains("案件核稿人"))
- {
- string reviewer = row["案件核稿人"].ToString().Trim();
- if (!string.IsNullOrEmpty(reviewer) && (item.Reviewer == null || item.Reviewer.Name != reviewer))
- {
- string temName = reviewer.Split('-')[0].Trim();
- if (!reviewer.Contains("君龙"))
- {
- temName = reviewer;
- }
- var temReviewer = spDb.Staffs.Where<Staff>(s => s.Name == temName).FirstOrDefault();
- if (temReviewer != null)
- {
- item.ReviewerId = temReviewer.Id;
- }
- }
- }
- // 申请类型
- if (row.Table.Columns.Contains("申请类型"))
- {
- string applicationType = row["申请类型"].ToString().Trim();
- if (!string.IsNullOrEmpty(applicationType) && item.ApplicationType != applicationType)
- {
- item.ApplicationType = applicationType;
- }
- }
- // 案件系数
- if (row.Table.Columns.Contains("案件系数") && caseXS)
- {
- string caseCoef = row["案件系数"].ToString().Trim();
- if (!string.IsNullOrEmpty(caseCoef) && item.CaseCoefficient != caseCoef)
- {
- item.CaseCoefficient = caseCoef;
- }
- }
- // 案件类型
- if (row.Table.Columns.Contains("案件类型"))
- {
- string caseType = row["案件类型"].ToString().Trim();
- if (!string.IsNullOrEmpty(caseType) && item.CaseType != caseType)
- {
- item.CaseType = caseType;
- }
- }
- // 案件阶段
- if (row.Table.Columns.Contains("案件阶段"))
- {
- string caseStage = row["案件阶段"].ToString().Trim();
- if (!string.IsNullOrEmpty(caseStage) && item.CaseStage != caseStage)
- {
- item.CaseStage = caseStage;
- }
- }
- // 如果有变化,重新计算绩效点
- if (spDb.Entry(item).State != EntityState.Unchanged)
- {
- if (item.AgentFeedbackMemo != "特殊点数申诉")
- {
- new Controllers.PerformanceItemController(spDb, new Services.FileTaskCacheService()).RefreshPoint(item);
- }
- else
- {
- // 特殊点数申诉:只保存字段更新,不重算点数
- spDb.SaveChanges();
- }
- }
- }
- /// <summary>
- /// 从IPEasy单条抓取更新(网页抓取)
- /// </summary>
- private void UpdateFromIPEasy(PerformanceItem item, spDbContext spDb)
- {
- dynamic retObj = IPEasyUtility.GetPerformanceRecord(item.CaseNo, item.DoItem, item.CaseStage);
- var appealAJXS = spDb.AppealTypes.FirstOrDefault(p => p.Name.Contains("案件系数"));
- var appealCLSXXS = spDb.AppealTypes.FirstOrDefault(p => p.Name.Contains("处理事项系数"));
- var caseXS = (spDb.AppealRecords.FirstOrDefault(p => p.ItemId == item.Id && p.TypeId == appealAJXS.Id && p.State == 1) == null);
- var doItemXS = (spDb.AppealRecords.FirstOrDefault(p => p.ItemId == item.Id && p.TypeId == appealCLSXXS.Id && p.State == 1) == null);
- IDictionary<String, Object> keyValuePairs = (IDictionary<String, Object>)retObj;
- if (keyValuePairs.ContainsKey("DoItemCoefficient") && item.DoItemCoefficient != retObj.DoItemCoefficient && doItemXS)
- {
- item.DoItemCoefficient = retObj.DoItemCoefficient;
- }
- if (keyValuePairs.ContainsKey("WordCount"))
- {
- if (!string.IsNullOrEmpty(retObj.WordCount))
- {
- var wordCount = int.Parse(retObj.WordCount);
- if (wordCount != item.WordCount)
- item.WordCount = wordCount;
- }
- }
- if (keyValuePairs.ContainsKey("Reviewer") && (item.Reviewer == null || item.Reviewer.Name != retObj.Reviewer) && !string.IsNullOrEmpty(retObj.Reviewer))
- {
- string name = retObj.Reviewer;
- if (!string.IsNullOrEmpty(name))
- {
- string temName = name.Split('-')[0].Trim();
- if (!name.Contains("君龙"))
- {
- temName = name;
- }
- var temReviewer = spDb.Staffs.Where<Staff>(s => s.Name == temName).FirstOrDefault();
- if (temReviewer != null)
- {
- item.ReviewerId = temReviewer.Id;
- }
- }
- }
- if (keyValuePairs.ContainsKey("ExternalHandler") && (item.ExternalHandler == null || item.ExternalHandler.Name != retObj.ExternalHandler) && !string.IsNullOrEmpty(retObj.ExternalHandler))
- {
- string name = retObj.ExternalHandler;
- if (!string.IsNullOrEmpty(name))
- {
- string temName = name.Split('-')[0].Trim();
- if (!name.Contains("君龙"))
- {
- temName = name;
- }
- var temExternalHandler = spDb.Staffs.Where<Staff>(s => s.Name == temName).FirstOrDefault();
- if (temExternalHandler != null)
- {
- item.ExternalHandlerId = temExternalHandler.Id;
- }
- }
- }
- if (keyValuePairs.ContainsKey("ApplicationType") && item.ApplicationType != retObj.ApplicationType && !string.IsNullOrEmpty(retObj.ApplicationType))
- {
- item.ApplicationType = retObj.ApplicationType;
- }
- if (keyValuePairs.ContainsKey("CaseCoefficient") && item.CaseCoefficient != retObj.CaseCoefficient && caseXS)
- {
- if (!(retObj.CaseCoefficient == null && string.IsNullOrEmpty(item.CaseCoefficient)))
- item.CaseCoefficient = retObj.CaseCoefficient;
- }
- if (keyValuePairs.ContainsKey("CaseType") && item.CaseType != retObj.CaseType && !string.IsNullOrEmpty(retObj.CaseType))
- {
- item.CaseType = retObj.CaseType;
- }
- if (keyValuePairs.ContainsKey("CaseStage") && item.CaseStage != retObj.CaseStage && !string.IsNullOrEmpty(retObj.CaseStage))
- {
- item.CaseStage = retObj.CaseStage;
- }
- if (spDb.Entry(item).State != EntityState.Unchanged)
- {
- if (item.AgentFeedbackMemo != "特殊点数申诉")
- {
- new Controllers.PerformanceItemController(spDb, new Services.FileTaskCacheService()).RefreshPoint(item);
- }
- else
- {
- // 特殊点数申诉:只保存字段更新,不重算点数
- spDb.SaveChanges();
- }
- }
- }
- private void Log(string strMessage)
- {
- try
- {
- if(string.IsNullOrEmpty(strLogFile))
- {
- strLogFile = $"c:\\temp\\{DateTime.Now.ToString("yyyyMMdd")}-Batch_Update_log.txt";
- }
- StreamWriter sw = File.AppendText(strLogFile);
- sw.WriteLine($"{strMessage}");
- sw.Flush();
- sw.Close();
- sw.Dispose();
- }
- catch { }
- }
- }
- }
|