CourseController.cs 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640
  1. using Microsoft.AspNetCore.Mvc;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using TEAMModelOS.Models;
  7. using TEAMModelOS.SDK;
  8. using TEAMModelOS.SDK.DI;
  9. using System.Text.Json;
  10. using TEAMModelOS.SDK.Models;
  11. using TEAMModelOS.SDK.Extension;
  12. using Azure.Cosmos;
  13. using Microsoft.AspNetCore.Http;
  14. using Microsoft.Extensions.Options;
  15. using System.IO;
  16. using System.Dynamic;
  17. using System.Net.Http;
  18. using System.Net;
  19. using Newtonsoft.Json;
  20. using System.Linq;
  21. using StackExchange.Redis;
  22. using static TEAMModelOS.SDK.Models.Teacher;
  23. using Microsoft.Extensions.Configuration;
  24. using TEAMModelOS.Filter;
  25. using Microsoft.AspNetCore.Authorization;
  26. using HTEXLib.COMM.Helpers;
  27. using TEAMModelOS.SDK.Models.Service;
  28. using System.ComponentModel.DataAnnotations;
  29. namespace TEAMModelAPI.Controllers
  30. {
  31. [ProducesResponseType(StatusCodes.Status200OK)]
  32. [ProducesResponseType(StatusCodes.Status400BadRequest)]
  33. [ApiController]
  34. [Route("school")]
  35. public class CourseController : ControllerBase
  36. {
  37. public AzureCosmosFactory _azureCosmos;
  38. private readonly AzureStorageFactory _azureStorage;
  39. private readonly AzureRedisFactory _azureRedis;
  40. private readonly DingDing _dingDing;
  41. private readonly Option _option;
  42. private readonly IConfiguration _configuration;
  43. private readonly CoreAPIHttpService _coreAPIHttpService;
  44. private readonly AzureServiceBusFactory _serviceBus;
  45. //1 2 3 4 5 6 7
  46. private List<string> weekDays = new List<string> { "MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN" };
  47. public CourseController(CoreAPIHttpService coreAPIHttpService, AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis, DingDing dingDing, IOptionsSnapshot<Option> option, IConfiguration configuration, AzureServiceBusFactory serviceBus)
  48. {
  49. _azureCosmos = azureCosmos;
  50. _azureStorage = azureStorage;
  51. _azureRedis = azureRedis;
  52. _dingDing = dingDing;
  53. _option = option?.Value;
  54. _configuration = configuration;
  55. _coreAPIHttpService = coreAPIHttpService;
  56. _serviceBus = serviceBus;
  57. }
  58. [ProducesDefaultResponseType]
  59. [HttpPost("get-course-list")]
  60. [ApiToken(Auth = "1301", Name = "获取课程列表信息", RW = "R", Limit = false)]
  61. public async Task<IActionResult> GetCourseList(JsonElement json)
  62. {
  63. var client = _azureCosmos.GetCosmosClient();
  64. var (id, school) = HttpContext.GetApiTokenInfo();
  65. json.TryGetProperty("periodId", out JsonElement periodId);
  66. json.TryGetProperty("subjectId", out JsonElement subjectId);
  67. StringBuilder sql = new StringBuilder($"SELECT c.id,c.name,c.subject,c.period,c.scope,c.no,c.school FROM c where 1=1 ");
  68. if (!string.IsNullOrWhiteSpace($"{periodId}"))
  69. {
  70. sql.Append($" and c.period.id='{periodId}'");
  71. }
  72. if (!string.IsNullOrWhiteSpace($"{subjectId}"))
  73. {
  74. sql.Append($" and c.subject.id='{subjectId}'");
  75. }
  76. List<dynamic> courses = new List<dynamic>();
  77. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").
  78. GetItemQueryIterator<dynamic>(queryText: sql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Course-{school}") }))
  79. {
  80. courses.Add(item);
  81. }
  82. return Ok(new { courses });
  83. }
  84. [ProducesDefaultResponseType]
  85. [HttpPost("get-course-info")]
  86. [ApiToken(Auth = "1302", Name = "课程详细信息", RW = "R", Limit = false)]
  87. public async Task<IActionResult> GetCourseInfo(JsonElement json)
  88. {
  89. var (id, school) = HttpContext.GetApiTokenInfo();
  90. json.TryGetProperty("courseId", out JsonElement courseId);
  91. Azure.Response response = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School")
  92. .ReadItemStreamAsync($"{courseId}", new PartitionKey($"Course-{school}"));
  93. if (response.Status == 200)
  94. {
  95. JsonDocument document = JsonDocument.Parse(response.Content);
  96. Course course = document.RootElement.Deserialize<Course>();
  97. return Ok(new { course.name, course.id, course.subject, course.period, course.scope, course.school, course.no, course.desc, course.schedule });
  98. }
  99. else
  100. {
  101. return Ok(new { error = 1, msg = "课程不存在!" });
  102. }
  103. }
  104. /// <summary>
  105. /// 获取指定学段作息
  106. /// </summary>
  107. /// <param name="request"></param>
  108. /// <returns></returns>
  109. [ProducesDefaultResponseType]
  110. [HttpPost("get-period-timetable")]
  111. [ApiToken(Auth = "1303", Name = "试卷和评测的条件信息", RW = "R", Limit = false)]
  112. public async Task<IActionResult> GetPaperExamCondition(JsonElement json)
  113. {
  114. json.TryGetProperty("periodId", out JsonElement _periodId);
  115. var (id, school) = HttpContext.GetApiTokenInfo();
  116. School data = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>(school, new PartitionKey("Base"));
  117. var period = data.period.Find(x => x.id.Equals($"{_periodId}"));
  118. if (period != null)
  119. {
  120. return Ok(new { period.subjects, period.timetable, period.grades, period.majors , weekDays });
  121. }
  122. else
  123. {
  124. return Ok(new { error = 1, msg = "学段不存在!" });
  125. }
  126. }
  127. [ProducesDefaultResponseType]
  128. [HttpPost("upsert-course-infos")]
  129. [ApiToken(Auth = "1304", Name = "课程详细信息", RW = "W", Limit = false)]
  130. public async Task<IActionResult> UpsertCourseInfo(JsonElement json)
  131. {
  132. var (id, school) = HttpContext.GetApiTokenInfo();
  133. if (!json.TryGetProperty("courses", out JsonElement _courses)) { return Ok(new { error = 1, msg = "课程对象不存在" }); }
  134. List<CourseDto> courseDtos = _courses.ToObject<List<CourseDto>>();
  135. List<Dictionary<string, string>> errorData = new List<Dictionary<string, string>>();
  136. List<Course> courses = new List<Course>() ;
  137. if (courseDtos != null && courseDtos.Valid().isVaild) {
  138. School data = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>(school, new PartitionKey("Base"));
  139. foreach (var courseDto in courseDtos) {
  140. var period = data.period.Find(x => x.id.Equals($"{courseDto.periodId}"));
  141. if (period != null)
  142. {
  143. //同名学科
  144. var subject = period.subjects.Find(x => x.id.Equals($"{courseDto.subjectId}"));
  145. if (subject == null) {
  146. subject = period.subjects.Find(x => x.name.Equals($"{courseDto.subjectName}"));
  147. }
  148. if (subject == null) {
  149. subject = new Subject { id = courseDto.subjectId, name = subject.name, type = 1 };
  150. period.subjects.Add(subject);
  151. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<School>(data, data.id, new PartitionKey("Base"));
  152. }
  153. Course course = null;
  154. if (string.IsNullOrWhiteSpace(courseDto?.id))
  155. {
  156. course = new Course
  157. {
  158. pk = "Course",
  159. id = Guid.NewGuid().ToString(),
  160. code = $"Course-{school}",
  161. name = courseDto.name,
  162. subject = new SubjectSimple { id = subject.id, name = subject.name },
  163. period = new PeriodSimple { id = period.id, name = period.name },
  164. school = school,
  165. desc = courseDto.desc,
  166. scope = "school",
  167. no = courseDto.no,
  168. };
  169. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).CreateItemAsync(course, new PartitionKey(course.code));
  170. }
  171. else
  172. {
  173. Azure.Response response = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync($"{course.id}", new PartitionKey($"Course-{school}"));
  174. if (response.Status == 200)
  175. {
  176. JsonDocument jsonDocument = JsonDocument.Parse(response.Content);
  177. course = jsonDocument.RootElement.ToObject<Course>();
  178. course.pk = "Course";
  179. course.name = string.IsNullOrWhiteSpace(courseDto.name) ? course.name : courseDto.name;
  180. course.subject = new SubjectSimple { id = subject.id, name = subject.name };
  181. course.period = new PeriodSimple { id = period.id, name = period.name };
  182. course.school = school;
  183. course.desc = string.IsNullOrWhiteSpace(courseDto.desc) ? course.desc : courseDto.desc;
  184. course.scope = "school";
  185. course.no = string.IsNullOrWhiteSpace(courseDto.no) ? course.no : courseDto.no;
  186. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReplaceItemAsync(course, course.id, new PartitionKey(course.code));
  187. }
  188. else
  189. {
  190. course = new Course
  191. {
  192. pk = "Course",
  193. id = Guid.NewGuid().ToString(),
  194. code = $"Course-{school}",
  195. name = courseDto.name,
  196. subject = new SubjectSimple { id = subject.id, name = subject.name },
  197. period = new PeriodSimple { id = period.id, name = period.name },
  198. school = school,
  199. desc = courseDto.desc,
  200. scope = "school",
  201. no = courseDto.no,
  202. };
  203. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).CreateItemAsync(course, new PartitionKey(course.code));
  204. }
  205. }
  206. if (course != null) { courses.Add(course); }
  207. }
  208. else
  209. {
  210. errorData.Add(new Dictionary<string, string> { { "course", courseDto.name }, { "periodId", courseDto.periodId } });
  211. //return Ok(new { error = 2, msg = "学段不存在!" });
  212. }
  213. }
  214. }
  215. else
  216. {
  217. return Ok(new { error = 3, msg = courseDtos.Valid() });
  218. }
  219. return Ok(new { courses = courses ,errorData});
  220. }
  221. //[Required(ErrorMessage = "{0} 课程的科目id必须填写"), RegularExpression(@"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}",ErrorMessage ="科目的uuid格式错误!")]
  222. public class ImportCourse {
  223. [Required(ErrorMessage = "课程id 必须设置"), RegularExpression(@"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}", ErrorMessage = "科目的uuid格式错误!")]
  224. public string courseId { get; set; }
  225. [Required(ErrorMessage = "课程名称 必须设置")]
  226. public string courseName { get; set; }
  227. [Required(ErrorMessage = "课程科目id 必须设置"), RegularExpression(@"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}", ErrorMessage = "科目的uuid格式错误!")]
  228. public string subjectId { get; set; }
  229. [Required(ErrorMessage = "课程科目名称 必须设置")]
  230. public string subjectName { get; set; }
  231. [Required(ErrorMessage = "课程学段id 必须设置"), RegularExpression(@"[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}", ErrorMessage = "学段的uuid格式错误!")]
  232. public string periodId { get; set; }
  233. public List<Schedule> schedules { get; set; }
  234. }
  235. [ProducesDefaultResponseType]
  236. [HttpPost("upsert-course-schedule")]
  237. [ApiToken(Auth = "1305", Name = "更新课程的排课信息", RW = "W", Limit = false)]
  238. public async Task<IActionResult> UpsertCourseSchedule(JsonElement json)
  239. {
  240. var (id, school) = HttpContext.GetApiTokenInfo();
  241. if (!json.TryGetProperty("courses", out JsonElement _courses)) { return Ok(new { error = 1, msg = "课程参数错误!" }); }
  242. List<ImportCourse> importCourses = _courses.ToObject<List<ImportCourse>>();
  243. var result = importCourses .Valid();
  244. if (!result.isVaild) {
  245. return Ok(new { error = 2, msg =result});
  246. }
  247. HashSet<string> courseIds= importCourses .Select(x => x.courseId).ToHashSet();
  248. if (courseIds.Count < 1) { return Ok(new { error = 1, msg = "课程参数错误!" }); }
  249. //string sql = $"select value(c) from c where c.id in({string.Join(",",courseIds.Select(x=>$"'{x}'"))})";
  250. string sql = $"select value(c) from c ";//直接获取全校的课程
  251. List<Course> courses = new List<Course>();
  252. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School)
  253. .GetItemQueryIterator<Course>(queryText: sql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Course-{school}") })) {
  254. courses.Add(item);
  255. }
  256. List<Subject> addSubjects = new List<Subject>();
  257. School data = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>(school, new PartitionKey("Base"));
  258. //不存在的课程,可以被直接创建
  259. var unexistCourseIds = courseIds.Except(courses.Select(x => x.id));
  260. foreach (var item in unexistCourseIds) {
  261. ImportCourse importCourse= importCourses.Find(x => x.courseId.Equals(item));
  262. if (importCourse != null) {
  263. Period period= data.period.Find(x => x.id.Equals(importCourse.periodId));
  264. if (period != null) {
  265. //同名学科
  266. var subject = period.subjects.Find(x => x.id.Equals($"{importCourse.subjectId}"));
  267. if (subject == null)
  268. {
  269. subject = period.subjects.Find(x => x.name.Equals($"{importCourse.subjectName}"));
  270. }
  271. if (subject == null) {
  272. subject = new Subject { id = importCourse.subjectId, name = importCourse.subjectName, type = 1 };
  273. period.subjects.Add(subject);
  274. addSubjects.Add(subject);
  275. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReplaceItemAsync(data, data.id, new PartitionKey("Base"));
  276. }
  277. Course course = new Course
  278. {
  279. id = importCourse.courseId,
  280. code = $"Course-{school}",
  281. pk = "Course",
  282. name = importCourse.courseName,
  283. period = new PeriodSimple { id = period.id, name = period.name },
  284. subject = new SubjectSimple { id = subject.id, name = subject.name },
  285. school = school,
  286. scope = "school",
  287. year = DateTimeOffset.Now.Year,
  288. schedule = new List<Schedule>(),
  289. };
  290. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).CreateItemAsync(course, new PartitionKey(course.code));
  291. courses.Add(course);
  292. }
  293. }
  294. }
  295. //importCourses =importCourses .Where(x => !unexistCourseIds .Contains(x.courseId));
  296. //排查 课程学段,课程排课作息,课程排课的星期几是否准确
  297. List<ScheduleTimeDto> import_schedules_hastime = new List<ScheduleTimeDto>() ;
  298. List<ScheduleNoTimeDto> import_schedules_nottime = new List<ScheduleNoTimeDto>();
  299. //保存没有选用名单的排课。
  300. List<Schedule> schedules_noList= new List<Schedule>() ;
  301. List<ScheduleTimeDto> weeksError = new List<ScheduleTimeDto>();
  302. importCourses .ToList().ForEach(x => {
  303. x.schedules.ForEach(z => {
  304. if (!string.IsNullOrWhiteSpace(z.classId) || !string.IsNullOrWhiteSpace(z.stulist))
  305. {
  306. string classId = null;
  307. //行政班不为空,教学班为空,则名单取行政班
  308. classId = !string.IsNullOrWhiteSpace(z.classId) && string.IsNullOrWhiteSpace(z.stulist) ? z.classId : classId;
  309. //行政班为空,教学班不为空,则名单取教学班
  310. classId = string.IsNullOrWhiteSpace(z.classId) && !string.IsNullOrWhiteSpace(z.stulist) ? z.stulist : classId;
  311. //行政班,教学班都不为空,且相同,则任取一个,取的是行政班
  312. classId = !string.IsNullOrWhiteSpace(z.classId) && !string.IsNullOrWhiteSpace(z.stulist) && z.classId.Equals(z.stulist) ? z.classId : classId;
  313. //行政班,教学班都不为空,且不同,则取null
  314. classId = !string.IsNullOrWhiteSpace(z.classId) && !string.IsNullOrWhiteSpace(z.stulist) && !z.classId.Equals(z.stulist) ? null : classId;
  315. if (!string.IsNullOrWhiteSpace(classId))
  316. {
  317. if (z.time.IsNotEmpty())
  318. {
  319. z.time.ForEach(t =>
  320. {
  321. ScheduleTimeDto scheduleDto = new ScheduleTimeDto
  322. {
  323. courseId = x.courseId,
  324. roomId = z.room,
  325. classId = z.classId,
  326. stulist = z.stulist,
  327. teacherId = z.teacherId,
  328. timeId = t.id,
  329. week = t.week,
  330. keyTeacher = $"{z.teacherId}_{t.week}_{t.id}",
  331. keyGroupId = $"{classId}_{t.week}_{t.id}",
  332. keyRoomIds = string.IsNullOrWhiteSpace(z.room) ? null : $"{z.room}_{t.week}_{t.id}"
  333. };
  334. //星期几自检 1 2 3 4 5 6 7
  335. if (weekDays.Contains(t.week))
  336. {
  337. import_schedules_hastime.Add(scheduleDto);
  338. }
  339. else
  340. {
  341. weeksError.Add(scheduleDto);
  342. }
  343. });
  344. }
  345. else {
  346. //允许导入没有排课时间表的课程。
  347. import_schedules_nottime.Add(new ScheduleNoTimeDto
  348. {
  349. courseId = x.courseId,
  350. roomId = z.room,
  351. classId = z.classId,
  352. stulist = z.stulist,
  353. teacherId = z.teacherId,
  354. });
  355. }
  356. }
  357. else { schedules_noList.Add(z); }
  358. }
  359. else {
  360. schedules_noList.Add(z);
  361. }
  362. });
  363. });
  364. //导入的排课自检。
  365. //教师自检
  366. var check_teacher = import_schedules_hastime.GroupBy(x => x.keyTeacher).Select(g => new { key = g.Key, list = g.ToList() });
  367. IEnumerable<ScheduleTimeDto> teacherWarning = new List<ScheduleTimeDto>();
  368. teacherWarning = check_teacher.Where(x => x.list.Count > 1).SelectMany(x => x.list);
  369. //import_schedules.RemoveAll(x => import_teacherConfuse.Contains(x));
  370. //名单自检
  371. var check_groupId = import_schedules_hastime.GroupBy(x => x.keyGroupId).Select(g => new { key = g.Key, list = g.ToList() });
  372. IEnumerable<ScheduleTimeDto> groupIdWarning = new List<ScheduleTimeDto>();
  373. groupIdWarning = check_groupId.Where(x => x.list.Count > 1).SelectMany(x => x.list);
  374. //import_schedules.RemoveAll(x => import_groupIdConfuse.Contains(x));
  375. //物理教室自检
  376. var check_roomIds = import_schedules_hastime.Where(r=>!string.IsNullOrWhiteSpace(r.keyRoomIds)).GroupBy(x => x.keyRoomIds).Select(g => new { key = g.Key, list = g.ToList() });
  377. IEnumerable<ScheduleTimeDto> roomIdsWarning = new List<ScheduleTimeDto>();
  378. roomIdsWarning = check_roomIds.Where(x => x.list.Count > 1).SelectMany(x => x.list);
  379. //import_schedules.RemoveAll(x => import_roomIdsConfuse.Contains(x));
  380. //打散数据库已经有的排课信息
  381. List<ScheduleTimeDto> database_schedules = new List<ScheduleTimeDto>();
  382. courses.ForEach(x => {
  383. x.schedule.ForEach(z => {
  384. if (!string.IsNullOrWhiteSpace(z.teacherId) &&(!string.IsNullOrWhiteSpace(z.classId) || !string.IsNullOrWhiteSpace(z.stulist)))
  385. {
  386. string classId = null;
  387. //行政班不为空,教学班为空,则名单取行政班
  388. classId = !string.IsNullOrWhiteSpace(z.classId) && string.IsNullOrWhiteSpace(z.stulist) ? z.classId : classId;
  389. //行政班为空,教学班不为空,则名单取教学班
  390. classId = string.IsNullOrWhiteSpace(z.classId) && !string.IsNullOrWhiteSpace(z.stulist) ? z.stulist : classId;
  391. //行政班,教学班都不为空,且相同,则任取一个,取的是行政班
  392. classId = !string.IsNullOrWhiteSpace(z.classId) && !string.IsNullOrWhiteSpace(z.stulist) && z.classId.Equals(z.stulist) ? z.classId : classId;
  393. //行政班,教学班都不为空,且不同,则取null
  394. classId = !string.IsNullOrWhiteSpace(z.classId) && !string.IsNullOrWhiteSpace(z.stulist) && !z.classId.Equals(z.stulist) ? null : classId;
  395. if (!string.IsNullOrWhiteSpace(classId))
  396. {
  397. z.time.ForEach(t =>
  398. {
  399. ScheduleTimeDto scheduleDto = new ScheduleTimeDto
  400. {
  401. courseId = x.id,
  402. roomId = z.room,
  403. classId = z.classId,
  404. stulist = z.stulist,
  405. teacherId = z.teacherId,
  406. timeId = t.id,
  407. week = t.week,
  408. keyTeacher = $"{z.teacherId}_{t.week}_{t.id}",
  409. keyGroupId = $"{classId}_{t.week}_{t.id}",
  410. keyRoomIds = string.IsNullOrWhiteSpace(z.room) ? null : $"{z.room}_{t.week}_{t.id}"
  411. };
  412. database_schedules.Add(scheduleDto);
  413. });
  414. }
  415. }
  416. });
  417. });
  418. List<ScheduleTimeDto> teacherError = new List<ScheduleTimeDto>();
  419. List<ScheduleTimeDto> groupIdError = new List<ScheduleTimeDto>();
  420. List<ScheduleTimeDto> roomIdsError = new List<ScheduleTimeDto>();
  421. //数据库排查
  422. import_schedules_hastime.ForEach(x => {
  423. //检查教师的排课是否冲突,不同的课程不能出现 教师冲突的情况, 相同课程可能是需要更新的。
  424. if (database_schedules.FindAll(s => s.keyTeacher.Equals(x.keyTeacher) && !x.courseId.Equals(s.courseId)).IsNotEmpty())
  425. {
  426. teacherError.Add(x);
  427. }
  428. //检查名单的排课是否冲突
  429. if (database_schedules.FindAll(s => s.keyGroupId.Equals(x.keyGroupId) && !x.courseId.Equals(s.courseId)).IsNotEmpty())
  430. {
  431. groupIdError.Add(x);
  432. }
  433. //检查教室的排课是否冲突
  434. if (database_schedules.FindAll(s => s.keyRoomIds.Equals(x.keyRoomIds) && !x.courseId.Equals(s.courseId)).IsNotEmpty())
  435. {
  436. roomIdsError.Add(x);
  437. }
  438. });
  439. //移除 教师,名单,教室冲突的排课
  440. import_schedules_hastime.RemoveAll(x => teacherError.Contains(x));
  441. import_schedules_hastime.RemoveAll(x => groupIdError.Contains(x));
  442. import_schedules_hastime.RemoveAll(x => roomIdsError.Contains(x));
  443. //最终导入之前,必须检查,课程是否存在(notInCourseIds),教师是否存在,名单是否存在,并重新排列行政班,教学班,
  444. //排课时间段id是否正确,星期几是否正确(import_weeksConfuse),教室是否正确
  445. //检查教师存在的
  446. HashSet<string> teachers = import_schedules_hastime.Select(x => x.teacherId).ToHashSet();
  447. teachers.Union(import_schedules_nottime.Select(x => x.teacherId));
  448. IEnumerable<string> unexistTeacherIds= null;
  449. if (teachers.Count > 0) {
  450. List<string> teacherIds = new List<string>();
  451. string sqlTeacher = $"select value(c.id) from c where c.id in ({string.Join(",",teachers.Select(x=>$"'{x}'"))})";
  452. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School)
  453. .GetItemQueryIterator<string>(queryText: sqlTeacher, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Teacher-{school}") }))
  454. {
  455. teacherIds.Add(item);
  456. }
  457. unexistTeacherIds= teachers.Except(teacherIds);
  458. //移除不存在的教师
  459. import_schedules_hastime.RemoveAll(x => unexistTeacherIds.Contains(x.teacherId));
  460. import_schedules_nottime.RemoveAll(x => unexistTeacherIds.Contains(x.teacherId));
  461. }
  462. //检查教室存在的
  463. HashSet<string> roomIds = import_schedules_hastime.Select(x => x.roomId).ToHashSet();
  464. roomIds.Union(import_schedules_nottime.Select(x => x.roomId));
  465. IEnumerable<string> unexistRoomIds = null;
  466. if (roomIds.Count > 0)
  467. {
  468. List<string> rooms = new List<string>();
  469. string sqlRoom = $"select value(c.id) from c where c.id in ({string.Join(",", roomIds.Select(x => $"'{x}'"))})";
  470. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School)
  471. .GetItemQueryIterator<string>(queryText: sqlRoom, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Room-{school}") }))
  472. {
  473. rooms.Add(item);
  474. }
  475. unexistRoomIds= roomIds.Except(rooms);
  476. //移除不存在的教室
  477. import_schedules_hastime.RemoveAll(x => unexistRoomIds.Contains(x.roomId));
  478. import_schedules_nottime.RemoveAll(x => unexistRoomIds.Contains(x.roomId));
  479. }
  480. //检查名单存在的
  481. List<string> groupIds = new List<string>();
  482. var classIdsHasTime = import_schedules_hastime.Where(x => !string.IsNullOrWhiteSpace(x.classId)).Select(x => x.classId).ToHashSet();
  483. if (classIdsHasTime.Any()) {
  484. groupIds.AddRange(classIdsHasTime);
  485. }
  486. var stulistsHasTime = import_schedules_hastime.Where(x => !string.IsNullOrWhiteSpace(x.stulist)).Select(x => x.stulist).ToHashSet();
  487. if (stulistsHasTime.Any())
  488. {
  489. groupIds.AddRange(stulistsHasTime);
  490. }
  491. var classIdsNotTime = import_schedules_nottime.Where(x => !string.IsNullOrWhiteSpace(x.classId)).Select(x => x.classId).ToHashSet();
  492. if (classIdsNotTime.Any())
  493. {
  494. groupIds.AddRange(classIdsNotTime);
  495. }
  496. var stulistsNotTime = import_schedules_nottime.Where(x => !string.IsNullOrWhiteSpace(x.stulist)).Select(x => x.stulist).ToHashSet();
  497. if (stulistsNotTime.Any())
  498. {
  499. groupIds.AddRange(stulistsNotTime);
  500. }
  501. List<GroupListDto> groupListDtos= await GroupListService.GetGroupListListids(_azureCosmos.GetCosmosClient(), _dingDing, groupIds, school);
  502. IEnumerable<string> unexistGroupIds = groupIds.Except(groupListDtos.Select(x=>x.id));
  503. //移除不存在的名单id
  504. import_schedules_hastime.RemoveAll(x => unexistGroupIds.Contains(x.classId));
  505. import_schedules_hastime.RemoveAll(x => unexistGroupIds.Contains(x.stulist));
  506. import_schedules_nottime.RemoveAll(x => unexistGroupIds.Contains(x.classId));
  507. import_schedules_nottime.RemoveAll(x => unexistGroupIds.Contains(x.stulist));
  508. HashSet<Course> update_course = new HashSet<Course>();
  509. HashSet<string> unexistTimeIds = new HashSet<string>();
  510. //处理包含时间排课的课程
  511. import_schedules_hastime.ForEach(schedule => {
  512. Course course = courses.Find(x => x.id.Equals(schedule.courseId));
  513. if (string.IsNullOrWhiteSpace(course?.period?.id))
  514. {
  515. Period period = data.period.Find(p => p.id.Equals(course.period.id));
  516. TimeTable timeTable = period?.timetable.Find(x => x.id.Equals(schedule.timeId));
  517. if (timeTable != null)
  518. {
  519. string groupId= string.IsNullOrWhiteSpace(schedule.classId)?schedule.stulist:schedule.classId;
  520. GroupListDto groupList= groupListDtos.Find(g => g.id.Equals(groupId));
  521. string classId = null;
  522. string stulist = null;
  523. if (groupList.type.Equals("class")) {
  524. classId = groupList.id;
  525. }
  526. else {
  527. stulist = groupList.id;
  528. }
  529. var course_schedule =course.schedule.Find(x => x.teacherId.Equals(schedule.teacherId));
  530. if (course_schedule != null)
  531. {
  532. course_schedule.classId = classId;
  533. course_schedule.stulist = stulist ;
  534. course_schedule.room = schedule.roomId;
  535. var time= course_schedule.time.Find(t => t.id.Equals(schedule.timeId) && t.week.Equals(schedule.week));
  536. if (time != null)
  537. {
  538. time.id=schedule.timeId;
  539. time.week=schedule.week;
  540. }
  541. else {
  542. course_schedule.time.Add(new TimeInfo { id = schedule.timeId, week = schedule.week });
  543. }
  544. }
  545. else {
  546. course.schedule.Add(new Schedule { teacherId = schedule.teacherId,classId = classId, stulist = stulist, room = schedule.roomId, time = new List<TimeInfo> { new TimeInfo { id=schedule.timeId,week=schedule.week} } });
  547. }
  548. update_course.Add(course);
  549. }
  550. else {
  551. //课程,所在学段对应的作息时间不正确
  552. unexistTimeIds.Add(schedule.timeId);
  553. }
  554. }
  555. });
  556. //处理没有时间排课的课程
  557. import_schedules_nottime.ForEach(schedule => {
  558. Course course = courses.Find(x => x.id.Equals(schedule.courseId));
  559. if (string.IsNullOrWhiteSpace(course?.period?.id))
  560. {
  561. Period period = data.period.Find(p => p.id.Equals(course.period.id));
  562. string groupId = string.IsNullOrWhiteSpace(schedule.classId) ? schedule.stulist : schedule.classId;
  563. GroupListDto groupList = groupListDtos.Find(g => g.id.Equals(groupId));
  564. string classId = null;
  565. string stulist = null;
  566. if (groupList.type.Equals("class"))
  567. {
  568. classId = groupList.id;
  569. }
  570. else
  571. {
  572. stulist = groupList.id;
  573. }
  574. var course_schedule = course.schedule.Find(x => x.teacherId.Equals(schedule.teacherId));
  575. if (course_schedule != null)
  576. {
  577. course_schedule.classId = classId;
  578. course_schedule.stulist = stulist;
  579. course_schedule.room = schedule.roomId;
  580. }
  581. else
  582. {
  583. course.schedule.Add(new Schedule { teacherId=schedule.teacherId, classId = classId, stulist = stulist, room = schedule.roomId});
  584. }
  585. update_course.Add(course);
  586. }
  587. });
  588. foreach (var item in update_course) {
  589. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReplaceItemAsync(item, item.id, new PartitionKey(item.code));
  590. }
  591. return Ok(new {
  592. import= new //导入数据自检信息
  593. {
  594. teacherWarning,//自检-教师冲突的排课
  595. groupIdWarning,//自检-名单冲突的排课
  596. roomIdsWarning,//自检-物理教室冲突的排课
  597. weeksError //自检-错误的星期几编码
  598. },
  599. database= new //数据库比对信息
  600. {
  601. teacherError,//数据比对-教师冲突的排课
  602. groupIdError,//数据比对-名单冲突的排课
  603. roomIdsError,//数据比对-物理教室冲突的排课
  604. unexistCourseIds ,//不存在的课程
  605. unexistTeacherIds,//不存在的教师
  606. unexistGroupIds,//不存在的名单
  607. unexistRoomIds,//不存在的教室
  608. unexistTimeIds //不存在的作息
  609. },
  610. updateCourse= update_course,
  611. addSubjects= addSubjects
  612. });
  613. }
  614. }
  615. }