WorkDaySupplier.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. using Hotline.Caching.Interfaces;
  2. using Hotline.Settings.TimeLimits;
  3. using Hotline.Share.Dtos.Settings;
  4. using System.ComponentModel.DataAnnotations;
  5. using XF.Domain.Dependency;
  6. namespace Hotline.Settings.TimeLimitDomain.ExpireTimeSupplier;
  7. public class WorkDaySupplier : IExpireTimeSupplier, IScopeDependency
  8. {
  9. private readonly IDaySettingCacheManager _daySettingCacheManager;
  10. public WorkDaySupplier(IDaySettingCacheManager daySettingCacheManager)
  11. {
  12. _daySettingCacheManager = daySettingCacheManager;
  13. }
  14. //public async Task<TimeResult> CalcEndTimeAsync(DateTime beginTime, TimeConfig timeConfig)
  15. //{
  16. // var startTime = beginTime;
  17. // var startTimeOne = beginTime;
  18. // if (timeConfig.WorkTime == null)
  19. // return new TimeResult { EndTime = beginTime, RuleStr = timeConfig.Count + "个工作日", NearlyExpiredTime = beginTime, NearlyExpiredTimeOne = beginTime };
  20. // //检查时间段内是否存在休息日或者工作日
  21. // //查询统一部门工作时间
  22. // //计算一天工作时间(分钟)
  23. // DateTime WorkBeginTime = DateTime.Parse(beginTime.ToShortDateString() + " " + timeConfig.WorkTime[0] + ":00");
  24. // DateTime WorkEndTime = DateTime.Parse(beginTime.ToShortDateString() + " " + timeConfig.WorkTime[1] + ":00");
  25. // //计算一天多少个工作小时
  26. // var duration = WorkEndTime - WorkBeginTime;
  27. // double workMinutes = duration.TotalMinutes;
  28. // double totalWorkMinutes = (workMinutes * timeConfig.Count) * (timeConfig.Percentage / 100.00);
  29. // double totalWorkMinutesOne = (workMinutes * timeConfig.Count) * (timeConfig.PercentageOne / 100.00);
  30. // //判断开始时间不在工时间段修正时间复位至当天或者第二天的开始时间(如果大于结束时间则复位至第二天的开始时间)
  31. // if (beginTime < WorkBeginTime)
  32. // {
  33. // beginTime = WorkBeginTime;
  34. // }
  35. // else
  36. // {
  37. // if (beginTime > WorkEndTime)
  38. // {
  39. // beginTime = WorkBeginTime.AddDays(1);
  40. // }
  41. // if (await NotWorkDay(beginTime))
  42. // {
  43. // beginTime = WorkBeginTime.AddDays(1);
  44. // }
  45. // }
  46. // while (true)
  47. // {
  48. // if (await IsWorkDay(beginTime))
  49. // {
  50. // break;
  51. // }
  52. // beginTime = beginTime.AddDays(1);
  53. // }
  54. // int day = 1;
  55. // for (int i = 1;i < timeConfig.Count+1;i++)
  56. // {
  57. // if (await IsWorkDay(beginTime.AddDays(day)))
  58. // {
  59. // beginTime = beginTime.AddDays(day);
  60. // if (totalWorkMinutes >= workMinutes)
  61. // {
  62. // startTime = startTime.AddDays(day);
  63. // totalWorkMinutes = totalWorkMinutes - workMinutes;
  64. // }
  65. // else if (totalWorkMinutes < workMinutes && totalWorkMinutes != 0)
  66. // {
  67. // if (startTime.AddMinutes(totalWorkMinutes) > DateTime.Parse(startTime.ToShortDateString() + " " + timeConfig.WorkTime[1] + ":00"))
  68. // {
  69. // totalWorkMinutes = totalWorkMinutes - ((DateTime.Parse(startTime.ToShortDateString() + " " + timeConfig.WorkTime[1] + ":00") - startTime).TotalMinutes);
  70. // startTime = startTime.AddDays(day);
  71. // startTime = DateTime.Parse(startTime.ToShortDateString() + " " + timeConfig.WorkTime[0] + ":00").AddMinutes(totalWorkMinutes);
  72. // totalWorkMinutes = 0;
  73. // }
  74. // else
  75. // {
  76. // startTime = startTime.AddMinutes(totalWorkMinutes);
  77. // }
  78. // }
  79. // if (totalWorkMinutesOne >= workMinutes)
  80. // {
  81. // startTimeOne = startTimeOne.AddDays(day);
  82. // totalWorkMinutesOne = totalWorkMinutesOne - workMinutes;
  83. // }
  84. // else if (totalWorkMinutesOne < workMinutes && totalWorkMinutesOne != 0)
  85. // {
  86. // if (startTimeOne.AddMinutes(totalWorkMinutesOne) > DateTime.Parse(startTimeOne.ToShortDateString() + " " + timeConfig.WorkTime[1] + ":00"))
  87. // {
  88. // totalWorkMinutesOne = totalWorkMinutesOne - ((DateTime.Parse(startTimeOne.ToShortDateString() + " " + timeConfig.WorkTime[1] + ":00") - startTimeOne).TotalMinutes);
  89. // startTimeOne = startTimeOne.AddDays(day);
  90. // startTimeOne = DateTime.Parse(startTimeOne.ToShortDateString() + " " + timeConfig.WorkTime[0] + ":00").AddMinutes(totalWorkMinutesOne);
  91. // totalWorkMinutesOne = 0;
  92. // }
  93. // else
  94. // {
  95. // startTimeOne = startTimeOne.AddMinutes(totalWorkMinutesOne);
  96. // }
  97. // }
  98. // day = 1;
  99. // }
  100. // else
  101. // {
  102. // i--;
  103. // day++;
  104. // }
  105. // }
  106. // return new TimeResult { EndTime = beginTime, RuleStr = timeConfig.Count + "个工作日", NearlyExpiredTime = startTime, NearlyExpiredTimeOne = startTimeOne };
  107. //}
  108. /// <summary>
  109. /// 计算超期时间(新)
  110. /// </summary>
  111. /// <param name="beginTime"></param>
  112. /// <param name="timeConfig"></param>
  113. /// <returns></returns>
  114. public async Task<TimeResult> CalcEndTimeNewAsync(DateTime beginTime,DateTime startTime,TimeConfig timeConfig)
  115. {
  116. //------------------------------New
  117. var isWorkSend = await IsWorkDay(beginTime);
  118. var startTimeOne = startTime;//即将超期时间50%;
  119. if (timeConfig.WorkTime == null) //如果没有对应配置
  120. return new TimeResult { EndTime = beginTime, RuleStr = timeConfig.Count + "个工作日", NearlyExpiredTime = beginTime, NearlyExpiredTimeOne = beginTime };
  121. //查询统一部门工作时间
  122. DateTime WorkBeginTime = DateTime.Parse(beginTime.ToShortDateString() + " " + timeConfig.WorkTime[0] + ":00");
  123. DateTime WorkEndTime = DateTime.Parse(beginTime.ToShortDateString() + " " + timeConfig.WorkTime[1] + ":00");
  124. if (timeConfig.EndType == null)
  125. {
  126. timeConfig.EndType = 1;
  127. }
  128. //获取期满时间收尾方式
  129. var endType = timeConfig.EndType;
  130. switch (endType)
  131. {
  132. case 0:
  133. if (!isWorkSend)
  134. {
  135. beginTime = WorkBeginTime;
  136. }
  137. int q = timeConfig.Count;
  138. while (true && q != 0)
  139. {
  140. if (await IsWorkDay(beginTime))
  141. {
  142. beginTime = beginTime.AddDays(1);
  143. q--;
  144. }
  145. else
  146. {
  147. beginTime = beginTime.AddDays(1);
  148. }
  149. }
  150. beginTime = beginTime.AddSeconds(-1);
  151. while (true)
  152. {
  153. if (await IsWorkDay(beginTime))
  154. {
  155. break;
  156. }
  157. else
  158. {
  159. beginTime = beginTime.AddDays(1);
  160. }
  161. }
  162. var sconds = (beginTime - startTime).TotalSeconds * (timeConfig.Percentage / 100.00);
  163. startTime = startTime.AddSeconds(sconds);
  164. var scondsOne = (beginTime - startTimeOne).TotalSeconds * (timeConfig.PercentageOne / 100.00);
  165. startTimeOne = startTimeOne.AddSeconds(scondsOne);
  166. break;
  167. case 1:
  168. //计算一天多少个工作小时
  169. var durationType1 = WorkEndTime - WorkBeginTime;
  170. double workMinutesType1 = durationType1.TotalMinutes;
  171. #region 计算期满时间
  172. if (!isWorkSend)
  173. {
  174. beginTime = WorkBeginTime;
  175. startTime = WorkBeginTime;
  176. startTimeOne = WorkBeginTime;
  177. }
  178. while (true)
  179. {
  180. if (!await IsWorkDay(beginTime))
  181. beginTime = beginTime.AddDays(1);
  182. else
  183. break;
  184. }
  185. int w = timeConfig.Count;
  186. int days = 1;
  187. while (true && w != 0)
  188. {
  189. if (await IsWorkDay(beginTime.AddDays(days)))
  190. {
  191. beginTime = beginTime.AddDays(days);
  192. w--;
  193. days = 1;
  194. }
  195. else
  196. {
  197. //beginTime = beginTime.AddDays(1);
  198. days++;
  199. }
  200. }
  201. beginTime = beginTime.AddSeconds(-1);
  202. while (true)
  203. {
  204. if (await IsWorkDay(beginTime))
  205. {
  206. if (beginTime < DateTime.Parse(beginTime.ToShortDateString() + " " + timeConfig.WorkTime[0] + ":00"))
  207. {
  208. beginTime = DateTime.Parse(beginTime.AddDays(-1).ToShortDateString() + " " + timeConfig.WorkTime[1] + ":00");
  209. }
  210. else
  211. {
  212. break;
  213. }
  214. }
  215. else if (!await IsWorkDay(beginTime))
  216. {
  217. beginTime = DateTime.Parse(beginTime.AddDays(-1).ToShortDateString() + " " + timeConfig.WorkTime[1] + ":00");
  218. }
  219. //else
  220. //{
  221. // beginTime = beginTime.AddDays(1);
  222. //}
  223. }
  224. #endregion
  225. var dayIndex = 1;
  226. var configCount = 1;
  227. while(true)
  228. {
  229. if (startTime.AddDays(dayIndex).Date!= beginTime.Date)
  230. {
  231. if (await IsWorkDay(startTime.AddDays(dayIndex)))
  232. {
  233. configCount++;
  234. }
  235. dayIndex++;
  236. }
  237. else
  238. {
  239. break;
  240. }
  241. }
  242. double totalWorkMinutesType1 = (workMinutesType1 * configCount) * (timeConfig.Percentage / 100.00);
  243. double totalWorkMinutesOneType1 = (workMinutesType1 * configCount) * (timeConfig.PercentageOne / 100.00);
  244. //计算即将超期时间
  245. while (true)
  246. {
  247. if (!await IsWorkDay(startTime))
  248. startTime = startTime.AddDays(1);
  249. else
  250. break;
  251. }
  252. days = 1;
  253. while (true && totalWorkMinutesType1 != 0)
  254. {
  255. if (await IsWorkDay(startTime.AddDays(days)))
  256. {
  257. if (totalWorkMinutesType1 > workMinutesType1)
  258. {
  259. startTime = startTime.AddDays(days);
  260. totalWorkMinutesType1 = totalWorkMinutesType1 - workMinutesType1;
  261. days = 1;
  262. }
  263. else
  264. {
  265. if (startTime.AddMinutes(totalWorkMinutesType1) > DateTime.Parse(startTime.ToShortDateString() + " " + timeConfig.WorkTime[1] + ":00"))
  266. {
  267. totalWorkMinutesType1 = totalWorkMinutesType1 - ((DateTime.Parse(startTime.ToShortDateString() + " " + timeConfig.WorkTime[1] + ":00") - startTime).TotalMinutes);
  268. startTime = startTime.AddDays(days);
  269. startTime = DateTime.Parse(startTime.ToShortDateString() + " " + timeConfig.WorkTime[0] + ":00").AddMinutes(totalWorkMinutesType1);
  270. totalWorkMinutesType1 = 0;
  271. days = 1;
  272. }
  273. else
  274. {
  275. startTime = startTime.AddMinutes(totalWorkMinutesType1);
  276. totalWorkMinutesType1 = 0;
  277. days = 1;
  278. }
  279. }
  280. }
  281. else
  282. {
  283. days++;
  284. }
  285. }
  286. //计算50%即将超期时间
  287. while (true)
  288. {
  289. if (!await IsWorkDay(startTimeOne))
  290. startTimeOne = startTimeOne.AddDays(1);
  291. else
  292. break;
  293. }
  294. days = 1;
  295. while (true && totalWorkMinutesOneType1 != 0)
  296. {
  297. if (await IsWorkDay(startTimeOne.AddDays(days)))
  298. {
  299. if (totalWorkMinutesOneType1 > workMinutesType1)
  300. {
  301. startTimeOne = startTimeOne.AddDays(days);
  302. totalWorkMinutesOneType1 = totalWorkMinutesOneType1 - workMinutesType1;
  303. days = 1;
  304. }
  305. else if (totalWorkMinutesOneType1 <= workMinutesType1)
  306. {
  307. if (startTimeOne.AddMinutes(totalWorkMinutesOneType1) > DateTime.Parse(startTimeOne.ToShortDateString() + " " + timeConfig.WorkTime[1] + ":00"))
  308. {
  309. totalWorkMinutesOneType1 = totalWorkMinutesOneType1 - ((DateTime.Parse(startTimeOne.ToShortDateString() + " " + timeConfig.WorkTime[1] + ":00") - startTimeOne).TotalMinutes);
  310. startTimeOne = startTimeOne.AddDays(days);
  311. startTimeOne = DateTime.Parse(startTimeOne.ToShortDateString() + " " + timeConfig.WorkTime[0] + ":00").AddMinutes(totalWorkMinutesOneType1);
  312. totalWorkMinutesOneType1 = 0;
  313. days = 1;
  314. }
  315. else
  316. {
  317. startTimeOne = startTimeOne.AddMinutes(totalWorkMinutesOneType1);
  318. totalWorkMinutesOneType1 = 0;
  319. days = 1;
  320. }
  321. }
  322. }
  323. else
  324. {
  325. days++;
  326. }
  327. }
  328. break;
  329. case 2:
  330. //期满时间注释延用老时间
  331. //startTime = beginTime;
  332. //startTimeOne = beginTime;
  333. //计算一天多少个工作小时
  334. var duration = WorkEndTime - WorkBeginTime;
  335. double workMinutes = duration.TotalMinutes;
  336. double totalWorkMinutes = (workMinutes * timeConfig.Count) * (timeConfig.Percentage / 100.00);
  337. double totalWorkMinutesOne = (workMinutes * timeConfig.Count) * (timeConfig.PercentageOne / 100.00);
  338. //判断开始时间不在工时间段修正时间复位至当天或者第二天的开始时间(如果大于结束时间则复位至第二天的开始时间)
  339. if (beginTime < WorkBeginTime)
  340. {
  341. beginTime = WorkBeginTime;
  342. }
  343. else
  344. {
  345. if (beginTime > WorkEndTime)
  346. {
  347. beginTime = WorkBeginTime.AddDays(1);
  348. }
  349. if (await NotWorkDay(beginTime))
  350. {
  351. beginTime = WorkBeginTime.AddDays(1);
  352. }
  353. }
  354. while (true)
  355. {
  356. if (await IsWorkDay(beginTime))
  357. {
  358. break;
  359. }
  360. beginTime = beginTime.AddDays(1);
  361. }
  362. int day = 1;
  363. for (int i = 1; i < timeConfig.Count + 1; i++)
  364. {
  365. if (await IsWorkDay(beginTime.AddDays(day)))
  366. {
  367. beginTime = beginTime.AddDays(day);
  368. if (totalWorkMinutes >= workMinutes)
  369. {
  370. startTime = startTime.AddDays(day);
  371. totalWorkMinutes = totalWorkMinutes - workMinutes;
  372. }
  373. else if (totalWorkMinutes < workMinutes && totalWorkMinutes != 0)
  374. {
  375. if (startTime.AddMinutes(totalWorkMinutes) > DateTime.Parse(startTime.ToShortDateString() + " " + timeConfig.WorkTime[1] + ":00"))
  376. {
  377. totalWorkMinutes = totalWorkMinutes - ((DateTime.Parse(startTime.ToShortDateString() + " " + timeConfig.WorkTime[1] + ":00") - startTime).TotalMinutes);
  378. startTime = startTime.AddDays(day);
  379. startTime = DateTime.Parse(startTime.ToShortDateString() + " " + timeConfig.WorkTime[0] + ":00").AddMinutes(totalWorkMinutes);
  380. totalWorkMinutes = 0;
  381. }
  382. else
  383. {
  384. startTime = startTime.AddMinutes(totalWorkMinutes);
  385. }
  386. }
  387. if (totalWorkMinutesOne >= workMinutes)
  388. {
  389. startTimeOne = startTimeOne.AddDays(day);
  390. totalWorkMinutesOne = totalWorkMinutesOne - workMinutes;
  391. }
  392. else if (totalWorkMinutesOne < workMinutes && totalWorkMinutesOne != 0)
  393. {
  394. if (startTimeOne.AddMinutes(totalWorkMinutesOne) > DateTime.Parse(startTimeOne.ToShortDateString() + " " + timeConfig.WorkTime[1] + ":00"))
  395. {
  396. totalWorkMinutesOne = totalWorkMinutesOne - ((DateTime.Parse(startTimeOne.ToShortDateString() + " " + timeConfig.WorkTime[1] + ":00") - startTimeOne).TotalMinutes);
  397. startTimeOne = startTimeOne.AddDays(day);
  398. startTimeOne = DateTime.Parse(startTimeOne.ToShortDateString() + " " + timeConfig.WorkTime[0] + ":00").AddMinutes(totalWorkMinutesOne);
  399. totalWorkMinutesOne = 0;
  400. }
  401. else
  402. {
  403. startTimeOne = startTimeOne.AddMinutes(totalWorkMinutesOne);
  404. }
  405. }
  406. day = 1;
  407. }
  408. else
  409. {
  410. i--;
  411. day++;
  412. }
  413. }
  414. break;
  415. case 3:
  416. break;
  417. default:
  418. break;
  419. }
  420. return new TimeResult { EndTime = beginTime, RuleStr = timeConfig.Count + "个工作日", NearlyExpiredTime = startTime, NearlyExpiredTimeOne = startTimeOne };
  421. }
  422. /// <summary>
  423. /// 是否是工作日
  424. /// 根据数据库的工作日和周末时间判断
  425. /// </summary>
  426. /// <param name="date"></param>
  427. /// <returns></returns>
  428. private async Task<bool> IsWorkDay(DateTime date)
  429. {
  430. return _daySettingCacheManager.IsWorkDay(date);
  431. }
  432. private async Task<bool> NotWorkDay(DateTime date)
  433. {
  434. return !await IsWorkDay(date);
  435. }
  436. }