CourseBaseController.cs 118 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702
  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. using System.Text.RegularExpressions;
  30. using System.Security.Claims;
  31. namespace TEAMModelOS.Controllers.Both
  32. {
  33. [ProducesResponseType(StatusCodes.Status200OK)]
  34. [ProducesResponseType(StatusCodes.Status400BadRequest)]
  35. [Route("course-base")]
  36. [ApiController]
  37. public class CourseBaseController : ControllerBase
  38. {
  39. private AzureCosmosFactory _azureCosmos;
  40. private readonly DingDing _dingDing;
  41. private readonly Option _option;
  42. private readonly AzureServiceBusFactory _serviceBus;
  43. private readonly AzureStorageFactory _azureStorage;
  44. private readonly AzureRedisFactory _azureRedis;
  45. private static List<string> weekDays = new List<string> { "MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN" };
  46. public IConfiguration _configuration { get; set; }
  47. public CourseBaseController(AzureRedisFactory azureRedis, AzureCosmosFactory azureCosmos, DingDing dingDing, IOptionsSnapshot<Option> option, AzureServiceBusFactory serviceBus, AzureStorageFactory azureStorage, IConfiguration configuration)
  48. {
  49. _azureCosmos = azureCosmos;
  50. _dingDing = dingDing;
  51. _option = option?.Value;
  52. _serviceBus = serviceBus;
  53. _configuration = configuration;
  54. _azureStorage = azureStorage;
  55. _azureRedis = azureRedis;
  56. }
  57. /// <summary>
  58. /// 更新保存课程
  59. /// </summary>
  60. /// <param name="request"></param>
  61. /// <returns></returns>
  62. [ProducesDefaultResponseType]
  63. [AuthToken(Roles = "teacher,admin")]
  64. [HttpPost("manage")]
  65. #if !DEBUG
  66. [Authorize(Roles = "IES")]
  67. #endif
  68. public async Task<IActionResult> Manage(JsonElement request)
  69. {
  70. try
  71. {
  72. (string tmdid, _, _, string school) = HttpContext.GetAuthTokenInfo();
  73. if (!request.TryGetProperty("grant_type", out JsonElement grant_type)) return BadRequest();
  74. if (!request.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
  75. var client = _azureCosmos.GetCosmosClient();
  76. switch (true)
  77. {
  78. case bool when $"{grant_type}".Equals("list", StringComparison.OrdinalIgnoreCase):
  79. {
  80. if (!request.TryGetProperty("code", out JsonElement _code))
  81. {
  82. return BadRequest();
  83. }
  84. if (!request.TryGetProperty("periodId", out JsonElement _periodId)) return BadRequest();
  85. string tbname = $"{scope}".Equals("school", StringComparison.OrdinalIgnoreCase) ? Constant.School : Constant.Teacher;
  86. string code = $"CourseBase-{_code}";
  87. string baseSql = $"select value c from c where c.period.id='{_periodId}'";
  88. List<CourseBase> courseBases = new List<CourseBase>();
  89. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tbname)
  90. .GetItemQueryIterator<CourseBase>(queryText: baseSql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey(code) }))
  91. {
  92. courseBases.Add(item);
  93. }
  94. return Ok(new { courseBases = courseBases.OrderByDescending(z => z._ts) });
  95. }
  96. case bool when $"{grant_type}".Equals("delete", StringComparison.OrdinalIgnoreCase):
  97. {
  98. if (!request.TryGetProperty("id", out JsonElement _id) || !request.TryGetProperty("code", out JsonElement _code))
  99. {
  100. return BadRequest();
  101. }
  102. string tbname = $"{scope}".Equals("school", StringComparison.OrdinalIgnoreCase) ? Constant.School : Constant.Teacher;
  103. Azure.Response response = await client.GetContainer(Constant.TEAMModelOS, tbname).DeleteItemStreamAsync(_id.ToString(), new PartitionKey($"CourseBase-{_code}"));
  104. //需要联动删除排课
  105. string taskCode = $"CourseTask-{_code}";
  106. string taskSql = $"select value c from c where c.courseId='{_id}'";
  107. List<CourseTask> courseTasks = new List<CourseTask>();
  108. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tbname)
  109. .GetItemQueryIterator<CourseTask>(queryText: taskSql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey(taskCode) }))
  110. {
  111. courseTasks.Add(item);
  112. }
  113. if (courseTasks.Count > 0)
  114. {
  115. await client.GetContainer(Constant.TEAMModelOS, tbname).DeleteItemsStreamAsync(courseTasks.Select(x => x.id).ToList(), taskCode);
  116. }
  117. return Ok(new { code = response.Status });
  118. }
  119. case bool when $"{grant_type}".Equals("import-base", StringComparison.OrdinalIgnoreCase) && $"{scope}".Equals("school", StringComparison.OrdinalIgnoreCase):
  120. {
  121. if (!request.TryGetProperty("courses", out JsonElement _courses))
  122. {
  123. return BadRequest();
  124. }
  125. if (!request.TryGetProperty("periodId", out JsonElement _periodId)) return BadRequest();
  126. List<CourseBase> courseBases = _courses.ToObject<List<CourseBase>>();
  127. var noNo = courseBases.Where(x => string.IsNullOrWhiteSpace(x.no));
  128. if (noNo!=null &&noNo.Count()>0)
  129. {
  130. return Ok(new { code = 5, msg = "课程编号为空", courses = noNo });
  131. }
  132. var noName = courseBases.Where(x => string.IsNullOrWhiteSpace(x.name));
  133. if (noName!=null &&noName.Count()>0)
  134. {
  135. return Ok(new { code = 6, msg = "课程名称,年级", courses = noName });
  136. }
  137. //1.检查导入的课程名称是否有效
  138. StringBuilder sqlNo = new StringBuilder(" select value c from c ");
  139. sqlNo.Append($" where c.no in( {string.Join(",", courseBases.Select(z => $"'{z.no}'"))} ) and c.period.id='{_periodId}' ");
  140. string tbname = Constant.School;
  141. List<CourseBase> courseBasesDB = new List<CourseBase>();
  142. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tbname)
  143. .GetItemQueryIterator<CourseBase>(queryText: sqlNo.ToString(), requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"CourseBase-{school}") }))
  144. {
  145. courseBasesDB.Add(item);
  146. }
  147. if (courseBasesDB.IsNotEmpty())
  148. {
  149. courseBases.RemoveAll(x => courseBasesDB.Select(y => y.no).Contains(x.no));
  150. }
  151. List<CourseBase> courseNameDuplicate = new List<CourseBase>();
  152. School schoolBase = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>(school, new PartitionKey("Base"));
  153. var period = schoolBase.period.Find(x => x.id.Equals($"{_periodId}"));
  154. if (period != null)
  155. {
  156. foreach (var item in courseBases)
  157. {
  158. item.pk = "CourseBase";
  159. if (string.IsNullOrWhiteSpace(item.id))
  160. {
  161. item.id = Guid.NewGuid().ToString();
  162. }
  163. item.scope = "school";
  164. item.school = school;
  165. item.creatorId = tmdid;
  166. item.code = $"CourseBase-{school}";
  167. item.period = new IdName { id = period.id, name = period.name };
  168. if (!string.IsNullOrWhiteSpace(item.subject?.id))
  169. {
  170. var subject = period.subjects.Find(x => x.id.Equals(item.subject.id));
  171. if (subject != null)
  172. {
  173. item.subject.name = subject.name;
  174. }
  175. else
  176. {
  177. return Ok(new { code = 1, msg = "科目不存在", course = item });
  178. }
  179. }
  180. else
  181. {
  182. return Ok(new { code = 1, msg = "科目不存在", course = item });
  183. }
  184. if (!string.IsNullOrWhiteSpace(item.major?.id))
  185. {
  186. var major = period.majors.Find(x => x.id.Equals(item.major.id));
  187. if (major != null)
  188. {
  189. item.major.name = major.name;
  190. }
  191. else
  192. {
  193. return Ok(new { code = 2, msg = "专业不存在", course = item });
  194. }
  195. }
  196. StringBuilder sqlName = new StringBuilder(" select value c from c ");
  197. sqlName.Append($" where c.name='{item.name}' and c.grade={item.grade} and c.period.id='{_periodId}' ");
  198. var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetList<CourseBase>(sqlName.ToString(), item.code);
  199. if (result.list.IsNotEmpty())
  200. {
  201. courseNameDuplicate.Add(item);
  202. }
  203. else { await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tbname).UpsertItemAsync(item, new PartitionKey(item.code)); }
  204. }
  205. return Ok(new { course = courseBases, courseNoDuplicate = courseBasesDB, courseNameDuplicate });
  206. }
  207. else
  208. {
  209. return Ok(new { code = 3, msg = "学段不存在", });
  210. }
  211. }
  212. case bool when $"{grant_type}".Equals("upsert", StringComparison.OrdinalIgnoreCase):
  213. {
  214. if (!request.TryGetProperty("course", out JsonElement _course))
  215. {
  216. return BadRequest();
  217. }
  218. CourseBase courseBase = _course.ToObject<CourseBase>();
  219. courseBase.pk = "CourseBase";
  220. string tbname = $"{courseBase.scope}".Equals("school", StringComparison.OrdinalIgnoreCase) ? Constant.School : Constant.Teacher;
  221. //1.检查导入的课程名称是否有效
  222. StringBuilder sqlCourse = new StringBuilder(" select value c from c ");
  223. if (courseBase.scope.Equals("school", StringComparison.OrdinalIgnoreCase))
  224. {
  225. courseBase.school = school;
  226. courseBase.creatorId = tmdid;
  227. courseBase.code = $"CourseBase-{school}";
  228. if (string.IsNullOrWhiteSpace(courseBase.subject?.id) ||courseBase.grade<0)
  229. {
  230. return BadRequest();
  231. }
  232. if (string.IsNullOrWhiteSpace(courseBase.period?.id))
  233. {
  234. return BadRequest();
  235. }
  236. else
  237. {
  238. if (string.IsNullOrWhiteSpace(courseBase.id))
  239. {
  240. if (string.IsNullOrWhiteSpace(courseBase.no))
  241. {
  242. School schoolBase = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>(school, new PartitionKey("Base"));
  243. var period = schoolBase.period.Find(x => x.id.Equals($"{courseBase.period.id}"));
  244. //生成新的课程编号
  245. string sqlNo = $"select value c.no from c where c.period.id='{courseBase.period.id}' ";
  246. var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tbname).GetList<string>(sqlNo, courseBase.code);
  247. if (result.list.IsNotEmpty())
  248. {
  249. int index = period.subjects.FindIndex(z => z.id.Equals(courseBase.subject.id))+1;
  250. var nos = result.list.FindAll(x => x.StartsWith($"{index}"));
  251. if (nos != null)
  252. {
  253. string couresNo = string.Empty;
  254. List<string> order = nos.Where(y => !string.IsNullOrEmpty(y) && Regex.IsMatch(y, @"^\d*$")).OrderBy(x => int.Parse(x)).ToList();
  255. if (!order.Contains($"{index}00"))
  256. {
  257. order.Insert(0, $"{index}00");
  258. }
  259. if (order != null)
  260. {
  261. if (!order.Contains($"{index}00"))
  262. {
  263. order.Insert(0, $"{index}00");
  264. }
  265. }
  266. else { order = new List<string>() { $"{index}00" }; }
  267. for (int i = 0; i < order.Count; i++)
  268. {
  269. couresNo = $"{int.Parse(order[i]) + 1}";
  270. int no = i + 1;
  271. if (no <= order.Count - 1)
  272. {
  273. if (!couresNo.Equals(order[no]))
  274. {
  275. break;
  276. }
  277. }
  278. }
  279. if (string.IsNullOrWhiteSpace(couresNo))
  280. {
  281. couresNo=$"{index}99";
  282. }
  283. courseBase.no=couresNo;
  284. }
  285. else
  286. {
  287. courseBase.no= $"{index}01";
  288. }
  289. }
  290. else
  291. {
  292. courseBase.no= $"{(period.subjects.FindIndex(z => z.id.Equals(courseBase.subject.id))+1)}01";
  293. }
  294. }
  295. }
  296. else
  297. {
  298. if (string.IsNullOrWhiteSpace(courseBase.no))
  299. {
  300. //编辑时,编号不能为空
  301. return Ok(new { code = 6, course = courseBase });
  302. }
  303. }
  304. sqlCourse.Append($" where c.no ='{courseBase.no}' ");
  305. sqlCourse.Append($" and c.period.id='{courseBase.period.id}' ");
  306. }
  307. }
  308. else
  309. {
  310. sqlCourse.Append($" where c.name ='{courseBase.name}' ");
  311. courseBase.creatorId = tmdid;
  312. courseBase.code = $"CourseBase-{tmdid}";
  313. }
  314. List<CourseBase> courseBases = new List<CourseBase>();
  315. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tbname)
  316. .GetItemQueryIterator<CourseBase>(queryText: sqlCourse.ToString(), requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey(courseBase.code) }))
  317. {
  318. if (courseBase.scope.Equals(item.scope))
  319. {
  320. if (courseBase.scope.Equals("school", StringComparison.OrdinalIgnoreCase))
  321. {
  322. //不是同一条数据,但是编号相同,则判定编号重复。
  323. if (!string.IsNullOrWhiteSpace(courseBase.id))
  324. {
  325. if (!item.id.Equals(courseBase.id) && item.no.Equals(courseBase.no))
  326. {
  327. return Ok(new { code = 4, course = courseBase });
  328. }
  329. }
  330. else
  331. {
  332. if (item.no.Equals(courseBase.no))
  333. {
  334. return Ok(new { code = 4, course = courseBase });
  335. }
  336. }
  337. }
  338. else
  339. {
  340. //不是同一条数据,但是名称相同,则判定名字重复。
  341. if (!item.id.Equals(courseBase.id) && item.name.Equals(courseBase.name))
  342. {
  343. return Ok(new { code = 5, course = courseBase });
  344. }
  345. }
  346. }
  347. }
  348. if (courseBase.scope.Equals("school", StringComparison.OrdinalIgnoreCase))
  349. {
  350. string sqlNameGrade = $"select value c from c where c.name ='{courseBase.name}' and c.grade={courseBase.grade} and c.period.id='{courseBase.period.id}' ";
  351. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tbname)
  352. .GetItemQueryIterator<CourseBase>(queryText: sqlNameGrade, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey(courseBase.code) }))
  353. {
  354. //不是同一条数据,但是名字年级重复
  355. if (!string.IsNullOrWhiteSpace(courseBase.id))
  356. {
  357. if (!item.id.Equals(courseBase.id) && item.name.Equals(courseBase.name) && item.grade== courseBase.grade)
  358. {
  359. //名字和年级重复
  360. return Ok(new { code = 5, course = courseBase });
  361. }
  362. }
  363. else
  364. {
  365. if (item.name.Equals(courseBase.name) && item.grade== courseBase.grade)
  366. {
  367. //名字和年级重复
  368. return Ok(new { code = 5, course = courseBase });
  369. }
  370. }
  371. }
  372. }
  373. if (string.IsNullOrWhiteSpace(courseBase.id))
  374. {
  375. courseBase.id = Guid.NewGuid().ToString();
  376. }
  377. await client.GetContainer(Constant.TEAMModelOS, tbname).UpsertItemAsync(courseBase, new PartitionKey(courseBase.code));
  378. return Ok(new { code = 200, course = courseBase });
  379. }
  380. case bool when $"{grant_type}".Equals("read-task", StringComparison.OrdinalIgnoreCase):
  381. {
  382. if (!request.TryGetProperty("courseId", out JsonElement _courseId)) return BadRequest();
  383. string tbname = $"{scope}".Equals("school", StringComparison.OrdinalIgnoreCase) ? Constant.School : Constant.Teacher;
  384. if (scope.ToString().Equals("school", StringComparison.OrdinalIgnoreCase))
  385. {
  386. if (!request.TryGetProperty("periodId", out JsonElement _periodId)) return BadRequest();
  387. int studyYear = -1;
  388. string semesterId = string.Empty;
  389. School schoolBase = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>(school, new PartitionKey("Base"));
  390. var period = schoolBase.period.Find(x => x.id.Equals($"{_periodId}"));
  391. if (!request.TryGetProperty("year", out JsonElement _year) || !request.TryGetProperty("semesterId", out JsonElement _semesterId))
  392. {
  393. //如果没传,则以当前时间获取学年和学期信息
  394. (Semester currSemester, int studyYear, DateTimeOffset date, DateTimeOffset nextSemester) info = SchoolService.GetSemester(period);
  395. semesterId = info.currSemester.id;
  396. studyYear = info.studyYear;
  397. }
  398. else
  399. {
  400. studyYear = _year.GetInt32();
  401. semesterId=_semesterId.GetString();
  402. }
  403. string taskCode = $"CourseTask-{school}";
  404. string taskId = $"{studyYear}-{semesterId}-{_courseId}";
  405. Azure.Response response = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tbname).ReadItemStreamAsync(taskId, new PartitionKey(taskCode));
  406. bool has_schedule = false;
  407. CourseTask courseTask = default;
  408. if (response.Status == 200)
  409. {
  410. courseTask=JsonDocument.Parse(response.Content).RootElement.ToObject<CourseTask>();
  411. if (courseTask != null && courseTask.schedules.IsNotEmpty())
  412. {
  413. has_schedule = true;
  414. }
  415. }
  416. //匹配建议的班级和教师
  417. List<Class> classes = new List<Class>();
  418. List<SchoolTeacher> teachers = new List<SchoolTeacher>();
  419. if (!has_schedule)
  420. {
  421. //如果没有找到排课安排信息。则可以进行建议升学年方式处理
  422. CourseBase courseBase = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<CourseBase>(_courseId.ToString(), new PartitionKey($"CourseBase-{school}"));
  423. if (courseBase.grade>=0)
  424. {
  425. var yearsdata = SchoolService.GetYears(schoolBase, _periodId.ToString(), new List<int> { courseBase.grade });
  426. List<int> years = yearsdata.years.ToList();
  427. if (years.IsNotEmpty())
  428. {
  429. StringBuilder sql = new StringBuilder($"select value c from c where c.year in ({string.Join(",", years)}) and c.periodId='{_periodId}' ");
  430. var result = await client.GetContainer(Constant.TEAMModelOS, Constant.School).GetList<Class>(sql.ToString(), $"Class-{school}");
  431. classes = result.list;
  432. }
  433. }
  434. if (!string.IsNullOrWhiteSpace(courseBase.subject?.id))
  435. {
  436. string teacherSQL = $"select distinct value c from c join b in c.subjectIds where b in ('{courseBase.subject.id}') and c.code = 'Teacher-{school}'";
  437. var result = await client.GetContainer(Constant.TEAMModelOS, Constant.School).GetList<SchoolTeacher>(teacherSQL.ToString(), $"Teacher-{school}");
  438. teachers = result.list;
  439. }
  440. }
  441. //当courseTask 为空,则matchedClasses可能会有年级匹配建议升学年的班级清单,
  442. //注:比如高二可能会将高三的课程学完,则该高三的课程的学年级应该是手动处理为高中二年级。不区分学期的目的,也是可能存在提前一学期学完第二学期的课程。
  443. 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 }) });
  444. }
  445. else
  446. {
  447. string taskCode = $"CourseTask-{tmdid}";
  448. string taskId = $"{_courseId}";
  449. Azure.Response response = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tbname).ReadItemStreamAsync(taskId, new PartitionKey(taskCode));
  450. CourseTask courseTask = default;
  451. if (response.Status == 200)
  452. {
  453. courseTask = JsonDocument.Parse(response.Content).RootElement.ToObject<CourseTask>();
  454. }
  455. return Ok(new { courseTask });
  456. }
  457. }
  458. case bool when $"{grant_type}".Equals("upsert-scheduleTask", StringComparison.OrdinalIgnoreCase):
  459. {
  460. List<ScheduleTaskDto> invalidCourseTask = new List<ScheduleTaskDto>();
  461. JsonElement _year = default, _semesterId = default, _courseId = default, _periodId = default;
  462. if (!request.TryGetProperty("courseId", out _courseId))
  463. {
  464. return BadRequest();
  465. }
  466. if (!request.TryGetProperty("datas", out JsonElement _datas))
  467. {
  468. return BadRequest();
  469. }
  470. if ($"{scope}".Equals("school", StringComparison.OrdinalIgnoreCase))
  471. {
  472. if (!request.TryGetProperty("periodId", out _periodId)) return BadRequest();
  473. if (!request.TryGetProperty("year", out _year))
  474. {
  475. return BadRequest();
  476. }
  477. if (!request.TryGetProperty("semesterId", out _semesterId))
  478. {
  479. return BadRequest();
  480. }
  481. }
  482. string tbname = $"{scope}".Equals("school", StringComparison.OrdinalIgnoreCase) ? Constant.School : Constant.Teacher;
  483. List<ScheduleTaskDto> datas = _datas.ToObject<List<ScheduleTaskDto>>();
  484. //过滤掉名单,教师空的数据
  485. var invalids = datas.FindAll(z => string.IsNullOrWhiteSpace(z.teacherId) || string.IsNullOrWhiteSpace(z.groupId) || string.IsNullOrWhiteSpace(z.type));
  486. if (invalids != null)
  487. {
  488. datas.RemoveAll(z => string.IsNullOrWhiteSpace(z.teacherId) || string.IsNullOrWhiteSpace(z.groupId) || string.IsNullOrWhiteSpace(z.type));
  489. foreach (var invalid in invalids)
  490. {
  491. if (string.IsNullOrWhiteSpace(invalid.groupId) || string.IsNullOrWhiteSpace(invalid.type))
  492. {
  493. invalid.invalidCode = 3;
  494. }
  495. if (string.IsNullOrWhiteSpace(invalid.teacherId))
  496. {
  497. invalid.invalidCode = 2;
  498. }
  499. invalidCourseTask.Add(invalid);
  500. }
  501. }
  502. var groups = datas.GroupBy(z => new { z.teacherId, z.groupId }).Select(x => new { key = x.Key, list = x.ToList() });
  503. foreach (var item in groups)
  504. {
  505. if (item.list.Count > 1)
  506. {
  507. return Ok(new { invalidCourseTask = item.list.Select(z => z.invalidCode=20) });//同一教师,同一班级,同一课程,只能有一条记录
  508. }
  509. }
  510. HashSet<CourseTask> courseTasks = new HashSet<CourseTask>();
  511. if (scope.ToString().Equals("school", StringComparison.OrdinalIgnoreCase))
  512. {
  513. string taskCode = $"CourseTask-{school}";
  514. string taskId = $"{_year}-{_semesterId}-{_courseId}";
  515. CourseTask courseTask = null;
  516. School schoolBase = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>(school, new PartitionKey("Base"));
  517. var period = schoolBase.period.Find(x => x.id.Equals($"{_periodId}"));
  518. //学年
  519. if (int.Parse(_year.ToString()) < 2000)
  520. {
  521. return Ok(new { invalidCode = 17 });//学年应大于2000
  522. }
  523. //学期
  524. var semester = period.semesters.Where(z => z.id.Equals(_semesterId.ToString()));
  525. if (!semester.Any())
  526. {
  527. return Ok(new { invalidCode = 16 });//学期不存在
  528. }
  529. CourseBase courseBase = null;
  530. Azure.Response responseBase = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemStreamAsync($"{_courseId.ToString()}", new PartitionKey($"CourseBase-{school}"));
  531. if (responseBase.Status == 200)
  532. {
  533. courseBase = JsonDocument.Parse(responseBase.Content).RootElement.ToObject<CourseBase>();
  534. }
  535. else
  536. {
  537. return Ok(new { invalidCode = 1 });//课程不存在
  538. }
  539. Azure.Response response = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemStreamAsync(taskId, new PartitionKey(taskCode));
  540. if (response.Status == 200)
  541. {
  542. courseTask = JsonDocument.Parse(response.Content).RootElement.ToObject<CourseTask>();
  543. }
  544. else
  545. {
  546. courseTask = new CourseTask
  547. {
  548. id = taskId,
  549. code = taskCode,
  550. pk = "CourseTask",
  551. ttl = -1,
  552. courseId = _courseId.ToString(),
  553. year = int.Parse(_year.ToString()),
  554. semesterId = _semesterId.ToString(),
  555. };
  556. }
  557. //获取相关的名单
  558. List<GroupListDto> groupListDtos = await GroupListService.GetGroupListByListids(client, _dingDing, datas.Select(z => z.groupId).ToHashSet().ToList(), school);
  559. //获取相关的教室
  560. var roomIds = datas.Where(x => !string.IsNullOrWhiteSpace(x.roomId)).Select(c => $"'{c.roomId}'");
  561. List<Room> rooms = new List<Room>();
  562. if (roomIds.Any())
  563. {
  564. string sqlRoom = $"select value c from c where c.id in ({string.Join(",", roomIds)})";
  565. var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetList<Room>(sqlRoom, $"Room-{school}");
  566. if (result.list.IsNotEmpty())
  567. {
  568. rooms.AddRange(result.list);
  569. }
  570. }
  571. //获取教师
  572. List<SchoolTeacher> schoolTeachers = new List<SchoolTeacher>();
  573. var teacherIds = datas.Where(x => !string.IsNullOrWhiteSpace(x.teacherId)).Select(c => c.teacherId);
  574. var assistants = datas.SelectMany(x => x.assistants);
  575. teacherIds = teacherIds.Union(assistants).ToHashSet();
  576. if (teacherIds.Any())
  577. {
  578. string sqlTeacher = $"select value c from c where c.id in ({string.Join(",", teacherIds.Select(x => $"'{x}'"))}) ";
  579. var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetList<SchoolTeacher>(sqlTeacher, $"Teacher-{school}");
  580. if (result.list.IsNotEmpty())
  581. {
  582. schoolTeachers.AddRange(result.list);
  583. }
  584. }
  585. foreach (var data in datas)
  586. {
  587. var courseTaskInsert = SchoolService.CheckCourseTask($"{scope}", data, school, groupListDtos, rooms, schoolTeachers, null);
  588. if (courseTaskInsert.invalidCode == 0)
  589. {
  590. var scheduleTask = courseTask.schedules.Find(z => z.type.Equals(courseTaskInsert.type) && z.groupId.Equals(courseTaskInsert.groupId));
  591. if (scheduleTask == null)
  592. {
  593. scheduleTask = new ScheduleTask()
  594. {
  595. roomId = courseTaskInsert.roomId,
  596. groupId = courseTaskInsert.groupId,
  597. type = courseTaskInsert.type,
  598. teacherId = courseTaskInsert.teacherId,
  599. times = new List<ScheduleTime>(),
  600. school = school,
  601. assistants = courseTaskInsert.assistants != null ? courseTaskInsert.assistants : new HashSet<string>()
  602. };
  603. courseTask.schedules.Add(scheduleTask);
  604. //新增
  605. }
  606. else
  607. {
  608. //编辑
  609. scheduleTask.roomId = courseTaskInsert.roomId;
  610. scheduleTask.school = school;
  611. scheduleTask.teacherId = courseTaskInsert.teacherId;
  612. scheduleTask.startTime= courseTaskInsert.startTime>0 ? courseTaskInsert.startTime : scheduleTask.startTime;
  613. scheduleTask.notice=string.IsNullOrWhiteSpace(courseTaskInsert.notice) ? scheduleTask.notice : courseTaskInsert.notice;
  614. scheduleTask.assistants= courseTaskInsert.assistants!=null ? courseTaskInsert.assistants : scheduleTask.assistants;
  615. }
  616. //如果被删除完了,就删除该条记录。
  617. if (courseTask.schedules.Count <= 0)
  618. {
  619. courseTasks.Remove(courseTask);
  620. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).DeleteItemStreamAsync(courseTask.id, new PartitionKey(courseTask.code));
  621. }
  622. else
  623. {
  624. courseTasks.Add(courseTask);
  625. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).UpsertItemAsync(courseTask, new PartitionKey(taskCode));
  626. }
  627. }
  628. else
  629. {
  630. invalidCourseTask.Add(courseTaskInsert);
  631. }
  632. }
  633. }
  634. else
  635. {
  636. string taskCode = $"CourseTask-{tmdid}";
  637. string taskId = $"{_courseId}";
  638. CourseTask courseTask = null;
  639. CourseBase courseBase = null;
  640. Azure.Response responseBase = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReadItemStreamAsync($"{_courseId.ToString()}", new PartitionKey($"CourseBase-{tmdid}"));
  641. if (responseBase.Status == 200)
  642. {
  643. courseBase = JsonDocument.Parse(responseBase.Content).RootElement.ToObject<CourseBase>();
  644. }
  645. else
  646. {
  647. return Ok(new { invalidCode = 1 });//课程不存在
  648. }
  649. Azure.Response response = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReadItemStreamAsync(taskId, new PartitionKey(taskCode));
  650. if (response.Status == 200)
  651. {
  652. courseTask = JsonDocument.Parse(response.Content).RootElement.ToObject<CourseTask>();
  653. }
  654. else
  655. {
  656. courseTask = new CourseTask
  657. {
  658. id = taskId,
  659. code = taskCode,
  660. pk = "CourseTask",
  661. ttl = -1,
  662. courseId = _courseId.ToString(),
  663. year = int.Parse(_year.ToString()),
  664. semesterId = _semesterId.ToString(),
  665. };
  666. }
  667. //获取相关的名单
  668. List<GroupListDto> groupListDtos = await GroupListService.GetGroupListByListids(client, _dingDing, datas.Select(z => z.groupId).ToHashSet().ToList(), school);
  669. //获取相关的教室
  670. var roomIds = datas.Where(x => !string.IsNullOrWhiteSpace(x.roomId)).Select(c => $"'{c.roomId}'");
  671. List<Room> rooms = new List<Room>();
  672. if (roomIds.Any() && !string.IsNullOrWhiteSpace(school))
  673. {
  674. string sqlRoom = $"select value c from c where c.id in ({string.Join(",", roomIds)})";
  675. var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetList<Room>(sqlRoom, $"Room-{school}");
  676. if (result.list.IsNotEmpty())
  677. {
  678. rooms.AddRange(result.list);
  679. }
  680. }
  681. //获取教师
  682. List<Teacher> teachers = new List<Teacher>();
  683. var teacherIds = datas.Where(x => !string.IsNullOrWhiteSpace(x.teacherId)).Select(x => x.teacherId);
  684. var assistants = datas.SelectMany(x => x.assistants);
  685. teacherIds = teacherIds.Union(assistants).ToHashSet();
  686. if (teacherIds.Any())
  687. {
  688. string sqlTeacher = $"select value c from c where c.id in ({string.Join(",", teacherIds.Select(x => $"'{x}'"))}) ";
  689. var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetList<Teacher>(sqlTeacher, $"Base");
  690. if (result.list.IsNotEmpty())
  691. {
  692. teachers.AddRange(result.list);
  693. }
  694. }
  695. foreach (var data in datas)
  696. {
  697. var courseTaskInsert = SchoolService.CheckCourseTask($"{scope}", data, school, groupListDtos, rooms, null, teachers);
  698. if (courseTaskInsert.invalidCode == 0)
  699. {
  700. var scheduleTask = courseTask.schedules.Find(z => z.type.Equals(courseTaskInsert.type) && z.groupId.Equals(courseTaskInsert.groupId));
  701. if (scheduleTask == null)
  702. {
  703. scheduleTask = new ScheduleTask()
  704. {
  705. roomId = courseTaskInsert.roomId,
  706. groupId = courseTaskInsert.groupId,
  707. type = courseTaskInsert.type,
  708. teacherId = courseTaskInsert.teacherId,
  709. times = new List<ScheduleTime>(),
  710. school = school,
  711. };
  712. courseTask.schedules.Add(scheduleTask);
  713. //新增
  714. }
  715. else
  716. {
  717. //编辑
  718. scheduleTask.roomId = courseTaskInsert.roomId;
  719. scheduleTask.school = school;
  720. scheduleTask.teacherId = courseTaskInsert.teacherId;
  721. scheduleTask.startTime = courseTaskInsert.startTime > 0 ? courseTaskInsert.startTime : scheduleTask.startTime;
  722. scheduleTask.notice = string.IsNullOrWhiteSpace(courseTaskInsert.notice) ? scheduleTask.notice : courseTaskInsert.notice;
  723. scheduleTask.assistants = courseTaskInsert.assistants != null ? courseTaskInsert.assistants : courseTaskInsert.assistants;
  724. }
  725. //如果被删除完了,就删除该条记录。
  726. if (courseTask.schedules.Count <= 0)
  727. {
  728. courseTasks.Remove(courseTask);
  729. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).DeleteItemStreamAsync(courseTask.id, new PartitionKey(courseTask.code));
  730. }
  731. else
  732. {
  733. courseTasks.Add(courseTask);
  734. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).UpsertItemAsync(courseTask, new PartitionKey(taskCode));
  735. }
  736. }
  737. else
  738. {
  739. invalidCourseTask.Add(courseTaskInsert);
  740. }
  741. }
  742. }
  743. return Ok(new { invalidCourseTask, courseTasks });
  744. }
  745. case bool when $"{grant_type}".Equals("insert-scheduleTask", StringComparison.OrdinalIgnoreCase)
  746. || $"{grant_type}".Equals("change-scheduleTask", StringComparison.OrdinalIgnoreCase)
  747. || $"{grant_type}".Equals("delete-scheduleTask", StringComparison.OrdinalIgnoreCase):
  748. {
  749. if (!request.TryGetProperty("datas", out JsonElement _datas))
  750. {
  751. return BadRequest();
  752. }
  753. string tbname = $"{scope}".Equals("school", StringComparison.OrdinalIgnoreCase) ? Constant.School : Constant.Teacher;
  754. List<CourseTaskChanged> datas = _datas.ToObject<List<CourseTaskChanged>>();
  755. if (scope.ToString().Equals("school", StringComparison.OrdinalIgnoreCase))
  756. {
  757. if (!request.TryGetProperty("periodId", out JsonElement _periodId)) return BadRequest();
  758. //获取相关的名单
  759. List<GroupListDto> groupListDtos = await GroupListService.GetGroupListByListids(client, _dingDing, datas.Select(z => z.groupId).ToHashSet().ToList(), school);
  760. //获取相关的教室
  761. var roomIds = datas.Where(x => !string.IsNullOrWhiteSpace(x.roomId)).Select(c => $"'{c.roomId}'");
  762. List<Room> rooms = new List<Room>();
  763. if (roomIds.Any())
  764. {
  765. string sqlRoom = $"select value c from c where c.id in ({string.Join(",", roomIds)})";
  766. var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetList<Room>(sqlRoom, $"Room-{school}");
  767. if (result.list.IsNotEmpty())
  768. {
  769. rooms.AddRange(result.list);
  770. }
  771. }
  772. //获取教师
  773. List<SchoolTeacher> schoolTeachers = new List<SchoolTeacher>();
  774. var teacherIds = datas.Where(x => !string.IsNullOrWhiteSpace(x.teacherId)).Select(c => $"'{c.teacherId}'");
  775. if (teacherIds.Any())
  776. {
  777. string sqlTeacher = $"select value c from c where c.id in ({string.Join(",", teacherIds)}) ";
  778. var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetList<SchoolTeacher>(sqlTeacher, $"Teacher-{school}");
  779. if (result.list.IsNotEmpty())
  780. {
  781. schoolTeachers.AddRange(result.list);
  782. }
  783. }
  784. //获取课程
  785. List<CourseBase> courseBases = new List<CourseBase>();
  786. var courseIds = datas.Where(x => !string.IsNullOrWhiteSpace(x.courseId)).Select(c => $"'{c.courseId}'");
  787. if (courseIds.Any())
  788. {
  789. string sqlCourse = $"select value c from c where c.id in ({string.Join(",", courseIds)}) ";
  790. var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetList<CourseBase>(sqlCourse, $"CourseBase-{school}");
  791. if (result.list.IsNotEmpty())
  792. {
  793. courseBases.AddRange(result.list);
  794. }
  795. }
  796. School schoolBase = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>(school, new PartitionKey("Base"));
  797. var period = schoolBase.period.Find(x => x.id.Equals($"{_periodId}"));
  798. HashSet<CourseTask> courseTasks = new HashSet<CourseTask>();
  799. List<CourseTaskChanged> invalidCourseTaskInsert = new List<CourseTaskChanged>();
  800. foreach (var data in datas)
  801. {
  802. var courseTaskInsert = SchoolService.CheckCourseTaskInsertOrChanged($"{grant_type}", scope.ToString(), data, school, period, courseBases, groupListDtos, rooms, schoolTeachers, null);
  803. if (courseTaskInsert.invalidCode == 0)
  804. {
  805. string taskCode = $"CourseTask-{school}";
  806. string taskId = $"{courseTaskInsert.year}-{courseTaskInsert.semesterId}-{courseTaskInsert.courseId}";
  807. CourseTask courseTask = courseTasks.Where(z => z.id.Equals(taskId) && z.code.Equals(taskCode)).FirstOrDefault();
  808. if (courseTask == null)
  809. {
  810. Azure.Response response = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemStreamAsync(taskId, new PartitionKey(taskCode));
  811. if (response.Status == 200)
  812. {
  813. courseTask = JsonDocument.Parse(response.Content).RootElement.ToObject<CourseTask>();
  814. }
  815. else
  816. {
  817. courseTask = new CourseTask
  818. {
  819. id = taskId,
  820. code = taskCode,
  821. pk = "CourseTask",
  822. ttl = -1,
  823. courseId = courseTaskInsert.courseId,
  824. year = courseTaskInsert.year,
  825. semesterId = courseTaskInsert.semesterId,
  826. schedules = new List<ScheduleTask> { new ScheduleTask {
  827. roomId = courseTaskInsert.roomId,
  828. groupId = courseTaskInsert.groupId,
  829. type = courseTaskInsert.type,
  830. teacherId = courseTaskInsert.teacherId,
  831. notice=courseTaskInsert.notice,
  832. startTime = courseTaskInsert.startTime,
  833. times= new List<ScheduleTime>(),
  834. school=school,
  835. } }
  836. };
  837. }
  838. }
  839. ScheduleTask scheduleTask = null;
  840. var scheduleTasks = courseTask.schedules.FindAll(z => z.type.Equals(courseTaskInsert.type) && z.groupId.Equals(courseTaskInsert.groupId));
  841. if (scheduleTasks.IsNotEmpty())
  842. {
  843. if (scheduleTasks.Count > 2)
  844. {
  845. courseTask.schedules.RemoveRange(1, scheduleTasks.Count - 1);
  846. }
  847. scheduleTask= scheduleTasks.First();
  848. scheduleTask.roomId = courseTaskInsert.roomId;
  849. scheduleTask.school = school;
  850. scheduleTask.teacherId = courseTaskInsert.teacherId;
  851. scheduleTask.startTime = courseTaskInsert.startTime > 0 ? courseTaskInsert.startTime : scheduleTask.startTime;
  852. scheduleTask.notice = string.IsNullOrWhiteSpace(courseTaskInsert.notice) ? scheduleTask.notice : courseTaskInsert.notice;
  853. scheduleTask.assistants = courseTaskInsert.assistants != null ? courseTaskInsert.assistants : courseTaskInsert.assistants;
  854. }
  855. else
  856. {
  857. scheduleTask = new ScheduleTask()
  858. {
  859. roomId = courseTaskInsert.roomId,
  860. groupId = courseTaskInsert.groupId,
  861. type = courseTaskInsert.type,
  862. teacherId = courseTaskInsert.teacherId,
  863. times = new List<ScheduleTime>(),
  864. school = school,
  865. };
  866. courseTask.schedules.Add(scheduleTask);
  867. }
  868. //修改教师或名单
  869. if (grant_type.ToString().Equals("change-scheduleTask", StringComparison.OrdinalIgnoreCase))
  870. {
  871. if (!string.IsNullOrWhiteSpace(courseTaskInsert.teacherIdChanged))
  872. {
  873. scheduleTask.teacherId = courseTaskInsert.teacherIdChanged;
  874. }
  875. if (!string.IsNullOrWhiteSpace(courseTaskInsert.typeChanged) && !string.IsNullOrWhiteSpace(courseTaskInsert.groupIdChanged))
  876. {
  877. scheduleTask.groupId = courseTaskInsert.groupIdChanged;
  878. scheduleTask.type = courseTaskInsert.typeChanged;
  879. }
  880. }
  881. //删除教师及名单的排课信息
  882. if (grant_type.ToString().Equals("delete-scheduleTask", StringComparison.OrdinalIgnoreCase))
  883. {
  884. courseTask.schedules.Remove(scheduleTask);
  885. }
  886. //如果被删除完了,就删除该条记录。
  887. if (courseTask.schedules.Count <= 0)
  888. {
  889. courseTasks.Remove(courseTask);
  890. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).DeleteItemStreamAsync(courseTask.id, new PartitionKey(courseTask.code));
  891. }
  892. else
  893. {
  894. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).UpsertItemAsync(courseTask, new PartitionKey(taskCode));
  895. }
  896. }
  897. else
  898. {
  899. invalidCourseTaskInsert.Add(courseTaskInsert);
  900. }
  901. }
  902. return Ok(new { invalidCourseTaskInsert, courseTasks });
  903. }
  904. else
  905. {
  906. //获取相关的名单
  907. List<GroupListDto> groupListDtos = await GroupListService.GetGroupListByListids(client, _dingDing, datas.Select(z => z.groupId).ToHashSet().ToList(), school);
  908. //获取相关的教室
  909. var roomIds = datas.Where(x => !string.IsNullOrWhiteSpace(x.roomId)).Select(c => $"'{c.roomId}'");
  910. List<Room> rooms = new List<Room>();
  911. if (roomIds.Any() && !string.IsNullOrWhiteSpace(school))
  912. {
  913. string sqlRoom = $"select value c from c where c.id in ({string.Join(",", roomIds)})";
  914. var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetList<Room>(sqlRoom, $"Room-{school}");
  915. if (result.list.IsNotEmpty())
  916. {
  917. rooms.AddRange(result.list);
  918. }
  919. }
  920. //获取教师
  921. List<Teacher> teachers = new List<Teacher>();
  922. var teacherIds = datas.Where(x => !string.IsNullOrWhiteSpace(x.teacherId)).Select(c => $"'{c.teacherId}'");
  923. if (teacherIds.Any())
  924. {
  925. string sqlTeacher = $"select value c from c where c.id in ({string.Join(",", teacherIds)}) ";
  926. var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetList<Teacher>(sqlTeacher, $"Base");
  927. if (result.list.IsNotEmpty())
  928. {
  929. teachers.AddRange(result.list);
  930. }
  931. }
  932. //获取课程
  933. List<CourseBase> courseBases = new List<CourseBase>();
  934. var courseIds = datas.Where(x => !string.IsNullOrWhiteSpace(x.courseId)).Select(c => $"'{c.courseId}'");
  935. if (courseIds.Any())
  936. {
  937. string sqlCourse = $"select value c from c where c.id in ({string.Join(",", courseIds)}) ";
  938. var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetList<CourseBase>(sqlCourse, $"CourseBase-{tmdid}");
  939. if (result.list.IsNotEmpty())
  940. {
  941. courseBases.AddRange(result.list);
  942. }
  943. }
  944. HashSet<CourseTask> courseTasks = new HashSet<CourseTask>();
  945. List<CourseTaskChanged> invalidCourseTaskInsert = new List<CourseTaskChanged>();
  946. foreach (var data in datas)
  947. {
  948. var courseTaskInsert = SchoolService.CheckCourseTaskInsertOrChanged($"{grant_type}", scope.ToString(), data, null, null, courseBases, groupListDtos, rooms, null, teachers);
  949. if (courseTaskInsert.invalidCode == 0)
  950. {
  951. string taskCode = $"CourseTask-{tmdid}";
  952. string taskId = courseTaskInsert.courseId;
  953. CourseTask courseTask = courseTasks.Where(z => z.id.Equals(taskId) && z.code.Equals(taskCode)).FirstOrDefault();
  954. if (courseTask == null)
  955. {
  956. Azure.Response response = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReadItemStreamAsync(taskId, new PartitionKey(taskCode));
  957. if (response.Status == 200)
  958. {
  959. courseTask = JsonDocument.Parse(response.Content).RootElement.ToObject<CourseTask>();
  960. }
  961. else
  962. {
  963. courseTask = new CourseTask
  964. {
  965. id = taskId,
  966. code = taskCode,
  967. pk = "CourseTask",
  968. ttl = -1,
  969. courseId = courseTaskInsert.courseId,
  970. schedules = new List<ScheduleTask> { new ScheduleTask {
  971. roomId = courseTaskInsert.roomId,
  972. groupId = courseTaskInsert.groupId,
  973. type = courseTaskInsert.type,
  974. teacherId = courseTaskInsert.teacherId,
  975. notice=courseTaskInsert.notice,
  976. startTime = courseTaskInsert.startTime,
  977. times= new List<ScheduleTime>(),
  978. school=courseTaskInsert.school,
  979. } }
  980. };
  981. }
  982. }
  983. ScheduleTask scheduleTask = null;
  984. var scheduleTasks = courseTask.schedules.FindAll(z => z.type.Equals(courseTaskInsert.type) && z.groupId.Equals(courseTaskInsert.groupId));
  985. if (scheduleTasks.IsNotEmpty())
  986. {
  987. if (scheduleTasks.Count > 2)
  988. {
  989. courseTask.schedules.RemoveRange(1, scheduleTasks.Count - 1);
  990. }
  991. scheduleTask = scheduleTasks.First();
  992. scheduleTask.roomId = string.IsNullOrWhiteSpace(courseTaskInsert.roomId) ? scheduleTask.roomId : courseTaskInsert.roomId;
  993. scheduleTask.school = school;
  994. scheduleTask.teacherId = courseTaskInsert.teacherId;
  995. scheduleTask.startTime = courseTaskInsert.startTime > 0 ? courseTaskInsert.startTime : scheduleTask.startTime;
  996. scheduleTask.notice = string.IsNullOrWhiteSpace(courseTaskInsert.notice) ? scheduleTask.notice : courseTaskInsert.notice;
  997. scheduleTask.assistants = courseTaskInsert.assistants != null ? courseTaskInsert.assistants : courseTaskInsert.assistants;
  998. }
  999. else
  1000. {
  1001. scheduleTask = new ScheduleTask()
  1002. {
  1003. roomId = courseTaskInsert.roomId,
  1004. groupId = courseTaskInsert.groupId,
  1005. type = courseTaskInsert.type,
  1006. teacherId = courseTaskInsert.teacherId,
  1007. times = new List<ScheduleTime>(),
  1008. school = school,
  1009. };
  1010. courseTask.schedules.Add(scheduleTask);
  1011. }
  1012. //修改教师或名单
  1013. if (grant_type.ToString().Equals("change-scheduleTask", StringComparison.OrdinalIgnoreCase))
  1014. {
  1015. if (!string.IsNullOrWhiteSpace(courseTaskInsert.teacherIdChanged))
  1016. {
  1017. scheduleTask.teacherId = courseTaskInsert.teacherIdChanged;
  1018. }
  1019. if (!string.IsNullOrWhiteSpace(courseTaskInsert.typeChanged) && !string.IsNullOrWhiteSpace(courseTaskInsert.groupIdChanged))
  1020. {
  1021. scheduleTask.groupId = courseTaskInsert.groupIdChanged;
  1022. scheduleTask.type = courseTaskInsert.typeChanged;
  1023. }
  1024. }
  1025. courseTasks.Add(courseTask);
  1026. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).UpsertItemAsync(courseTask, new PartitionKey(taskCode));
  1027. }
  1028. else
  1029. {
  1030. invalidCourseTaskInsert.Add(courseTaskInsert);
  1031. }
  1032. }
  1033. return Ok(new { invalidCourseTaskInsert, courseTasks });
  1034. }
  1035. }
  1036. //按照模板导入进行数据转换并且进行检查
  1037. case bool when $"{grant_type}".Equals("import-check") && $"{scope}".Equals("school", StringComparison.OrdinalIgnoreCase):
  1038. {
  1039. //检查完成,生成一个检查通过的token+检查结果(pass,warn,error), 在正式导入的时候,只需要检查token是否存在则进行数据保存。 以确保每次被导入的数据都是检查通过的。
  1040. //并标记相关检查状态对于的具体数值。
  1041. //数据转换是必须的,可选是否开启数据检查,数据检查包括导入数据自检(逻辑,排他,教室-名单-教师-时间段,重复),导入数据与数据库数据库的比对检查。
  1042. //课程 批量升学年 学期.
  1043. if (!request.TryGetProperty("courseCheckImports", out JsonElement _courseCheckImports)) return BadRequest();
  1044. if (!request.TryGetProperty("periodId", out JsonElement _periodId)) return BadRequest();
  1045. request.TryGetProperty("majorId", out JsonElement _majorId);
  1046. School schoolBase = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>(school, new PartitionKey("Base"));
  1047. var period = schoolBase.period.Find(x => x.id.Equals($"{_periodId}"));
  1048. if (period == null)
  1049. {
  1050. return Ok(new { code = 1, msg = "学段不存在!" });
  1051. }
  1052. List<CourseCheckImport> courseCheckImports = _courseCheckImports.ToObject<List<CourseCheckImport>>();
  1053. //数据检查
  1054. //1.检查导入的课程编号是否有效
  1055. StringBuilder sqlNo = new StringBuilder(" select value c from c ");
  1056. var courseNoidImports = courseCheckImports.Where(x => string.IsNullOrWhiteSpace(x.courseNo));
  1057. sqlNo.Append($" where c.no in({string.Join(",", courseCheckImports.Where(x => !string.IsNullOrWhiteSpace(x.courseNo)).Select(z => $"'{z.courseNo}'"))}) and c.period.id='{_periodId}' ");
  1058. if (!string.IsNullOrWhiteSpace($"{_majorId}"))
  1059. {
  1060. var major = period.majors.Find(z => z.id.Equals($"{_majorId}"));
  1061. if (major==null)
  1062. {
  1063. return Ok(new { code = 2, msg = "专业不存在!" });
  1064. }
  1065. sqlNo.Append($" and c.major.id='{_majorId}'");
  1066. }
  1067. List<CourseBase> courseBases = new List<CourseBase>();
  1068. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School)
  1069. .GetItemQueryIterator<CourseBase>(queryText: sqlNo.ToString(), requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"CourseBase-{school}") }))
  1070. {
  1071. courseBases.Add(item);
  1072. }
  1073. HashSet<CourseCheckImport> courseInvalidImports = new HashSet<CourseCheckImport>();
  1074. HashSet<CourseCheckImport> courseVerifiedImports = new HashSet<CourseCheckImport>();
  1075. var noInvalidImports = courseCheckImports.Where(z => !courseBases.Select(x => x.no).Contains(z.courseNo));
  1076. //保留课程名称存在的排课信息
  1077. if (noInvalidImports != null && noInvalidImports.Any())
  1078. {
  1079. foreach (var noInvalidImport in noInvalidImports)
  1080. {
  1081. noInvalidImport.invalidCode =1;
  1082. courseInvalidImports.Add(noInvalidImport);
  1083. }
  1084. courseCheckImports.RemoveAll(z => noInvalidImports.Contains(z));
  1085. }
  1086. //2.检查导入的醍摩豆教师ID是否有效
  1087. StringBuilder sqlTmdid = new StringBuilder(" select c.id,c.name ,c.code ,c.picture from c ");
  1088. //sqlTmdid.Append($" where c.id in({string.Join(",", courseCheckImports.Select(z => $"'{z.tmdid}'"))}) ");
  1089. List<IdNameCode> teachers = new List<IdNameCode>();
  1090. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School)
  1091. .GetItemQueryIterator<IdNameCode>(queryText: sqlTmdid.ToString(), requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Teacher-{school}") }))
  1092. {
  1093. teachers.Add(item);
  1094. }
  1095. var tmdidInvalidImports = courseCheckImports.ExceptBy(teachers.Select(x => x.id), z => z.tmdid);
  1096. //保留课程名称存在的及醍摩豆ID有效的排课信息
  1097. if (tmdidInvalidImports != null && tmdidInvalidImports.Any())
  1098. {
  1099. foreach (var tmdidInvalidImport in tmdidInvalidImports)
  1100. {
  1101. tmdidInvalidImport.invalidCode = 2;
  1102. courseInvalidImports.Add(tmdidInvalidImport);
  1103. }
  1104. courseCheckImports.RemoveAll(z => tmdidInvalidImports.Contains(z));
  1105. }
  1106. //3.检查导入的教学班名称是否有效
  1107. IEnumerable<CourseCheckImport> teachInvalidImports = null;
  1108. List<GroupList> groupLists = new List<GroupList>();
  1109. var teachList = courseCheckImports.Where(x => x.type.Equals("teach"));
  1110. if (teachList.Any() && teachList.Count()>0)
  1111. {
  1112. StringBuilder sqlTeach = new StringBuilder(" select value c from c ");
  1113. sqlTeach.Append($" where c.name in({string.Join(",", teachList.Select(z => $"'{z.list}'"))}) ");
  1114. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School)
  1115. .GetItemQueryIterator<GroupList>(queryText: sqlTeach.ToString(), requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"GroupList-{school}") }))
  1116. {
  1117. groupLists.Add(item);
  1118. }
  1119. teachInvalidImports = teachList.ExceptBy(groupLists.Select(x => x.name), z => z.list);
  1120. //保留课程名称存在的及醍摩豆ID有效的排课信息
  1121. if (teachInvalidImports != null && teachInvalidImports.Any())
  1122. {
  1123. foreach (var teachInvalidImport in teachInvalidImports)
  1124. {
  1125. teachInvalidImport.invalidCode = 3;
  1126. courseInvalidImports.Add(teachInvalidImport);
  1127. }
  1128. courseCheckImports.RemoveAll(z => teachInvalidImports.Contains(z));
  1129. }
  1130. }
  1131. //4.检查导入的教室编号是否有效
  1132. //获取填写了教室编号的数据
  1133. var roomNos = courseCheckImports.Where(z => !string.IsNullOrWhiteSpace(z.roomNo));
  1134. IEnumerable<CourseCheckImport> roomNoInvalidImports = null;
  1135. List<Room> rooms = new List<Room>();
  1136. if (roomNos.Any() && roomNos.Count() > 0)
  1137. {
  1138. StringBuilder sqlRoom = new StringBuilder(" select value c from c ");
  1139. sqlRoom.Append($" where c.no in({string.Join(",", roomNos.Select(z => $"'{z.roomNo}'"))}) ");
  1140. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School)
  1141. .GetItemQueryIterator<Room>(queryText: sqlRoom.ToString(), requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Room-{school}") }))
  1142. {
  1143. rooms.Add(item);
  1144. }
  1145. roomNoInvalidImports = courseCheckImports.ExceptBy(rooms.Select(x => x.no), z => z.roomNo);
  1146. //保留课程名称存在的及醍摩豆ID有效的排课信息
  1147. if (roomNoInvalidImports != null && roomNoInvalidImports.Any())
  1148. {
  1149. foreach (var roomNoInvalidImport in roomNoInvalidImports)
  1150. {
  1151. roomNoInvalidImport.invalidCode = 4;
  1152. courseInvalidImports.Add(roomNoInvalidImport);
  1153. }
  1154. courseCheckImports.RemoveAll(z => roomNoInvalidImports.Contains(z));
  1155. }
  1156. }
  1157. //5.检查开学日期,行政班编号是否有效
  1158. //List<CourseCheckImport> stimeInvalidImports = new List<CourseCheckImport>() ;
  1159. //List<CourseCheckImport> etimeInvalidImports = new List<CourseCheckImport>();
  1160. //List<CourseCheckImport> scheduleInvalidImports = new List<CourseCheckImport>();
  1161. //List<CourseCheckImport> classIdNoInvalidImports = new List<CourseCheckImport>();
  1162. Dictionary<string, List<Class>> duplicateClasses = new Dictionary<string, List<Class>>();
  1163. //1 上课时间段的
  1164. var timeTables = period.timetable.Where(z => z.type.Equals("1")).ToList();
  1165. HashSet<CourseTask> courseTasks = new HashSet<CourseTask>();
  1166. int checkedCount = 0;
  1167. foreach (var item in courseCheckImports)
  1168. {
  1169. DateTimeOffset sdateTime = default;
  1170. DateTimeOffset edateTime = default;
  1171. //5.1.检查开学日期格式是否正确
  1172. if (!DateTimeOffset.TryParseExact(item.stime, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out sdateTime))
  1173. {
  1174. item.invalidCode = 5;
  1175. courseInvalidImports.Add(item);
  1176. continue;
  1177. }
  1178. //获取当前学年,当前学期,当前导入时间的日期,以及下学期开学时间
  1179. (Semester currSemester, int studyYear, DateTimeOffset date, DateTimeOffset nextSemester) info = SchoolService.GetSemester(period, time: item.stime);
  1180. if (info.currSemester != null)
  1181. {
  1182. //5.2检查课程结束日期格式是否正确
  1183. if (!string.IsNullOrWhiteSpace(item.etime))
  1184. {
  1185. if (!DateTimeOffset.TryParseExact(item.etime, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out edateTime))
  1186. {
  1187. item.invalidCode = 6;
  1188. courseInvalidImports.Add(item);
  1189. continue;
  1190. }
  1191. }
  1192. else
  1193. {
  1194. //未设置课程结束时间,开学前一天
  1195. edateTime = info.nextSemester.AddDays(-1);
  1196. }
  1197. }
  1198. else
  1199. {
  1200. //15.根据开学时间无法获取学期信息
  1201. item.invalidCode = 15;
  1202. courseInvalidImports.Add(item);
  1203. continue;
  1204. }
  1205. ScheduleTime scheduleTime = null;
  1206. //5.3检查排课字段格式,数据是否符合要求
  1207. if (!string.IsNullOrWhiteSpace(item.schedule))
  1208. {
  1209. string[] datas = item.schedule.Split('-');
  1210. if (datas.Length >= 3)
  1211. {
  1212. int timeIndex = -1;
  1213. int weekIndex = -1;
  1214. string mode = string.Empty;
  1215. if (int.TryParse(datas[0], out timeIndex) && timeIndex > 0
  1216. && int.TryParse(datas[1], out weekIndex) && weekIndex > 0
  1217. && (datas[2].Equals("A", StringComparison.OrdinalIgnoreCase) || datas[2].Equals("D", StringComparison.OrdinalIgnoreCase) || datas[2].Equals("C", StringComparison.OrdinalIgnoreCase)))
  1218. {
  1219. mode = datas[2];
  1220. HashSet<int> weekIndexs = new HashSet<int>();
  1221. if (mode.Equals("C"))
  1222. {
  1223. if (datas.Length == 4)
  1224. {
  1225. var customWeeks = datas[3].Split(',');
  1226. bool hasInvalidData = false;
  1227. HashSet<int> weeks = new HashSet<int>();
  1228. foreach (var customWeek in customWeeks)
  1229. {
  1230. if (int.TryParse(customWeek, out int customWeekIndex) && customWeekIndex > 0)
  1231. {
  1232. weeks.Add(customWeekIndex);
  1233. }
  1234. else
  1235. {
  1236. hasInvalidData = true;
  1237. break;
  1238. }
  1239. }
  1240. if (hasInvalidData)
  1241. {
  1242. //C 自定义模式下,配置的上课周是大于等于1的整数
  1243. item.invalidCode = 11;
  1244. courseInvalidImports.Add(item);
  1245. continue;
  1246. }
  1247. else
  1248. {
  1249. weekIndexs = weeks;
  1250. }
  1251. }
  1252. else
  1253. {
  1254. //C 自定义模式下,需要配置对应的上课周
  1255. item.invalidCode = 10;
  1256. courseInvalidImports.Add(item);
  1257. continue;
  1258. }
  1259. }
  1260. scheduleTime = new ScheduleTime();
  1261. try
  1262. {
  1263. var timeTable = timeTables[timeIndex-1];
  1264. scheduleTime.id= timeTable.id;
  1265. }
  1266. catch (Exception ex)
  1267. {
  1268. //数组越界,表示导入的不存在,没有对应的上课时间段
  1269. item.invalidCode = 8;
  1270. courseInvalidImports.Add(item);
  1271. continue;
  1272. }
  1273. try
  1274. {
  1275. var week = weekDays[weekIndex - 1];
  1276. scheduleTime.week = week;
  1277. }
  1278. catch (Exception ex)
  1279. {
  1280. //数组越界,表示导入的不存在
  1281. //上课时间不在星期一至星期日
  1282. item.invalidCode = 9;
  1283. courseInvalidImports.Add(item);
  1284. continue;
  1285. }
  1286. scheduleTime.mode= mode;
  1287. scheduleTime.index = weekIndexs;
  1288. }
  1289. else
  1290. {
  1291. //不满足最基本的1-1-A格式,可能是不是数字,或者不是A,D,C模式,
  1292. //排课时间格式不满足[1-n]-[1|2|3|4|5|6|7]-[A|D|C]
  1293. item.invalidCode = 7;
  1294. courseInvalidImports.Add(item);
  1295. continue;
  1296. }
  1297. }
  1298. else
  1299. {
  1300. //不满足最基本的1-1-A格式
  1301. //排课时间格式不满足[1-n]-[1|2|3|4|5|6|7]-[A|D|C]
  1302. item.invalidCode = 7;
  1303. courseInvalidImports.Add(item);
  1304. continue;
  1305. }
  1306. }
  1307. string groupId = string.Empty;
  1308. //5.4 检查导入的行政班编号是否有效
  1309. if (item.type.Equals("class"))
  1310. {
  1311. var yearNo = item.list.Split("-");
  1312. if (yearNo.Length == 2)
  1313. {
  1314. StringBuilder sqlYearNo = new StringBuilder(" select value c from c ");
  1315. sqlYearNo.Append($" where c.year ={yearNo[0]} and c.no ='{yearNo[1]}' and c.periodId='{period.id}' ");
  1316. List<Class> classes = new List<Class>();
  1317. await foreach (var classInfo in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School)
  1318. .GetItemQueryIterator<Class>(queryText: sqlYearNo.ToString(), requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Class-{school}") }))
  1319. {
  1320. classes.Add(classInfo);
  1321. }
  1322. if (classes.Count > 1)
  1323. {
  1324. ///班级入学年-编号重复的班级
  1325. duplicateClasses.Add(item.list, classes);
  1326. //导入的班级入学年-编号在系统中重复,请检查行政班设置。
  1327. item.invalidCode = 13;
  1328. courseInvalidImports.Add(item);
  1329. continue;
  1330. }
  1331. else if (classes.Count <= 0)
  1332. {
  1333. //班级入学年-编号不存在
  1334. item.invalidCode = 12;
  1335. courseInvalidImports.Add(item);
  1336. continue;
  1337. }
  1338. else
  1339. {
  1340. Class @class = classes[0];
  1341. groupId = @class.id;
  1342. }
  1343. }
  1344. else
  1345. {
  1346. courseInvalidImports.Add(item);
  1347. //导入的班级入学年-编号格式错误
  1348. item.invalidCode = 14;
  1349. continue;
  1350. }
  1351. }
  1352. else
  1353. {
  1354. var groupList = groupLists.Find(z => z.name.Equals(item.list));
  1355. groupId=groupList?.id;
  1356. }
  1357. //检查助教是否存在
  1358. string[] assistants = new string[] { };
  1359. if (!string.IsNullOrWhiteSpace(item.assistants))
  1360. {
  1361. assistants = Regex.Split(item.assistants, "\\.|\\.|\\、|\\:|\\:|\\,|\\,|\\;|\\;");
  1362. var invalidAssistants = assistants.Except(teachers.Select(x => x.id));
  1363. if (invalidAssistants != null && invalidAssistants.Any())
  1364. {
  1365. item.invalidCode = 21;
  1366. item.invalidMsg = $"{string.Join(",", invalidAssistants)}";
  1367. courseInvalidImports.Add(item);
  1368. continue;
  1369. }
  1370. }
  1371. Room room = rooms.Find(z => !string.IsNullOrWhiteSpace(item.roomNo) && z.no.Equals(item.roomNo));
  1372. string roomId = room?.id;
  1373. string teacherId = teachers.Find(z => z.id.Equals(item.tmdid))?.id;
  1374. CourseBase courseBase = courseBases.Find(z => z.no.Equals(item.courseNo));
  1375. string taskId = $"{info.studyYear}-{info.currSemester.id}-{courseBase.id}";
  1376. string taskCode = $"CourseTask-{school}";
  1377. CourseTask courseTask = courseTasks.FirstOrDefault(z => z.id.Equals(taskId) && z.code.Equals(taskCode));
  1378. if (courseTask == null)
  1379. {
  1380. Azure.Response courseTaskResponse = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemStreamAsync(taskId, new PartitionKey(taskCode));
  1381. if (courseTaskResponse.Status == 200)
  1382. {
  1383. courseTask = JsonDocument.Parse(courseTaskResponse.Content).RootElement.ToObject<CourseTask>();
  1384. }
  1385. }
  1386. if (courseTask == null)
  1387. {
  1388. courseTask = new CourseTask()
  1389. {
  1390. id = taskId,
  1391. code = taskCode,
  1392. expire = edateTime.ToUnixTimeMilliseconds(),
  1393. pk = "CourseTask",
  1394. ttl = -1,
  1395. courseId = courseBase.id,
  1396. year = info.studyYear,
  1397. semesterId = info.currSemester.id,
  1398. schedules = new List<ScheduleTask>
  1399. {
  1400. new ScheduleTask()
  1401. {
  1402. roomId=roomId,
  1403. groupId=groupId,
  1404. type=item.type,
  1405. teacherId=teacherId,
  1406. times = scheduleTime!=null ? new List<ScheduleTime> { scheduleTime }: new List<ScheduleTime> { },
  1407. school=school,
  1408. assistants=assistants.ToHashSet(),
  1409. }
  1410. }
  1411. };
  1412. courseTasks.Add(courseTask);
  1413. }
  1414. else
  1415. {
  1416. ScheduleTask scheduleTask = null;
  1417. var scheduleTasks = courseTask.schedules.FindAll(z => z.type.Equals(item.type) && z.groupId.Equals(groupId));
  1418. if (scheduleTasks.IsNotEmpty())
  1419. {
  1420. if (scheduleTasks.Count > 2)
  1421. {
  1422. courseTask.schedules.RemoveRange(1, scheduleTasks.Count - 1);
  1423. }
  1424. scheduleTask = scheduleTasks.First();
  1425. scheduleTask.roomId = string.IsNullOrWhiteSpace(roomId) ? scheduleTask.roomId : roomId;
  1426. scheduleTask.school = school;
  1427. scheduleTask.teacherId = teacherId;
  1428. scheduleTask.assistants = assistants != null ? assistants.ToHashSet() : scheduleTask.assistants;
  1429. if (scheduleTime != null)
  1430. {
  1431. var shtime = scheduleTask.times.Find(z => z.id.Equals(scheduleTime.id) && z.week.Equals(scheduleTime.week) && z.mode.Equals(scheduleTime.mode));
  1432. if (shtime == null)
  1433. {
  1434. scheduleTask.times.Add(scheduleTime);
  1435. }
  1436. else
  1437. {
  1438. if (scheduleTime.index.Any())
  1439. {
  1440. foreach (var ind in scheduleTime.index)
  1441. {
  1442. shtime.index.Add(ind);
  1443. }
  1444. }
  1445. }
  1446. }
  1447. }
  1448. else
  1449. {
  1450. scheduleTask = new ScheduleTask()
  1451. {
  1452. roomId = roomId,
  1453. groupId = groupId,
  1454. type = item.type,
  1455. teacherId = teacherId,
  1456. times = scheduleTime != null ? new List<ScheduleTime> { scheduleTime } : new List<ScheduleTime> { },
  1457. school = school,
  1458. assistants= assistants != null ? assistants.ToHashSet() : scheduleTask.assistants
  1459. };
  1460. courseTask.schedules.Add(scheduleTask);
  1461. }
  1462. courseTasks.Add(courseTask);
  1463. }
  1464. item.invalidCode = 0;
  1465. courseVerifiedImports.Add(item);
  1466. checkedCount++;
  1467. }
  1468. //生成检查结果token,有效期5分钟
  1469. if (courseTasks != null && courseTasks.Count > 0)
  1470. {
  1471. string checkToken = $"CourseTask:CheckToken:{scope}:{school}:{Guid.NewGuid()}";
  1472. await _azureRedis.GetRedisClient(8).StringSetAsync(checkToken, courseTasks.ToJsonString(), expiry: new TimeSpan(0, 5, 0));
  1473. return Ok(new { courseCheckedImports = courseTasks, checkedCount, invalidCount = courseInvalidImports.Count, courseVerifiedImports, courseInvalidImports, checkToken });
  1474. }
  1475. else
  1476. {
  1477. return Ok(new { courseCheckedImports = courseTasks, checkedCount, invalidCount = courseInvalidImports.Count, courseVerifiedImports, courseInvalidImports, checkToken = string.Empty });
  1478. }
  1479. }
  1480. case bool when $"{grant_type}".Equals("import-task", StringComparison.OrdinalIgnoreCase) && $"{scope}".Equals("school", StringComparison.OrdinalIgnoreCase):
  1481. {
  1482. request.TryGetProperty("checkToken", out JsonElement _checkToken);
  1483. if (!string.IsNullOrWhiteSpace($"{_checkToken}") && $"{_checkToken}".StartsWith($"CourseTask:CheckToken:{scope}:{school}:"))
  1484. {
  1485. RedisValue value = await _azureRedis.GetRedisClient(8).StringGetAsync($"{_checkToken}");
  1486. List<CourseTask> courseTasks = value.ToString().ToObject<List<CourseTask>>();
  1487. if (courseTasks.IsNotEmpty())
  1488. {
  1489. foreach (var task in courseTasks)
  1490. {
  1491. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).UpsertItemAsync(task, new PartitionKey(task.code));
  1492. }
  1493. return Ok(new { code = 200 });
  1494. }
  1495. }
  1496. return BadRequest();
  1497. }
  1498. case bool when $"{grant_type}".Equals("export-task", StringComparison.OrdinalIgnoreCase) && $"{scope}".Equals("school", StringComparison.OrdinalIgnoreCase):
  1499. {
  1500. JsonElement _year = default, _semesterId = default, _periodId = default;
  1501. if (!request.TryGetProperty("periodId", out _periodId)) return BadRequest();
  1502. if (!request.TryGetProperty("year", out _year))
  1503. {
  1504. return BadRequest();
  1505. }
  1506. if (!request.TryGetProperty("semesterId", out _semesterId))
  1507. {
  1508. return BadRequest();
  1509. }
  1510. School schoolBase = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>(school, new PartitionKey("Base"));
  1511. var period = schoolBase.period.Find(x => x.id.Equals($"{_periodId}"));
  1512. string date = SchoolService.GetOpensByStudyYearAndSemester(period.semesters, int.Parse($"{_year}"), $"{_semesterId}");
  1513. string sql = $"select value c from c where c.year={_year} and c.semesterId='{_semesterId}'";
  1514. string code = $"CourseTask-{school}";
  1515. var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetList<CourseTask>(sql, code);
  1516. List<CourseCheckImport> imports = new List<CourseCheckImport>();
  1517. if (result.list.IsNotEmpty())
  1518. {
  1519. string courseIdSQL = $"select value c from c where c.id in({string.Join(",", result.list.Select(z => $"'{z.courseId}'"))})";
  1520. List<CourseBase> courseBases = new List<CourseBase>();
  1521. var resultCourse = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetList<CourseBase>(courseIdSQL, $"CourseBase-{school}");
  1522. if (resultCourse.list.IsNotEmpty())
  1523. {
  1524. courseBases.AddRange(resultCourse.list);
  1525. }
  1526. var classIds = result.list.SelectMany(z => z.schedules).Where(y => y.type.Equals("class") && !string.IsNullOrWhiteSpace(y.groupId)).Select(x => x.groupId);
  1527. var teachIds = result.list.SelectMany(z => z.schedules).Where(y => y.type.Equals("teach")&& !string.IsNullOrWhiteSpace(y.groupId)).Select(x => x.groupId);
  1528. var teacherIds = result.list.SelectMany(z => z.schedules).Where(y => !string.IsNullOrWhiteSpace(y.teacherId)).Select(x => x.teacherId);
  1529. var assistantIds = result.list.SelectMany(z => z.schedules).Where(y => y.assistants!=null && y.assistants.Any()).SelectMany(x => x.assistants);
  1530. List<Class> classes = new List<Class>();
  1531. if (classIds!=null && classIds.Count()>0)
  1532. {
  1533. string classIdSQL = $"select value c from c where c.id in({string.Join(",", classIds.Select(x => $"'{x}'"))})";
  1534. var resultClass = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetList<Class>(classIdSQL, $"Class-{school}");
  1535. if (resultClass.list.IsNotEmpty())
  1536. {
  1537. classes.AddRange(resultClass.list);
  1538. }
  1539. }
  1540. List<GroupList> groupLists = new List<GroupList>();
  1541. if (teachIds!=null && teachIds.Count()>0)
  1542. {
  1543. string teachIdSQL = $"select value c from c where c.id in({string.Join(",", teachIds.Select(x => $"'{x}'"))})";
  1544. var resultGroupList = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetList<GroupList>(teachIdSQL, $"GroupList-{school}");
  1545. if (resultGroupList.list.IsNotEmpty())
  1546. {
  1547. groupLists.AddRange(resultGroupList.list);
  1548. }
  1549. }
  1550. List<string> tmdids = new List<string>();
  1551. if (teacherIds!=null && teacherIds.Count()>0)
  1552. {
  1553. tmdids.AddRange(teacherIds);
  1554. }
  1555. if (assistantIds!=null && assistantIds.Count()>0)
  1556. {
  1557. tmdids.AddRange(assistantIds);
  1558. }
  1559. List<Teacher> teachers = new List<Teacher>();
  1560. if (tmdids.Count>0)
  1561. {
  1562. string tmdidSQL = $"select value c from c where c.id in({string.Join(",", tmdids.Select(x => $"'{x}'"))})";
  1563. var resultTmdid = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetList<Teacher>(tmdidSQL, "Base");
  1564. if (resultTmdid.list.IsNotEmpty())
  1565. {
  1566. teachers.AddRange(resultTmdid.list);
  1567. }
  1568. }
  1569. foreach (var item in result.list)
  1570. {
  1571. var courseBase = courseBases.Find(z => z.id.Equals(item.courseId));
  1572. item.schedules.ForEach(z =>
  1573. {
  1574. CourseCheckImport courseCheckImport = new CourseCheckImport { name=courseBase?.name, stime=date, grade=courseBase.grade, courseNo=courseBase.no };
  1575. if (z.type.Equals("class") &&!string.IsNullOrWhiteSpace(z.groupId))
  1576. {
  1577. var clazz = classes.Find(x => x.id.Equals(z.groupId));
  1578. if (clazz!=null)
  1579. {
  1580. courseCheckImport.type=z.type;
  1581. courseCheckImport.list=$"{clazz?.year}-{clazz?.no}";
  1582. courseCheckImport.listName=clazz?.name;
  1583. }
  1584. }
  1585. if (z.type.Equals("teach")&&!string.IsNullOrWhiteSpace(z.groupId))
  1586. {
  1587. var groupList = groupLists.Find(x => x.id.Equals(z.groupId));
  1588. if (groupList!=null)
  1589. {
  1590. courseCheckImport.type=z.type;
  1591. courseCheckImport.list=$"{groupList?.name}";
  1592. courseCheckImport.listName=groupList?.name;
  1593. }
  1594. }
  1595. if (!string.IsNullOrWhiteSpace(z.teacherId))
  1596. {
  1597. var teacher = teachers.Find(x => x.id.Equals(z.teacherId));
  1598. if (teacher!=null)
  1599. {
  1600. courseCheckImport.tmdid=teacher?.id;
  1601. courseCheckImport.tmdName=teacher?.name;
  1602. }
  1603. }
  1604. if (z.assistants!=null && z.assistants.Count>0)
  1605. {
  1606. var teacher_assistants = teachers.FindAll(x => z.assistants.Contains(x.id));
  1607. if (teacher_assistants!=null)
  1608. {
  1609. courseCheckImport.assistants=string.Join(",", z.assistants);
  1610. courseCheckImport.assistantNames=string.Join(",", teacher_assistants.Select(x => x.name));
  1611. }
  1612. }
  1613. imports.Add(courseCheckImport);
  1614. });
  1615. }
  1616. }
  1617. return Ok(new { export = imports, code = 200 });
  1618. }
  1619. }
  1620. }
  1621. catch (Exception ex)
  1622. {
  1623. await _dingDing.SendBotMsg($"{_option.Location},课程处理异常,{ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
  1624. return Ok(new { code = 500, msg = ex.Message });
  1625. }
  1626. return Ok();
  1627. }
  1628. /// <summary>
  1629. /// 教师任教的课程
  1630. /// </summary>
  1631. /// <param name="request"></param>
  1632. /// <returns></returns>
  1633. [ProducesDefaultResponseType]
  1634. [AuthToken(Roles = "teacher,admin")]
  1635. [HttpPost("teacher")]
  1636. public async Task<IActionResult> Teacher(JsonElement request)
  1637. {
  1638. try
  1639. {
  1640. (string tmdid, _, _, string school) = HttpContext.GetAuthTokenInfo();
  1641. if (!request.TryGetProperty("grant_type", out JsonElement grant_type)) return BadRequest();
  1642. if (!request.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
  1643. var client = _azureCosmos.GetCosmosClient();
  1644. switch (true)
  1645. {
  1646. //任教学校课程和个人课程
  1647. case bool when $"{grant_type}".Equals("teach", StringComparison.OrdinalIgnoreCase):
  1648. //个人,
  1649. //学校,
  1650. //助教,学校。
  1651. //助教,个人。
  1652. break;
  1653. }
  1654. }
  1655. catch (Exception ex)
  1656. {
  1657. }
  1658. return Ok();
  1659. }
  1660. }
  1661. }