ExamSpecialStudentAuditService.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. using Furion.DatabaseAccessor.Extensions;
  2. using YBEE.EQM.Core;
  3. namespace YBEE.EQM.Application;
  4. /// <summary>
  5. /// 特殊学生审核服务
  6. /// </summary>
  7. public class ExamSpecialStudentAuditService(IRepository<ExamSpecialStudent> rep, ISysRoleService sysRoleService) : IExamSpecialStudentAuditService, ITransient
  8. {
  9. /// <summary>
  10. /// 提交审核
  11. /// </summary>
  12. /// <param name="input"></param>
  13. /// <returns></returns>
  14. public async Task Submit(BaseId input)
  15. {
  16. var item = await rep.FirstOrDefaultAsync(t => t.Id == input.Id) ?? throw Oops.Oh(ErrorCode.E2001);
  17. var dtype = await rep.Change<ExamDataReport>().Where(t => t.ExamPlanId == item.ExamPlanId && t.Type == DataReportType.SP_STUDENT).FirstOrDefaultAsync();
  18. if (dtype == null || dtype.Status != ExamStatus.ACTIVE || (item.Status != AuditStatus.UNSUBMIT && item.Status != AuditStatus.REJECTED))
  19. {
  20. throw Oops.Oh(ErrorCode.E2006);
  21. }
  22. item.Status = AuditStatus.AUDIT;
  23. item.Audits = AuditUtil.InsertInto(item.Audits, AuditUtil.CreateNew(AuditActionType.SUBMIT, item.Status));
  24. await item.UpdateAsync();
  25. }
  26. /// <summary>
  27. /// 审核
  28. /// </summary>
  29. /// <param name="input"></param>
  30. /// <returns></returns>
  31. public async Task Audit(ExamSepcialStudentAuditInput input)
  32. {
  33. var dt = DateTime.Now;
  34. var items = await rep.Where(t => input.Ids.Contains(t.Id)).ToListAsync();
  35. foreach (var item in items)
  36. {
  37. item.Status = input.IsApproved ? AuditStatus.APPROVED : AuditStatus.REJECTED;
  38. item.Audits = AuditUtil.InsertInto(item.Audits, AuditUtil.CreateNew(input.IsApproved ? AuditActionType.APPROVE : AuditActionType.REJECT, item.Status, dt, input.Remark));
  39. }
  40. await rep.UpdateAsync(items);
  41. }
  42. /// <summary>
  43. /// 反审
  44. /// </summary>
  45. /// <param name="input"></param>
  46. /// <returns></returns>
  47. public async Task Reaudit(BaseId input)
  48. {
  49. var item = await rep.FirstOrDefaultAsync(t => t.Id == input.Id) ?? throw Oops.Oh(ErrorCode.E2001);
  50. if (item.Status != AuditStatus.APPROVED)
  51. {
  52. throw Oops.Oh(ErrorCode.E2006);
  53. }
  54. item.Status = AuditStatus.APPROVE_CANCELED;
  55. item.Audits = AuditUtil.InsertInto(item.Audits, AuditUtil.CreateNew(AuditActionType.REAUDIT, item.Status));
  56. await item.UpdateAsync();
  57. }
  58. //public async Task<byte[]> ExportAll(int examPlanId)
  59. //{
  60. //}
  61. /// <summary>
  62. /// 获取待审核监测计划列表
  63. /// </summary>
  64. /// <param name="input"></param>
  65. /// <returns></returns>
  66. public async Task<PageResult<ExamPlanAuditOutput>> QueryExamPlanPageList(ExamPlanPageInput input)
  67. {
  68. var roleDataScope = await sysRoleService.GetCurrentUserDataScope();
  69. if (roleDataScope == null || roleDataScope.EducationStages.Count == 0)
  70. {
  71. return new();
  72. }
  73. List<string> whereCause = new();
  74. if (roleDataScope.EducationStages.Count == 0)
  75. {
  76. whereCause.Add($"T1.education_stage = {(short)roleDataScope.EducationStages[0]}");
  77. }
  78. else
  79. {
  80. var ess = roleDataScope.EducationStages.Select(t => $"T1.education_stage = {(short)t}").ToList();
  81. string wes = string.Join(" OR ", ess);
  82. whereCause.Add($"({wes})");
  83. }
  84. if (!string.IsNullOrEmpty(input.Name?.Trim()))
  85. {
  86. whereCause.Add("T1.full_name LIKE '%@name%'");
  87. }
  88. if (input.SemesterId.HasValue)
  89. {
  90. whereCause.Add("T1.semester_id = @semesterId");
  91. }
  92. if (input.Status.HasValue)
  93. {
  94. whereCause.Add("T1.status = @status");
  95. }
  96. string whereSql = $"WHERE (T1.`status` = {(short)ExamStatus.ACTIVE} OR T1.`status` = {(short)ExamStatus.STOPPED}) AND T1.is_deleted = 0 AND EDR.type = {(short)DataReportType.SP_STUDENT}";
  97. if (whereCause.Count > 0)
  98. {
  99. whereSql = $"{whereSql} AND {string.Join(" AND ", whereCause)}";
  100. }
  101. var p = new
  102. {
  103. input.PageSize,
  104. PageOffset = (input.PageIndex - 1) * input.PageSize,
  105. Type = DataReportType.SP_STUDENT,
  106. input.SemesterId,
  107. input.Status,
  108. input.Name,
  109. };
  110. var totalCount = await rep.SqlScalarAsync<int>($@"
  111. SELECT COUNT(1) AS total_count
  112. FROM
  113. (
  114. SELECT T1.id, COUNT(T1.sys_org_id) AS org_count
  115. FROM
  116. (
  117. SELECT T1.id, T2.sys_org_id
  118. FROM exam_plan AS T1
  119. JOIN exam_data_report AS EDR ON T1.id = EDR.exam_plan_id
  120. LEFT JOIN exam_org AS T2 ON T1.id = T2.exam_plan_id
  121. {whereSql}
  122. GROUP BY T1.id, t2.sys_org_id
  123. ) AS T1
  124. GROUP BY T1.id
  125. ) AS T
  126. ", p);
  127. var items = await rep.SqlQueriesAsync<ExamPlanAuditOutput>($@"
  128. SELECT
  129. T1.id,
  130. T1.full_name,
  131. T1.short_name,
  132. T1.`name`,
  133. T1.semester_id,
  134. T1.education_stage,
  135. T1.`status`,
  136. COUNT(DISTINCT T1.sys_org_id) AS org_count,
  137. SUM(T1.total_count) AS total_count,
  138. SUM(T1.audit_count) AS audit_count,
  139. SUM(T1.approved_count) AS approved_count,
  140. SUM(T1.rejected_count) AS rejected_count,
  141. SUM(T1.pre_identified_count) AS pre_identified_count
  142. FROM
  143. (
  144. SELECT
  145. T1.id,
  146. T1.full_name,
  147. T1.short_name,
  148. T1.`name`,
  149. T1.semester_id,
  150. T1.education_stage,
  151. T1.`status`,
  152. T2.sys_org_id,
  153. COUNT(CASE WHEN T3.`status` = {(short)DataReportStatus.REPORTED} OR T3.`status` = {(short)DataReportStatus.REJECTED} THEN T4.id ELSE NULL END) AS total_count,
  154. COUNT(CASE WHEN (T3.`status` = {(short)DataReportStatus.REPORTED} OR T3.`status` = {(short)DataReportStatus.REJECTED}) AND (T4.`status` ={(short)AuditStatus.AUDIT} OR T4.`status` = {(short)AuditStatus.APPROVE_CANCELED}) THEN T4.id ELSE NULL END) AS audit_count,
  155. COUNT(CASE WHEN (T3.`status` = {(short)DataReportStatus.REPORTED} OR T3.`status` = {(short)DataReportStatus.REJECTED}) AND T4.`status` = {(short)AuditStatus.APPROVED} THEN T4.id ELSE NULL END) AS approved_count,
  156. COUNT(CASE WHEN (T3.`status` = {(short)DataReportStatus.REPORTED} OR T3.`status` = {(short)DataReportStatus.REJECTED}) AND T4.`status` = {(short)AuditStatus.REJECTED} THEN T4.id ELSE NULL END) AS rejected_count,
  157. COUNT(CASE WHEN (T3.`status` = {(short)DataReportStatus.REPORTED} OR T3.`status` = {(short)DataReportStatus.REJECTED}) AND T4.is_pre_identified = 1 THEN T4.id ELSE NULL END) AS pre_identified_count
  158. FROM exam_plan AS T1
  159. JOIN exam_data_report AS EDR ON T1.id = EDR.exam_plan_id
  160. LEFT JOIN exam_org AS T2 ON T1.id = T2.exam_plan_id
  161. LEFT JOIN (SELECT * FROM exam_org_data_report WHERE type = {(short)DataReportType.SP_STUDENT}) AS T3 ON T2.id = T3.exam_org_id AND EDR.type = T3.type
  162. LEFT JOIN exam_special_student AS T4 ON T1.id = T4.exam_plan_id AND T2.sys_org_id = T4.sys_org_id
  163. {whereSql}
  164. GROUP BY T1.id, T1.full_name, T1.short_name, T1.`name`, T1.semester_id, T1.education_stage, T1.`status`, T2.sys_org_id
  165. ) AS T1
  166. GROUP BY T1.id, T1.full_name, T1.short_name, T1.`name`, T1.semester_id, T1.education_stage, T1.`status`
  167. ORDER BY T1.id DESC
  168. LIMIT @pageSize OFFSET @pageOffset;
  169. ", p);
  170. PageResult<ExamPlanAuditOutput> ret = new()
  171. {
  172. PageIndex = input.PageIndex,
  173. PageSize = input.PageSize,
  174. TotalCount = totalCount,
  175. Items = items
  176. };
  177. return ret;
  178. }
  179. /// <summary>
  180. /// 获取待审核机构列表
  181. /// </summary>
  182. /// <param name="input"></param>
  183. /// <returns></returns>
  184. public async Task<PageResult<ExamPlanOrgAuditOutput>> QueryOrgAuditPageList(ExamOrgDataReportAuditPageInput input)
  185. {
  186. var roleDataScope = await sysRoleService.GetCurrentUserDataScope();
  187. if (roleDataScope == null || roleDataScope.EducationStages.Count == 0)
  188. {
  189. return new();
  190. }
  191. var p = new
  192. {
  193. input.PageSize,
  194. PageOffset = (input.PageIndex - 1) * input.PageSize,
  195. input.ExamPlanId,
  196. input.SearchValue,
  197. input.SysOrgName,
  198. input.ExamPlanName,
  199. Type = (short)DataReportType.SP_STUDENT,
  200. };
  201. List<string> whereCause = new();
  202. if (input.ExamPlanId.HasValue)
  203. {
  204. whereCause.Add("T1.id = @examPlanId");
  205. }
  206. if (roleDataScope.EducationStages.Count == 0)
  207. {
  208. whereCause.Add($"T1.education_stage = {(short)roleDataScope.EducationStages[0]}");
  209. }
  210. else
  211. {
  212. var ess = roleDataScope.EducationStages.Select(t => $"T1.education_stage = {(short)t}").ToList();
  213. string wes = string.Join(" OR ", ess);
  214. whereCause.Add($"({wes})");
  215. }
  216. if (input.SemesterId.HasValue)
  217. {
  218. whereCause.Add("T1.semester_id = @semesterId");
  219. }
  220. if (!string.IsNullOrEmpty(input.ExamPlanName?.Trim()))
  221. {
  222. whereCause.Add("T1.full_name LIKE '%@examPlanName%'");
  223. }
  224. if (!string.IsNullOrEmpty(input.SysOrgName?.Trim()))
  225. {
  226. whereCause.Add("ORG.full_name LIKE '%@sysOrgName%'");
  227. }
  228. string whereSql = $"WHERE (T1.`status` = {(short)ExamStatus.ACTIVE} OR T1.`status` = {(short)ExamStatus.STOPPED})";
  229. if (whereCause.Count > 0)
  230. {
  231. whereSql = $"{whereSql} AND {string.Join(" AND ", whereCause)}";
  232. }
  233. string fromSql = $@"
  234. FROM exam_plan AS T1
  235. JOIN exam_org AS T2 ON T1.id = T2.exam_plan_id
  236. JOIN sys_org AS ORG ON T2.sys_org_id = ORG.id
  237. LEFT JOIN (SELECT * FROM exam_org_data_report WHERE type = {(short)DataReportType.SP_STUDENT}) AS T3 ON T2.id = T3.exam_org_id
  238. LEFT JOIN exam_special_student AS T4 ON T1.id = T4.exam_plan_id AND T2.sys_org_id = T4.sys_org_id
  239. ";
  240. string groupSql = @"GROUP BY T2.exam_plan_id, T1.full_name, T1.`name`, T1.semester_id, T1.education_stage, T1.`status`, T2.sys_org_id, ORG.full_name, ORG.`name`, ORG.`code`, T3.`status`, T3.report_time";
  241. var totalCount = await rep.SqlScalarAsync<int>($@"
  242. SELECT COUNT(1) AS total_count
  243. FROM
  244. (
  245. SELECT COUNT(1) AS total_count
  246. {fromSql}
  247. {whereSql}
  248. {groupSql}
  249. ) AS T", p);
  250. var items = await rep.SqlQueriesAsync<ExamPlanOrgAuditOutput>($@"
  251. SELECT ROW_NUMBER() OVER (ORDER BY T.exam_plan_id DESC, T.audit_count DESC, T.report_time) AS `row_number`, T.*
  252. FROM
  253. (
  254. SELECT
  255. T2.exam_plan_id,
  256. T1.full_name AS exam_plan_full_name,
  257. T1.`name` AS exam_plan_name,
  258. T1.semester_id,
  259. T1.education_stage,
  260. T1.`status` AS exam_status,
  261. T2.sys_org_id,
  262. ORG.full_name AS sys_org_full_name,
  263. ORG.`name` AS sys_org_name,
  264. ORG.`code` AS sys_org_code,
  265. IFNULL(T3.`status`, 1) AS data_report_status,
  266. T3.report_time,
  267. COUNT(CASE WHEN (T3.`status` = {(short)DataReportStatus.REPORTED} OR T3.`status` = {(short)DataReportStatus.REJECTED}) THEN T4.id ELSE NULL END) AS total_count,
  268. COUNT(CASE WHEN (T3.`status` = {(short)DataReportStatus.REPORTED} OR T3.`status` = {(short)DataReportStatus.REJECTED}) AND (T4.`status` = {(short)AuditStatus.AUDIT} OR T4.`status` = {(short)AuditStatus.APPROVE_CANCELED}) THEN T4.id ELSE NULL END) AS audit_count,
  269. COUNT(CASE WHEN (T3.`status` = {(short)DataReportStatus.REPORTED} OR T3.`status` = {(short)DataReportStatus.REJECTED}) AND T4.`status` = {(short)AuditStatus.APPROVED} THEN T4.id ELSE NULL END) AS approved_count,
  270. COUNT(CASE WHEN (T3.`status` = {(short)DataReportStatus.REPORTED} OR T3.`status` = {(short)DataReportStatus.REJECTED}) AND T4.`status` = {(short)AuditStatus.REJECTED} THEN T4.id ELSE NULL END) AS rejected_count,
  271. COUNT(CASE WHEN (T3.`status` = {(short)DataReportStatus.REPORTED} OR T3.`status` = {(short)DataReportStatus.REJECTED}) AND T4.is_pre_identified = 1 THEN T4.id ELSE NULL END) AS pre_identified_count
  272. {fromSql}
  273. {whereSql}
  274. {groupSql}
  275. ) AS T
  276. ORDER BY T.exam_plan_id DESC, T.audit_count DESC, T.data_report_status DESC, T.report_time DESC
  277. LIMIT @pageSize OFFSET @pageOffset;
  278. ", p);
  279. PageResult<ExamPlanOrgAuditOutput> ret = new()
  280. {
  281. PageIndex = input.PageIndex,
  282. PageSize = input.PageSize,
  283. TotalCount = totalCount,
  284. Items = items
  285. };
  286. return ret;
  287. }
  288. }