CourseBaseController.cs 70 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988
  1. using Azure.Cosmos;
  2. using Microsoft.AspNetCore.Http;
  3. using Microsoft.AspNetCore.Mvc;
  4. using Microsoft.Extensions.Options;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Linq;
  8. using System.Text;
  9. using System.Text.Json;
  10. using System.Threading.Tasks;
  11. using TEAMModelOS.Models;
  12. using TEAMModelOS.SDK.Models;
  13. using TEAMModelOS.SDK.DI;
  14. using TEAMModelOS.SDK.Extension;
  15. using Azure;
  16. using Microsoft.Extensions.Configuration;
  17. using TEAMModelOS.Filter;
  18. using HTEXLib.COMM.Helpers;
  19. using System.Globalization;
  20. using TEAMModelOS.SDK;
  21. using Microsoft.AspNetCore.Authorization;
  22. using StackExchange.Redis;
  23. using Azure.Storage.Blobs.Models;
  24. using Microsoft.Azure.Amqp.Sasl;
  25. using DocumentFormat.OpenXml.Drawing.Charts;
  26. using FastJSON;
  27. using OpenXmlPowerTools;
  28. using DocumentFormat.OpenXml.Drawing.Spreadsheet;
  29. namespace TEAMModelOS.Controllers.Both
  30. {
  31. [ProducesResponseType(StatusCodes.Status200OK)]
  32. [ProducesResponseType(StatusCodes.Status400BadRequest)]
  33. [Route("course-base")]
  34. [ApiController]
  35. public class CourseBaseController : ControllerBase
  36. {
  37. private AzureCosmosFactory _azureCosmos;
  38. private readonly DingDing _dingDing;
  39. private readonly Option _option;
  40. private readonly AzureServiceBusFactory _serviceBus;
  41. private readonly AzureStorageFactory _azureStorage;
  42. private readonly AzureRedisFactory _azureRedis;
  43. private static List<string> weekDays = new List<string> { "MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN" };
  44. public IConfiguration _configuration { get; set; }
  45. public CourseBaseController(AzureRedisFactory azureRedis,AzureCosmosFactory azureCosmos, DingDing dingDing, IOptionsSnapshot<Option> option, AzureServiceBusFactory serviceBus, AzureStorageFactory azureStorage, IConfiguration configuration)
  46. {
  47. _azureCosmos = azureCosmos;
  48. _dingDing = dingDing;
  49. _option = option?.Value;
  50. _serviceBus = serviceBus;
  51. _configuration = configuration;
  52. _azureStorage = azureStorage;
  53. _azureRedis = azureRedis;
  54. }
  55. /// <summary>
  56. /// 更新保存课程
  57. /// </summary>
  58. /// <param name="request"></param>
  59. /// <returns></returns>
  60. [ProducesDefaultResponseType]
  61. [AuthToken(Roles = "teacher,admin")]
  62. [HttpPost("manage")]
  63. #if !DEBUG
  64. [Authorize(Roles = "IES")]
  65. #endif
  66. public async Task<IActionResult> upsert(JsonElement request)
  67. {
  68. try {
  69. (string tmdid, _, _, string school) = HttpContext.GetAuthTokenInfo();
  70. if (!request.TryGetProperty("grant_type", out JsonElement grant_type)) return BadRequest();
  71. if (!request.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
  72. var client = _azureCosmos.GetCosmosClient();
  73. switch (true)
  74. {
  75. case bool when $"{grant_type}".Equals("list", StringComparison.OrdinalIgnoreCase):
  76. {
  77. if ( !request.TryGetProperty("code", out JsonElement _code))
  78. {
  79. return BadRequest();
  80. }
  81. string tbname = $"{scope}".Equals("school", StringComparison.OrdinalIgnoreCase)?Constant.School:Constant.Teacher;
  82. string code = $"CourseBase-{_code}";
  83. string baseSql = $"select value c from c ";
  84. List<CourseBase> courseBases = new List<CourseBase>();
  85. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tbname)
  86. .GetItemQueryIterator<CourseBase>(queryText: baseSql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey(code) }))
  87. {
  88. courseBases.Add(item);
  89. }
  90. return Ok(new { courseBases });
  91. }
  92. case bool when $"{grant_type}".Equals("delete", StringComparison.OrdinalIgnoreCase):
  93. {
  94. if (!request.TryGetProperty("id", out JsonElement _id) || !request.TryGetProperty("code", out JsonElement _code))
  95. {
  96. return BadRequest();
  97. }
  98. string tbname = $"{scope}".Equals("school", StringComparison.OrdinalIgnoreCase) ? Constant.School : Constant.Teacher;
  99. Azure.Response response= await client.GetContainer(Constant.TEAMModelOS, tbname).DeleteItemStreamAsync(_id.ToString(), new PartitionKey($"CourseBase-{_code}"));
  100. //需要联动删除排课
  101. string taskCode = $"CourseTask-{_code}";
  102. string taskSql = $"select value c from c where c.courseId='{_id}'";
  103. List<CourseTask> courseTasks = new List<CourseTask>();
  104. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tbname)
  105. .GetItemQueryIterator<CourseTask>(queryText: taskSql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey(taskCode) }))
  106. {
  107. courseTasks.Add(item);
  108. }
  109. if (courseTasks.Count > 0)
  110. {
  111. await client.GetContainer(Constant.TEAMModelOS, tbname).DeleteItemsStreamAsync(courseTasks.Select(x=>x.id).ToList(), taskCode);
  112. }
  113. return Ok(new {code= response .Status});
  114. }
  115. case bool when $"{grant_type}".Equals("import-base", StringComparison.OrdinalIgnoreCase) && $"{scope}".Equals("school", StringComparison.OrdinalIgnoreCase):
  116. {
  117. if (!request.TryGetProperty("courses", out JsonElement _courses))
  118. {
  119. return BadRequest();
  120. }
  121. if (!request.TryGetProperty("periodId", out JsonElement _periodId)) return BadRequest();
  122. List<CourseBase> courseBases = _courses.ToObject<List<CourseBase>>();
  123. //1.检查导入的课程名称是否有效
  124. StringBuilder sqlName = new StringBuilder(" select value c from c ");
  125. sqlName.Append($" where c.name in {string.Join(",",courseBases.Select(z=>$"'{z.name}'"))} and c.period.id='{_periodId}' ");
  126. string tbname = Constant.School;
  127. List<CourseBase> courseBasesDB = new List<CourseBase>();
  128. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tbname)
  129. .GetItemQueryIterator<CourseBase>(queryText: sqlName.ToString(), requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"CourseBase-{school}") }))
  130. {
  131. courseBasesDB.Add(item);
  132. }
  133. School schoolBase = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>(school, new PartitionKey("Base"));
  134. var period = schoolBase.period.Find(x => x.id.Equals($"{_periodId}"));
  135. if (period != null) {
  136. foreach (var item in courseBases)
  137. {
  138. item.pk = "CourseBase";
  139. if (string.IsNullOrWhiteSpace(item.id))
  140. {
  141. item.id = Guid.NewGuid().ToString();
  142. }
  143. item.scope = "school";
  144. item.school = school;
  145. item.creatorId = tmdid;
  146. item.code = $"CourseBase-{school}";
  147. item.period = new IdName { id = period.id, name = period.name };
  148. if (!string.IsNullOrWhiteSpace(item.subject?.id))
  149. {
  150. var subject = period.subjects.Find(x => x.id.Equals(item.subject.id));
  151. if (subject != null)
  152. {
  153. item.subject.name = subject.name;
  154. }
  155. }
  156. else {
  157. }
  158. var dbcoursebase = courseBasesDB.Find(x => x.name.Equals(item.name));
  159. if (dbcoursebase != null)
  160. {
  161. item.id = dbcoursebase.id;
  162. item.major = item.major == null ? dbcoursebase.major : item.major;
  163. item.desc = string.IsNullOrWhiteSpace(item.desc) ? dbcoursebase.desc : item.desc;
  164. item.color = string.IsNullOrWhiteSpace(item.color) ? dbcoursebase.color : item.color;
  165. item.no = string.IsNullOrWhiteSpace(item.no) ? dbcoursebase.no : item.no;
  166. item.grades = !item.grades.Any() ? dbcoursebase.grades : item.grades;
  167. }
  168. }
  169. }
  170. return Ok(new { course = courseBases });
  171. }
  172. case bool when $"{grant_type}".Equals("upsert", StringComparison.OrdinalIgnoreCase) :
  173. {
  174. if (!request.TryGetProperty("course", out JsonElement _course))
  175. {
  176. return BadRequest();
  177. }
  178. CourseBase courseBase = _course.ToObject<CourseBase>();
  179. courseBase.pk = "CourseBase";
  180. if (string.IsNullOrWhiteSpace(courseBase.id))
  181. {
  182. courseBase.id = Guid.NewGuid().ToString();
  183. }
  184. string tbname = $"{courseBase.scope}".Equals("school", StringComparison.OrdinalIgnoreCase) ? Constant.School : Constant.Teacher;
  185. //1.检查导入的课程名称是否有效
  186. StringBuilder sqlName = new StringBuilder(" select value c from c ");
  187. sqlName.Append($" where c.name ='{courseBase.name}' ");
  188. if (courseBase.scope.Equals("school", StringComparison.OrdinalIgnoreCase))
  189. {
  190. courseBase.school = school;
  191. courseBase.creatorId = tmdid;
  192. courseBase.code = $"CourseBase-{school}";
  193. if (string.IsNullOrWhiteSpace(courseBase.subject?.id) || !courseBase.grades.Any()) {
  194. return BadRequest();
  195. }
  196. if (string.IsNullOrWhiteSpace(courseBase.period?.id))
  197. {
  198. return BadRequest();
  199. }
  200. else {
  201. sqlName.Append($" and c.period.id='{courseBase.period.id}' ");
  202. }
  203. }
  204. else
  205. {
  206. courseBase.creatorId = tmdid;
  207. courseBase.code = $"CourseBase-{tmdid}";
  208. }
  209. List<CourseBase> courseBases = new List<CourseBase>();
  210. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tbname)
  211. .GetItemQueryIterator<CourseBase>(queryText: sqlName.ToString(), requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey(courseBase.code) }))
  212. {
  213. if (courseBase.scope.Equals(item.scope))
  214. {
  215. //不是同一条数据,但是名字相同,则判定名字重复。
  216. if (!item.id.Equals(courseBase.id) && item.name.Equals(courseBase.name))
  217. {
  218. return Ok(new { code = 409, course = courseBase });
  219. }
  220. }
  221. }
  222. await client.GetContainer(Constant.TEAMModelOS, tbname).UpsertItemAsync(courseBase, new PartitionKey(courseBase.code));
  223. return Ok(new {code =200, course = courseBase });
  224. }
  225. case bool when $"{grant_type}".Equals("read-task", StringComparison.OrdinalIgnoreCase):
  226. {
  227. if (!request.TryGetProperty("courseId", out JsonElement _courseId)) return BadRequest();
  228. string tbname = $"{scope}".Equals("school", StringComparison.OrdinalIgnoreCase) ? Constant.School : Constant.Teacher;
  229. if (scope.ToString().Equals("school", StringComparison.OrdinalIgnoreCase))
  230. {
  231. if (!request.TryGetProperty("periodId", out JsonElement _periodId)) return BadRequest();
  232. int studyYear = -1;
  233. string semesterId = string.Empty;
  234. School schoolBase = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>(school, new PartitionKey("Base"));
  235. var period = schoolBase.period.Find(x => x.id.Equals($"{_periodId}"));
  236. if (!request.TryGetProperty("year", out JsonElement _year) || !request.TryGetProperty("semesterId", out JsonElement _semesterId))
  237. {
  238. //如果没传,则以当前时间获取学年和学期信息
  239. (Semester currSemester, int studyYear, DateTimeOffset date, DateTimeOffset nextSemester) info = SchoolService.GetSemester(period);
  240. semesterId = info.currSemester.id;
  241. studyYear = info.studyYear;
  242. }
  243. else {
  244. studyYear = _year.GetInt32();
  245. semesterId=_semesterId.GetString();
  246. }
  247. string taskCode = $"CourseTask-{school}";
  248. string taskId = $"{studyYear}-{semesterId}-{_courseId}";
  249. Azure.Response response = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tbname).ReadItemStreamAsync(taskId, new PartitionKey(taskCode));
  250. bool has_schedule = false;
  251. CourseTask courseTask = default;
  252. if (response.Status == 200) {
  253. courseTask=JsonDocument.Parse(response.Content).RootElement.ToObject<CourseTask>();
  254. if (courseTask != null && courseTask.schedules.IsNotEmpty())
  255. {
  256. has_schedule = true;
  257. }
  258. }
  259. //匹配建议的班级和教师
  260. List<Class> classes = new List<Class>();
  261. List<SchoolTeacher> teachers = new List<SchoolTeacher>();
  262. if (!has_schedule)
  263. {
  264. //如果没有找到排课安排信息。则可以进行建议升学年方式处理
  265. CourseBase courseBase = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<CourseBase>(_courseId.ToString(), new PartitionKey($"CourseBase-{school}"));
  266. if (courseBase.grades.Any()) {
  267. var yearsdata = SchoolService.GetYears(schoolBase, _periodId.ToString(), courseBase.grades);
  268. List<int> years = yearsdata.years.ToList();
  269. if (years.IsNotEmpty())
  270. {
  271. StringBuilder sql = new StringBuilder($"select value c from c where c.year in ({string.Join(",", years)}) and c.periodId='{_periodId}' ");
  272. var result = await client.GetContainer(Constant.TEAMModelOS, Constant.School).GetList<Class>(sql.ToString(), $"Class-{school}");
  273. classes = result.list;
  274. }
  275. }
  276. if (!string.IsNullOrWhiteSpace(courseBase.subject?.id)) {
  277. string teacherSQL = $"select distinct value c from c join b in c.subjectIds where b in ('{courseBase.subject.id}') and c.code = 'Teacher-{school}'";
  278. var result = await client.GetContainer(Constant.TEAMModelOS, Constant.School).GetList<SchoolTeacher>(teacherSQL.ToString(), $"Teacher-{school}");
  279. teachers = result.list;
  280. }
  281. }
  282. //当courseTask 为空,则matchedClasses可能会有年级匹配建议升学年的班级清单,
  283. //注:比如高二可能会将高三的课程学完,则该高三的课程的学年级应该是手动处理为高中二年级。不区分学期的目的,也是可能存在提前一学期学完第二学期的课程。
  284. return Ok(new { studyYear, semesterId, courseTask, matchedClasses = classes, matchedTeachers = teachers.Select(z=>new { z.id,z.name,z.subjectIds,z.job,z.periodId,z.picture })});
  285. }
  286. else
  287. {
  288. string taskCode = $"CourseTask-{tmdid}";
  289. string taskId = $"{_courseId}";
  290. Azure.Response response = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tbname).ReadItemStreamAsync(taskId, new PartitionKey(taskCode));
  291. CourseTask courseTask = default;
  292. if (response.Status == 200)
  293. {
  294. courseTask = JsonDocument.Parse(response.Content).RootElement.ToObject<CourseTask>();
  295. }
  296. return Ok(new { courseTask });
  297. }
  298. }
  299. case bool when $"{grant_type}".Equals("insert-scheduleTask", StringComparison.OrdinalIgnoreCase)
  300. || $"{grant_type}".Equals("change-scheduleTask", StringComparison.OrdinalIgnoreCase)
  301. || $"{grant_type}".Equals("delete-scheduleTask", StringComparison.OrdinalIgnoreCase):
  302. {
  303. if ( !request.TryGetProperty("datas", out JsonElement _datas))
  304. {
  305. return BadRequest();
  306. }
  307. string tbname = $"{scope}".Equals("school", StringComparison.OrdinalIgnoreCase) ? Constant.School : Constant.Teacher;
  308. List<CourseTaskChanged> datas = _datas.ToObject<List<CourseTaskChanged>>();
  309. if (scope.ToString().Equals("school", StringComparison.OrdinalIgnoreCase))
  310. {
  311. if (!request.TryGetProperty("periodId", out JsonElement _periodId)) return BadRequest();
  312. //获取相关的名单
  313. List<GroupListDto> groupListDtos= await GroupListService.GetGroupListByListids(client, _dingDing, datas.Select(z => z.groupId).ToHashSet().ToList(), school);
  314. //获取相关的教室
  315. var roomIds = datas.Where(x => !string.IsNullOrWhiteSpace(x.roomId)).Select(c=>$"'{c.roomId}'");
  316. List<Room> rooms = new List<Room>();
  317. if (roomIds.Any()) {
  318. string sqlRoom = $"select value c from c where c.id in ({string.Join(",", roomIds)})";
  319. var result= await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetList<Room>(sqlRoom,$"Room-{school}");
  320. if (result.list.IsNotEmpty()) {
  321. rooms.AddRange(result.list);
  322. }
  323. }
  324. //获取教师
  325. List<SchoolTeacher> schoolTeachers = new List<SchoolTeacher>();
  326. var teacherIds = datas.Where(x => !string.IsNullOrWhiteSpace(x.teacherId)).Select(c => $"'{c.teacherId}'");
  327. if (teacherIds.Any()) {
  328. string sqlTeacher = $"select value c from c where c.id in ({string.Join(",", teacherIds)}) ";
  329. var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetList<SchoolTeacher>(sqlTeacher, $"Teacher-{school}");
  330. if (result.list.IsNotEmpty())
  331. {
  332. schoolTeachers.AddRange(result.list);
  333. }
  334. }
  335. //获取课程
  336. List<CourseBase> courseBases = new List<CourseBase>();
  337. var courseIds = datas.Where(x => !string.IsNullOrWhiteSpace(x.courseId)).Select(c => $"'{c.courseId}'");
  338. if (courseIds.Any())
  339. {
  340. string sqlCourse = $"select value c from c where c.id in ({string.Join(",", courseIds)}) ";
  341. var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetList<CourseBase>(sqlCourse, $"CourseBase-{school}");
  342. if (result.list.IsNotEmpty())
  343. {
  344. courseBases.AddRange(result.list);
  345. }
  346. }
  347. School schoolBase = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>(school, new PartitionKey("Base"));
  348. var period = schoolBase.period.Find(x => x.id.Equals($"{_periodId}"));
  349. HashSet<CourseTask> courseTasks = new HashSet<CourseTask>();
  350. List<CourseTaskChanged> invalidCourseTaskInsert= new List<CourseTaskChanged>();
  351. foreach (var data in datas)
  352. {
  353. var courseTaskInsert = SchoolService.CheckCourseTaskInsertOrChanged($"{grant_type}", scope.ToString(),data, school, period, courseBases, groupListDtos, rooms, schoolTeachers,null);
  354. if (courseTaskInsert.invalidCode == 0)
  355. {
  356. string taskCode = $"CourseTask-{school}";
  357. string taskId = $"{courseTaskInsert.year}-{courseTaskInsert.semesterId}-{courseTaskInsert.courseId}";
  358. CourseTask courseTask = courseTasks.Where(z => z.id.Equals(taskId) && z.code.Equals(taskCode)).FirstOrDefault();
  359. if (courseTask == null)
  360. {
  361. Azure.Response response = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemStreamAsync(taskId, new PartitionKey(taskCode));
  362. if (response.Status == 200)
  363. {
  364. courseTask = JsonDocument.Parse(response.Content).RootElement.ToObject<CourseTask>();
  365. }
  366. else
  367. {
  368. courseTask = new CourseTask
  369. {
  370. id = taskId,
  371. code = taskCode,
  372. pk = "CourseTask",
  373. ttl = -1,
  374. courseId = courseTaskInsert.courseId,
  375. year = courseTaskInsert.year,
  376. semesterId = courseTaskInsert.semesterId,
  377. schedules = new List<ScheduleTask> { new ScheduleTask {
  378. roomId = courseTaskInsert.roomId,
  379. groupId = courseTaskInsert.groupId,
  380. type = courseTaskInsert.type,
  381. teacherId = courseTaskInsert.teacherId,
  382. notice=courseTaskInsert.notice,
  383. startTime = courseTaskInsert.startTime,
  384. times= new List<ScheduleTime>(),
  385. school=school,
  386. } }
  387. };
  388. }
  389. }
  390. var scheduleTask = courseTask.schedules.Find(z => z.type.Equals(courseTaskInsert.type) && z.groupId.Equals(courseTaskInsert.groupId) && z.teacherId.Equals(courseTaskInsert.teacherId));
  391. if (scheduleTask == null)
  392. {
  393. scheduleTask = new ScheduleTask()
  394. {
  395. roomId = courseTaskInsert.roomId,
  396. groupId = courseTaskInsert.groupId,
  397. type = courseTaskInsert.type,
  398. teacherId = courseTaskInsert.teacherId,
  399. times = new List<ScheduleTime>(),
  400. school = school,
  401. };
  402. courseTask.schedules.Add(scheduleTask);
  403. }
  404. else
  405. {
  406. scheduleTask.roomId = courseTaskInsert.roomId;
  407. scheduleTask.school=school;
  408. }
  409. //修改教师或名单
  410. if (grant_type.ToString().Equals("change-scheduleTask", StringComparison.OrdinalIgnoreCase)) {
  411. if (!string.IsNullOrWhiteSpace(courseTaskInsert.teacherIdChanged)) {
  412. scheduleTask.teacherId = courseTaskInsert.teacherIdChanged;
  413. }
  414. if (!string.IsNullOrWhiteSpace(courseTaskInsert.typeChanged) && !string.IsNullOrWhiteSpace(courseTaskInsert.groupIdChanged)) {
  415. scheduleTask.groupId = courseTaskInsert.groupIdChanged;
  416. scheduleTask.type = courseTaskInsert.typeChanged;
  417. }
  418. }
  419. //删除教师及名单的排课信息
  420. if (grant_type.ToString().Equals("delete-scheduleTask", StringComparison.OrdinalIgnoreCase))
  421. {
  422. courseTask.schedules.Remove(scheduleTask);
  423. }
  424. //如果被删除完了,就删除该条记录。
  425. if (courseTask.schedules.Count <= 0)
  426. {
  427. courseTasks.Remove(courseTask);
  428. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).DeleteItemStreamAsync(courseTask.id, new PartitionKey(courseTask.code));
  429. }
  430. else {
  431. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).UpsertItemAsync(courseTask, new PartitionKey(taskCode));
  432. }
  433. }
  434. else {
  435. invalidCourseTaskInsert.Add(courseTaskInsert);
  436. }
  437. }
  438. return Ok(new { invalidCourseTaskInsert, courseTasks });
  439. }
  440. else {
  441. //获取相关的名单
  442. List<GroupListDto> groupListDtos = await GroupListService.GetGroupListByListids(client, _dingDing, datas.Select(z => z.groupId).ToHashSet().ToList(), school);
  443. //获取相关的教室
  444. var roomIds = datas.Where(x => !string.IsNullOrWhiteSpace(x.roomId)).Select(c => $"'{c.roomId}'");
  445. List<Room> rooms = new List<Room>();
  446. if (roomIds.Any() && !string.IsNullOrWhiteSpace(school))
  447. {
  448. string sqlRoom = $"select value c from c where c.id in ({string.Join(",", roomIds)})";
  449. var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetList<Room>(sqlRoom, $"Room-{school}");
  450. if (result.list.IsNotEmpty())
  451. {
  452. rooms.AddRange(result.list);
  453. }
  454. }
  455. //获取教师
  456. List<Teacher> teachers = new List<Teacher>();
  457. var teacherIds = datas.Where(x => !string.IsNullOrWhiteSpace(x.teacherId)).Select(c => $"'{c.teacherId}'");
  458. if (teacherIds.Any())
  459. {
  460. string sqlTeacher = $"select value c from c where c.id in ({string.Join(",", teacherIds)}) ";
  461. var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetList<Teacher>(sqlTeacher, $"Base");
  462. if (result.list.IsNotEmpty())
  463. {
  464. teachers.AddRange(result.list);
  465. }
  466. }
  467. //获取课程
  468. List<CourseBase> courseBases = new List<CourseBase>();
  469. var courseIds = datas.Where(x => !string.IsNullOrWhiteSpace(x.courseId)).Select(c => $"'{c.courseId}'");
  470. if (courseIds.Any())
  471. {
  472. string sqlCourse = $"select value c from c where c.id in ({string.Join(",", courseIds)}) ";
  473. var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetList<CourseBase>(sqlCourse, $"CourseBase-{tmdid}");
  474. if (result.list.IsNotEmpty())
  475. {
  476. courseBases.AddRange(result.list);
  477. }
  478. }
  479. HashSet<CourseTask> courseTasks = new HashSet<CourseTask>();
  480. List<CourseTaskChanged> invalidCourseTaskInsert = new List<CourseTaskChanged>();
  481. foreach (var data in datas)
  482. {
  483. var courseTaskInsert = SchoolService.CheckCourseTaskInsertOrChanged($"{grant_type}", scope.ToString(),data, null, null, courseBases, groupListDtos, rooms,null, teachers);
  484. if (courseTaskInsert.invalidCode == 0)
  485. {
  486. string taskCode = $"CourseTask-{tmdid}";
  487. string taskId = courseTaskInsert.courseId;
  488. CourseTask courseTask = courseTasks.Where(z => z.id.Equals(taskId) && z.code.Equals(taskCode)).FirstOrDefault();
  489. if (courseTask == null)
  490. {
  491. Azure.Response response = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReadItemStreamAsync(taskId, new PartitionKey(taskCode));
  492. if (response.Status == 200)
  493. {
  494. courseTask = JsonDocument.Parse(response.Content).RootElement.ToObject<CourseTask>();
  495. }
  496. else
  497. {
  498. courseTask = new CourseTask
  499. {
  500. id = taskId,
  501. code = taskCode,
  502. pk = "CourseTask",
  503. ttl = -1,
  504. courseId = courseTaskInsert.courseId,
  505. schedules = new List<ScheduleTask> { new ScheduleTask {
  506. roomId = courseTaskInsert.roomId,
  507. groupId = courseTaskInsert.groupId,
  508. type = courseTaskInsert.type,
  509. teacherId = courseTaskInsert.teacherId,
  510. notice=courseTaskInsert.notice,
  511. startTime = courseTaskInsert.startTime,
  512. times= new List<ScheduleTime>(),
  513. school=courseTaskInsert.school,
  514. } }
  515. };
  516. }
  517. }
  518. var scheduleTask = courseTask.schedules.Find(z => z.type.Equals(courseTaskInsert.type) && z.groupId.Equals(courseTaskInsert.groupId) && z.teacherId.Equals(courseTaskInsert.teacherId));
  519. if (scheduleTask == null)
  520. {
  521. scheduleTask = new ScheduleTask()
  522. {
  523. roomId = courseTaskInsert.roomId,
  524. groupId = courseTaskInsert.groupId,
  525. type = courseTaskInsert.type,
  526. teacherId = courseTaskInsert.teacherId,
  527. times = new List<ScheduleTime>(),
  528. school = courseTaskInsert.school,
  529. };
  530. courseTask.schedules.Add(scheduleTask);
  531. }
  532. else
  533. {
  534. scheduleTask.roomId = courseTaskInsert.roomId;
  535. scheduleTask.school = courseTaskInsert.school;
  536. }
  537. //修改教师或名单
  538. if (grant_type.ToString().Equals("change-scheduleTask", StringComparison.OrdinalIgnoreCase))
  539. {
  540. if (!string.IsNullOrWhiteSpace(courseTaskInsert.teacherIdChanged))
  541. {
  542. scheduleTask.teacherId = courseTaskInsert.teacherIdChanged;
  543. }
  544. if (!string.IsNullOrWhiteSpace(courseTaskInsert.typeChanged) && !string.IsNullOrWhiteSpace(courseTaskInsert.groupIdChanged))
  545. {
  546. scheduleTask.groupId = courseTaskInsert.groupIdChanged;
  547. scheduleTask.type = courseTaskInsert.typeChanged;
  548. }
  549. }
  550. courseTasks.Add(courseTask);
  551. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).UpsertItemAsync(courseTask, new PartitionKey(taskCode));
  552. }
  553. else
  554. {
  555. invalidCourseTaskInsert.Add(courseTaskInsert);
  556. }
  557. }
  558. return Ok(new { invalidCourseTaskInsert, courseTasks });
  559. }
  560. }
  561. //按照模板导入进行数据转换并且进行检查
  562. case bool when $"{grant_type}".Equals("import-check") && $"{scope}".Equals("school", StringComparison.OrdinalIgnoreCase):
  563. {
  564. //检查完成,生成一个检查通过的token+检查结果(pass,warn,error), 在正式导入的时候,只需要检查token是否存在则进行数据保存。 以确保每次被导入的数据都是检查通过的。
  565. //并标记相关检查状态对于的具体数值。
  566. //数据转换是必须的,可选是否开启数据检查,数据检查包括导入数据自检(逻辑,排他,教室-名单-教师-时间段,重复),导入数据与数据库数据库的比对检查。
  567. //课程 批量升学年 学期.
  568. if (!request.TryGetProperty("courseCheckImports", out JsonElement _courseCheckImports)) return BadRequest();
  569. if (!request.TryGetProperty("periodId", out JsonElement _periodId)) return BadRequest();
  570. request.TryGetProperty("majorId", out JsonElement _majorId) ;
  571. School schoolBase = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>(school, new PartitionKey("Base"));
  572. var period = schoolBase.period.Find(x => x.id.Equals($"{_periodId}"));
  573. if (period == null) {
  574. return Ok(new { code = 1, msg = "学段不存在!" });
  575. }
  576. List<CourseCheckImport> courseCheckImports= _courseCheckImports.ToObject<List<CourseCheckImport>>();
  577. //数据检查
  578. //1.检查导入的课程名称是否有效
  579. StringBuilder sqlName = new StringBuilder(" select value c from c ");
  580. sqlName.Append($" where c.name in({string.Join(",", courseCheckImports.Select(z=>$"'{z.name}'"))}) and c.period.id='{_periodId}' ");
  581. if (!string.IsNullOrWhiteSpace($"{_majorId}"))
  582. {
  583. var major = period.majors.Find(z => z.id.Equals($"{_majorId}"));
  584. if (major==null) {
  585. return Ok(new { code = 2, msg = "专业不存在!" });
  586. }
  587. sqlName.Append($" and c.major.id='{_majorId}'");
  588. }
  589. List<CourseBase> courseBases = new List<CourseBase>() ;
  590. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School)
  591. .GetItemQueryIterator<CourseBase>(queryText: sqlName.ToString(), requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"CourseBase-{school}") }))
  592. {
  593. courseBases.Add(item);
  594. }
  595. HashSet<CourseCheckImport> courseInvalidImports = new HashSet<CourseCheckImport>();
  596. var nameInvalidImports = courseCheckImports.ExceptBy(courseBases.Select(x => x.name),z=>z.name);
  597. //保留课程名称存在的排课信息
  598. if (nameInvalidImports != null && nameInvalidImports.Any())
  599. {
  600. foreach (var nameInvalidImport in nameInvalidImports)
  601. {
  602. nameInvalidImport.invalidCode =1;
  603. courseInvalidImports.Add(nameInvalidImport);
  604. }
  605. courseCheckImports.RemoveAll(z=> nameInvalidImports.Contains(z));
  606. }
  607. //2.检查导入的醍摩豆教师ID是否有效
  608. StringBuilder sqlTmdid = new StringBuilder(" select c.id,c.name ,c.code ,c.picture from c ");
  609. sqlTmdid.Append($" where c.id in({string.Join(",", courseCheckImports.Select(z => $"'{z.tmdid}'"))}) ");
  610. List<IdNameCode> teachers = new List<IdNameCode>();
  611. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher)
  612. .GetItemQueryIterator<IdNameCode>(queryText: sqlTmdid.ToString(), requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey("Base") }))
  613. {
  614. teachers.Add(item);
  615. }
  616. var tmdidInvalidImports = courseCheckImports.ExceptBy(teachers.Select(x => x.id), z => z.tmdid);
  617. //保留课程名称存在的及醍摩豆ID有效的排课信息
  618. if (tmdidInvalidImports != null && tmdidInvalidImports.Any())
  619. {
  620. foreach (var tmdidInvalidImport in tmdidInvalidImports)
  621. {
  622. tmdidInvalidImport.invalidCode = 2;
  623. courseInvalidImports.Add(tmdidInvalidImport);
  624. }
  625. courseCheckImports.RemoveAll(z => tmdidInvalidImports.Contains(z));
  626. }
  627. //3.检查导入的教学班名称是否有效
  628. IEnumerable<CourseCheckImport> teachInvalidImports = null;
  629. List<GroupList> groupLists = new List<GroupList>();
  630. var teachList = courseCheckImports.Where(x => x.type.Equals("teach"));
  631. if (teachList.Any() && teachList.Count()>0) {
  632. StringBuilder sqlTeach = new StringBuilder(" select value c from c ");
  633. sqlTeach.Append($" where c.name in({string.Join(",", teachList.Select(z => $"'{z.list}'"))}) ");
  634. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School)
  635. .GetItemQueryIterator<GroupList>(queryText: sqlTeach.ToString(), requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"GroupList-{school}") }))
  636. {
  637. groupLists.Add(item);
  638. }
  639. teachInvalidImports = courseCheckImports.ExceptBy(groupLists.Select(x => x.name), z => z.list);
  640. //保留课程名称存在的及醍摩豆ID有效的排课信息
  641. if (teachInvalidImports != null && teachInvalidImports.Any())
  642. {
  643. foreach (var teachInvalidImport in teachInvalidImports)
  644. {
  645. teachInvalidImport.invalidCode = 3;
  646. courseInvalidImports.Add(teachInvalidImport);
  647. }
  648. courseCheckImports.RemoveAll(z => teachInvalidImports.Contains(z));
  649. }
  650. }
  651. //4.检查导入的教室编号是否有效
  652. //获取填写了教室编号的数据
  653. var roomNos= courseCheckImports.Where(z => !string.IsNullOrWhiteSpace(z.roomNo));
  654. IEnumerable<CourseCheckImport> roomNoInvalidImports = null;
  655. List<Room> rooms = new List<Room>();
  656. if (roomNos.Any() && roomNos.Count() > 0)
  657. {
  658. StringBuilder sqlRoom = new StringBuilder(" select value c from c ");
  659. sqlRoom.Append($" where c.no in({string.Join(",", roomNos.Select(z => $"'{z.roomNo}'"))}) ");
  660. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School)
  661. .GetItemQueryIterator<Room>(queryText: sqlRoom.ToString(), requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Room-{school}") }))
  662. {
  663. rooms.Add(item);
  664. }
  665. roomNoInvalidImports = courseCheckImports.ExceptBy(rooms.Select(x => x.no), z => z.roomNo);
  666. //保留课程名称存在的及醍摩豆ID有效的排课信息
  667. if (roomNoInvalidImports != null && roomNoInvalidImports.Any())
  668. {
  669. foreach (var roomNoInvalidImport in roomNoInvalidImports)
  670. {
  671. roomNoInvalidImport.invalidCode = 4;
  672. courseInvalidImports.Add(roomNoInvalidImport);
  673. }
  674. courseCheckImports.RemoveAll(z => roomNoInvalidImports.Contains(z));
  675. }
  676. }
  677. //5.检查开学日期,行政班编号是否有效
  678. //List<CourseCheckImport> stimeInvalidImports = new List<CourseCheckImport>() ;
  679. //List<CourseCheckImport> etimeInvalidImports = new List<CourseCheckImport>();
  680. //List<CourseCheckImport> scheduleInvalidImports = new List<CourseCheckImport>();
  681. //List<CourseCheckImport> classIdNoInvalidImports = new List<CourseCheckImport>();
  682. Dictionary<string,List<Class>> duplicateClasses= new Dictionary<string, List<Class>>();
  683. //1 上课时间段的
  684. var timeTables = period.timetable.Where(z => z.type.Equals("1")).ToList();
  685. HashSet< CourseTask > courseTasks = new HashSet<CourseTask>();
  686. int checkedCount = 0;
  687. foreach (var item in courseCheckImports)
  688. {
  689. DateTimeOffset sdateTime = default;
  690. DateTimeOffset edateTime = default;
  691. //5.1.检查开学日期格式是否正确
  692. if (!DateTimeOffset.TryParseExact(item.stime, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out sdateTime))
  693. {
  694. item.invalidCode = 5;
  695. courseInvalidImports.Add(item);
  696. continue;
  697. }
  698. //获取当前学年,当前学期,当前导入时间的日期,以及下学期开学时间
  699. (Semester currSemester, int studyYear, DateTimeOffset date, DateTimeOffset nextSemester) info = SchoolService.GetSemester(period, item.stime);
  700. if (info.currSemester != null)
  701. {
  702. //5.2检查课程结束日期格式是否正确
  703. if (!string.IsNullOrWhiteSpace(item.etime))
  704. {
  705. if (!DateTimeOffset.TryParseExact(item.etime, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out edateTime))
  706. {
  707. item.invalidCode = 6;
  708. courseInvalidImports.Add(item);
  709. continue;
  710. }
  711. }
  712. else
  713. {
  714. //未设置课程结束时间,开学前一天
  715. edateTime = info.nextSemester.AddDays(-1);
  716. }
  717. }
  718. else {
  719. //15.根据开学时间无法获取学期信息
  720. item.invalidCode = 15;
  721. courseInvalidImports.Add(item);
  722. continue;
  723. }
  724. ScheduleTime scheduleTime = null;
  725. //5.3检查排课字段格式,数据是否符合要求
  726. if (!string.IsNullOrWhiteSpace(item.schedule)) {
  727. string[] datas= item.schedule.Split('-');
  728. if (datas.Length >= 3) {
  729. int timeIndex = -1;
  730. int weekIndex = -1;
  731. string mode =string.Empty;
  732. if (int.TryParse(datas[0], out timeIndex) && timeIndex > 0
  733. && int.TryParse(datas[1], out weekIndex) && weekIndex > 0
  734. && (datas[2].Equals("A", StringComparison.OrdinalIgnoreCase) || datas[2].Equals("D", StringComparison.OrdinalIgnoreCase) || datas[2].Equals("C", StringComparison.OrdinalIgnoreCase)))
  735. {
  736. mode = datas[2];
  737. HashSet<int> weekIndexs = new HashSet<int>();
  738. if (mode.Equals("C"))
  739. {
  740. if (datas.Length == 4)
  741. {
  742. var customWeeks = datas[3].Split(',');
  743. bool hasInvalidData = false;
  744. HashSet<int> weeks = new HashSet<int>();
  745. foreach (var customWeek in customWeeks)
  746. {
  747. if (int.TryParse(customWeek, out int customWeekIndex) && customWeekIndex > 0)
  748. {
  749. weeks.Add(customWeekIndex);
  750. }
  751. else {
  752. hasInvalidData = true;
  753. break;
  754. }
  755. }
  756. if (hasInvalidData)
  757. {
  758. //C 自定义模式下,配置的上课周是大于等于1的整数
  759. item.invalidCode = 11;
  760. courseInvalidImports.Add(item);
  761. continue;
  762. }
  763. else {
  764. weekIndexs = weeks;
  765. }
  766. }
  767. else {
  768. //C 自定义模式下,需要配置对应的上课周
  769. item.invalidCode = 10;
  770. courseInvalidImports.Add(item);
  771. continue;
  772. }
  773. }
  774. scheduleTime = new ScheduleTime();
  775. try {
  776. var timeTable = timeTables[timeIndex-1];
  777. scheduleTime.id= timeTable.id;
  778. }
  779. catch (Exception ex)
  780. {
  781. //数组越界,表示导入的不存在,没有对应的上课时间段
  782. item.invalidCode = 8;
  783. courseInvalidImports.Add(item);
  784. continue;
  785. }
  786. try
  787. {
  788. var week = weekDays[weekIndex - 1];
  789. scheduleTime.week = week;
  790. }
  791. catch (Exception ex)
  792. {
  793. //数组越界,表示导入的不存在
  794. //上课时间不在星期一至星期日
  795. item.invalidCode = 9;
  796. courseInvalidImports.Add(item);
  797. continue;
  798. }
  799. scheduleTime.mode= mode;
  800. scheduleTime.index = weekIndexs;
  801. }
  802. else {
  803. //不满足最基本的1-1-A格式,可能是不是数字,或者不是A,D,C模式,
  804. //排课时间格式不满足[1-n]-[1|2|3|4|5|6|7]-[A|D|C]
  805. item.invalidCode = 7;
  806. courseInvalidImports.Add(item);
  807. continue;
  808. }
  809. }
  810. else
  811. {
  812. //不满足最基本的1-1-A格式
  813. //排课时间格式不满足[1-n]-[1|2|3|4|5|6|7]-[A|D|C]
  814. item.invalidCode = 7;
  815. courseInvalidImports.Add(item);
  816. continue;
  817. }
  818. }
  819. string groupId = string.Empty;
  820. //5.4 检查导入的行政班编号是否有效
  821. if (item.type.Equals("class"))
  822. {
  823. var yearNo = item.list.Split("-");
  824. if (yearNo.Length == 2)
  825. {
  826. StringBuilder sqlYearNo = new StringBuilder(" select value c from c ");
  827. sqlYearNo.Append($" where c.year ={yearNo[0]} and c.no ='{yearNo[1]}' and c.periodId='{period.id}' ");
  828. List<Class> classes = new List<Class>();
  829. await foreach (var classInfo in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School)
  830. .GetItemQueryIterator<Class>(queryText: sqlYearNo.ToString(), requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Class-{school}") }))
  831. {
  832. classes.Add(classInfo);
  833. }
  834. if (classes.Count > 1)
  835. {
  836. ///班级入学年-编号重复的班级
  837. duplicateClasses.Add(item.list, classes);
  838. //导入的班级入学年-编号在系统中重复,请检查行政班设置。
  839. item.invalidCode = 13;
  840. courseInvalidImports.Add(item);
  841. continue;
  842. }
  843. else if (classes.Count <= 0)
  844. {
  845. //班级入学年-编号不存在
  846. item.invalidCode = 12;
  847. courseInvalidImports.Add(item);
  848. continue;
  849. }
  850. else
  851. {
  852. Class @class = classes[0];
  853. groupId = @class.id;
  854. }
  855. }
  856. else
  857. {
  858. courseInvalidImports.Add(item);
  859. //导入的班级入学年-编号格式错误
  860. item.invalidCode = 14;
  861. continue;
  862. }
  863. }
  864. else {
  865. var groupList= groupLists.Find(z => z.name.Equals(item.list));
  866. groupId=groupList?.id;
  867. }
  868. Room room = rooms.Find(z =>!string.IsNullOrWhiteSpace(item.roomNo) && z.no.Equals(item.roomNo));
  869. string roomId= room?.id;
  870. string teacherId = teachers.Find(z => z.id.Equals(item.tmdid))?.id;
  871. CourseBase courseBase = courseBases.Find(z => z.name.Equals(item.name));
  872. string taskId = $"{info.studyYear}-{info.currSemester.id}-{courseBase.id}";
  873. string taskCode = $"CourseTask-{school}";
  874. CourseTask courseTask = courseTasks.FirstOrDefault(z => z.id.Equals(taskId) && z.code.Equals(taskCode));
  875. if (courseTask == null) {
  876. Azure.Response courseTaskResponse = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemStreamAsync(taskId, new PartitionKey(taskCode));
  877. if (courseTaskResponse.Status == 200) {
  878. courseTask = JsonDocument.Parse(courseTaskResponse.Content).RootElement.ToObject<CourseTask>();
  879. }
  880. }
  881. if (courseTask == null)
  882. {
  883. courseTask = new CourseTask()
  884. {
  885. id = taskId,
  886. code = taskCode,
  887. expire = edateTime.ToUnixTimeMilliseconds(),
  888. pk = "CourseTask",
  889. ttl = -1,
  890. courseId = courseBase.id,
  891. year = info.studyYear,
  892. semesterId = info.currSemester.id,
  893. schedules = new List<ScheduleTask>
  894. {
  895. new ScheduleTask()
  896. {
  897. roomId=roomId,
  898. groupId=groupId,
  899. type=item.type,
  900. teacherId=teacherId,
  901. times= new List<ScheduleTime> { scheduleTime },
  902. school=school,
  903. }
  904. }
  905. };
  906. courseTasks.Add(courseTask);
  907. }
  908. else {
  909. var scheduleTask= courseTask.schedules.Find(z => z.type.Equals(item.type) && z.groupId.Equals(groupId) && z.teacherId.Equals(teacherId));
  910. if (scheduleTask == null)
  911. {
  912. courseTask.schedules.Add(new ScheduleTask()
  913. {
  914. roomId = roomId,
  915. groupId = groupId,
  916. type = item.type,
  917. teacherId = teacherId,
  918. times = new List<ScheduleTime> { scheduleTime },
  919. school = school,
  920. });
  921. }
  922. else {
  923. scheduleTask.roomId = roomId;
  924. scheduleTask.school = school;
  925. if (scheduleTime != null) {
  926. var shtime = scheduleTask.times.Find(z => z.id.Equals(scheduleTime.id) && z.week.Equals(scheduleTime.week) && z.mode.Equals(scheduleTime.mode));
  927. if (shtime == null)
  928. {
  929. scheduleTask.times.Add(scheduleTime);
  930. }
  931. else {
  932. if (scheduleTime.index.Any())
  933. {
  934. foreach (var ind in scheduleTime.index) {
  935. shtime.index.Add(ind);
  936. }
  937. }
  938. }
  939. }
  940. }
  941. }
  942. checkedCount++;
  943. }
  944. //生成检查结果token,有效期5分钟
  945. string checkToken=$"CourseTask:CheckToken:{scope}:{school}:{Guid.NewGuid()}" ;
  946. await _azureRedis.GetRedisClient(8).StringSetAsync(checkToken, courseTasks.ToJsonString(),expiry:new TimeSpan(0,5,0));
  947. return Ok(new { courseCheckedImports = courseTasks , checkedCount, invalidCount= courseInvalidImports.Count, courseInvalidImports, checkToken });
  948. }
  949. case bool when $"{grant_type}".Equals("import-task", StringComparison.OrdinalIgnoreCase) && $"{scope}".Equals("school", StringComparison.OrdinalIgnoreCase):
  950. {
  951. request.TryGetProperty("checkToken", out JsonElement _checkToken);
  952. if (!string.IsNullOrWhiteSpace($"{_checkToken}") && $"{_checkToken}".StartsWith($"CourseTask:CheckToken:{scope}:{school}:"))
  953. {
  954. RedisValue value = await _azureRedis.GetRedisClient(8).StringGetAsync($"{_checkToken}");
  955. List<CourseTask> courseTasks = value.ToString().ToObject<List<CourseTask>>();
  956. if (courseTasks.IsNotEmpty())
  957. {
  958. foreach (var task in courseTasks)
  959. {
  960. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).UpsertItemAsync(task, new PartitionKey(task.code));
  961. }
  962. return Ok(new { code=200 });
  963. }
  964. }
  965. return BadRequest();
  966. }
  967. }
  968. } catch (Exception ex) {
  969. await _dingDing.SendBotMsg($"{_option.Location},课程处理异常,{ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
  970. }
  971. return Ok();
  972. }
  973. }
  974. }