ScoreCalcController.cs 104 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012
  1. using Azure;
  2. using Azure.Core;
  3. using Azure.Cosmos;
  4. using Azure.Messaging.ServiceBus;
  5. using Azure.Storage.Blobs.Models;
  6. using DinkToPdf;
  7. using DinkToPdf.Contracts;
  8. using DocumentFormat.OpenXml.Bibliography;
  9. using DocumentFormat.OpenXml.Office2010.Excel;
  10. using DocumentFormat.OpenXml.Office2016.Excel;
  11. using DocumentFormat.OpenXml.Presentation;
  12. using DocumentFormat.OpenXml.Spreadsheet;
  13. using DocumentFormat.OpenXml.VariantTypes;
  14. using DocumentFormat.OpenXml.Wordprocessing;
  15. using FastJSON;
  16. using HTEXLib.COMM.Helpers;
  17. using HTEXLib.Helpers.ShapeHelpers;
  18. using MathNet.Numerics.Distributions;
  19. using Microsoft.AspNetCore.Authorization;
  20. using Microsoft.AspNetCore.Hosting;
  21. using Microsoft.AspNetCore.Http;
  22. using Microsoft.AspNetCore.Mvc;
  23. using Microsoft.Extensions.Configuration;
  24. using Microsoft.Extensions.Options;
  25. using Microsoft.International.Converters.PinYinConverter;
  26. using Microsoft.International.Converters.TraditionalChineseToSimplifiedConverter;
  27. using Microsoft.OData.Edm;
  28. using Newtonsoft.Json;
  29. using NUnit.Framework;
  30. using NUnit.Framework.Internal;
  31. using OpenXmlPowerTools;
  32. using StackExchange.Redis;
  33. using System;
  34. using System.Collections;
  35. using System.Collections.Concurrent;
  36. using System.Collections.Generic;
  37. using System.IO;
  38. using System.Linq;
  39. using System.Net;
  40. using System.Net.Http;
  41. using System.Net.Http.Json;
  42. using System.Runtime.Intrinsics.X86;
  43. using System.Security.Policy;
  44. using System.Text;
  45. using System.Text.Json;
  46. using System.Text.RegularExpressions;
  47. using System.Threading.Tasks;
  48. using System.Xml.Linq;
  49. using TEAMModelOS.Controllers.Analysis;
  50. using TEAMModelOS.Controllers.Core;
  51. using TEAMModelOS.Filter;
  52. using TEAMModelOS.Models;
  53. using TEAMModelOS.Models.Dto;
  54. using TEAMModelOS.SDK;
  55. using TEAMModelOS.SDK.DI;
  56. using TEAMModelOS.SDK.Extension;
  57. using TEAMModelOS.SDK.Helper.Common.DateTimeHelper;
  58. using TEAMModelOS.SDK.Models;
  59. using TEAMModelOS.SDK.Models.Cosmos.Common;
  60. using TEAMModelOS.SDK.Models.Cosmos.OpenEntity;
  61. using TEAMModelOS.SDK.Models.Cosmos.School;
  62. using TEAMModelOS.SDK.Models.Service;
  63. using TEAMModelOS.SDK.Models.Service.BI;
  64. using TEAMModelOS.SDK.Services;
  65. using static Azure.Core.HttpHeader;
  66. using static TEAMModelOS.Controllers.Learn.HomeworkController;
  67. using static TEAMModelOS.SDK.Models.Teacher;
  68. using static TEAMModelOS.SDK.SchoolService;
  69. namespace TEAMModelOS.Controllers
  70. {
  71. [Route("score")]
  72. [ApiController]
  73. public class ScoreCalcController : ControllerBase
  74. {
  75. private readonly IHttpClientFactory _httpClient;
  76. public IWebHostEnvironment _environment { get; set; }
  77. private readonly AzureStorageFactory _azureStorage;
  78. private readonly AzureRedisFactory _azureRedis;
  79. private readonly AzureCosmosFactory _azureCosmos;
  80. private readonly DingDing _dingDing;
  81. private readonly AzureServiceBusFactory _serviceBus;
  82. private readonly CoreAPIHttpService _coreAPIHttpService;
  83. private readonly Option _option;
  84. private readonly IPSearcher _searcher;
  85. public IConfiguration _configuration { get; set; }
  86. private readonly IConverter _converter;
  87. public ScoreCalcController(IConverter converter, IPSearcher searcher, IOptionsSnapshot<Option> option, CoreAPIHttpService coreAPIHttpService, IHttpClientFactory httpClient, IWebHostEnvironment environment, AzureCosmosFactory azureCosmos, AzureRedisFactory azureRedis, AzureStorageFactory azureStorage, IConfiguration configuration, AzureServiceBusFactory serviceBus, DingDing dingDing)
  88. {
  89. _converter = converter;
  90. _azureCosmos = azureCosmos;
  91. _azureRedis = azureRedis;
  92. _azureStorage = azureStorage;
  93. _dingDing = dingDing;
  94. _serviceBus = serviceBus; _configuration = configuration;
  95. _environment = environment;
  96. _httpClient = httpClient;
  97. _option = option.Value;
  98. _coreAPIHttpService = coreAPIHttpService;
  99. _searcher = searcher;
  100. }
  101. //新建成績結算
  102. [ProducesDefaultResponseType]
  103. [Authorize(Roles = "IES")]
  104. [HttpPost("upsert-scorecalc")]
  105. //[Authorize(Roles = "IES")]
  106. //[AuthToken(Roles = "admin,teacher,student")]
  107. public async Task<IActionResult> UpsertScoreCalc(JsonElement json)
  108. {
  109. try
  110. {
  111. //var client = _azureCosmos.GetCosmosClient();
  112. ////總覽
  113. //ScoreCalcBase scoreCalcBase = new ScoreCalcBase();
  114. //string tmid = "1595321354";
  115. //scoreCalcBase.id = "8f25d7b4-79bd-4448-baaf-01b0d3d3efd9";
  116. //scoreCalcBase.name = "測試成績001";
  117. //scoreCalcBase.code = $"ScoreCalc-{tmid}";
  118. //scoreCalcBase.courseId = "a6d778e8-e4f0-46a3-850f-c15daedc5d94";
  119. //scoreCalcBase.classId = "b069d9d4-ef7e-4f3e-ac62-532b11f95b80";
  120. //ScoreCalcMember member1 = new ScoreCalcMember() { id = "20230001" , name = "學生1" , no = "1"};
  121. //ScoreCalcMember member2 = new ScoreCalcMember() { id = "20230002", name = "學生2", no = "2" };
  122. //scoreCalcBase.members.Add(member1);
  123. //scoreCalcBase.members.Add(member2);
  124. //scoreCalcBase.scores.Add(65.5);
  125. //scoreCalcBase.scores.Add(73.8);
  126. //scoreCalcBase.scoresOrg.Add(66.7);
  127. //scoreCalcBase.scoresOrg.Add(71.4);
  128. //scoreCalcBase.rateType = "percentage";
  129. //await client.GetContainer(Constant.TEAMModelOS, "Teacher").UpsertItemAsync(scoreCalcBase, new PartitionKey($"ScoreCalc-{tmid}"));
  130. ////評量
  131. //ScoreCalcActivity scoreCalcActivity = new ScoreCalcActivity();
  132. //scoreCalcActivity.id = "bd492c0c-c6d5-472d-9b3a-93196d3a7010";
  133. //scoreCalcActivity.code = $"ScoreCalcAct-{tmid}";
  134. //scoreCalcActivity.scorecalcId = "8f25d7b4-79bd-4448-baaf-01b0d3d3efd9";
  135. //scoreCalcActivity.type = "exam";
  136. //ScoreCalcActivityItems exam1 = new ScoreCalcActivityItems(); //被選取的第一個評量
  137. //exam1.id = "af6cc80f-a4be-4a5f-94ff-12c1fd366a8f";
  138. //exam1.name = "第一次小考";
  139. //exam1.code = "Exam-1595321354";
  140. //exam1.scope = "school";
  141. //exam1.owner = "teacher";
  142. //exam1.progress = "finish";
  143. //exam1.sStatus = 1;
  144. //exam1.source = "1";
  145. //exam1.createTime = 1623919622766;
  146. //scoreCalcActivity.items.Add(exam1);
  147. //ScoreCalcActivityItems exam2 = new ScoreCalcActivityItems(); //被選取的第二個評量
  148. //exam2.id = "b3f95a17-b839-4b9a-84de-76c83d0e2845";
  149. //exam2.name = "第二次小考";
  150. //exam2.code = "Exam-1595321354";
  151. //exam2.scope = "private";
  152. //exam2.owner = "teacher";
  153. //exam2.progress = "finish";
  154. //exam2.sStatus = 1;
  155. //exam2.source = "1";
  156. //exam2.createTime = 1623204312794;
  157. //scoreCalcActivity.items.Add(exam2);
  158. //scoreCalcActivity.itemRates.Add(2); //第一個評量權重
  159. //scoreCalcActivity.itemRates.Add(1); //第二個評量權重
  160. //scoreCalcActivity.itemRateType = "count";
  161. //scoreCalcActivity.itemScores.Add(76.2);
  162. //scoreCalcActivity.itemScores.Add(81.1);
  163. //scoreCalcActivity.itemScoresOrg.Add(72.6);
  164. //scoreCalcActivity.itemScoresOrg.Add(80.7);
  165. ////scoreCalcActivity.score = 78.2;
  166. ////scoreCalcActivity.scoreOrg = 77.5;
  167. //scoreCalcActivity.rate = 40; //評量的總加權 = 40%
  168. //List<double> stuScores = new List<double>() { 70.1, 73.5 }; //第一個學生的所有評量總成績,第二個同學...
  169. //scoreCalcActivity.stuScores = stuScores;
  170. //List<double> examScore1 = new List<double>() { 73.2, 69.7 }; //第一個評量,第一位同學73.2 第二位同學69.7
  171. //scoreCalcActivity.stuActScores.Add(examScore1);
  172. //List<double> examScore2 = new List<double>() { 81.6, 58.1 }; //第二個評量
  173. //scoreCalcActivity.stuActScores.Add(examScore2);
  174. //List<double> examScore1Org = new List<double>() { 73.2, 69.7 };
  175. //scoreCalcActivity.stuActScoresOrg.Add(examScore1Org);
  176. //List<double> examScore2Org = new List<double>() { 81.6, 58.1 };
  177. //scoreCalcActivity.stuActScoresOrg.Add(examScore2Org);
  178. //await client.GetContainer(Constant.TEAMModelOS, "Teacher").UpsertItemAsync(scoreCalcActivity, new PartitionKey($"ScoreCalcAct-{tmid}"));
  179. ////課堂紀錄
  180. //ScoreCalcLsRecord scoreCalcLsRecord = new ScoreCalcLsRecord();
  181. return Ok(new { status = 200 });
  182. }
  183. catch (Exception ex)
  184. {
  185. return BadRequest();
  186. }
  187. }
  188. /// <summary>
  189. /// (一)查詢成績統計列表
  190. /// </summary>
  191. /// <param name="request"></param>
  192. /// <returns></returns>
  193. [ProducesDefaultResponseType]
  194. [Authorize(Roles = "IES")]
  195. [HttpPost("get-scorecalc-list")]
  196. public async Task<IActionResult> GetSscoreCalcList(JsonElement request)
  197. {
  198. try
  199. {
  200. if (!request.TryGetProperty("courseId", out JsonElement courseId)) return BadRequest();
  201. bool ishaveClassId = request.TryGetProperty("classId", out JsonElement classId);
  202. bool ishaveGrouplistId = request.TryGetProperty("grouplistId", out JsonElement grouplistId);
  203. string sql = "";
  204. // classId 跟 grouplistId 兩個必須有一個必填
  205. if (!ishaveClassId)
  206. {
  207. if (!ishaveGrouplistId)
  208. {
  209. return BadRequest();
  210. }
  211. else
  212. {
  213. sql = $"SELECT c.id, c.name, c.sort FROM c where c.courseId = '{courseId}' and c.grouplistId = '{grouplistId}' order by c.sort Desc ";
  214. }
  215. }
  216. else
  217. {
  218. sql = $"SELECT c.id, c.name, c.sort FROM c where c.courseId = '{courseId}' and c.classId = '{classId}' order by c.sort Desc ";
  219. }
  220. var client = _azureCosmos.GetCosmosClient();
  221. #region ====資料取得===
  222. List<Calc> calcList = new List<Calc>();
  223. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetItemQueryIterator<Calc>(queryText: sql))
  224. {
  225. calcList.Add(item);
  226. }
  227. #endregion
  228. return Ok(calcList);
  229. }
  230. catch (Exception e)
  231. {
  232. //await _dingDing.SendBotMsg($"OS,{_option.Location},open-api/upsert()\n{e.Message}\n{e.StackTrace}\n{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
  233. return BadRequest();
  234. }
  235. }
  236. /// <summary>
  237. /// (二)查詢成績統計首頁表資料
  238. /// </summary>
  239. /// <param name="request"></param>
  240. /// <returns></returns>
  241. [ProducesDefaultResponseType]
  242. [Authorize(Roles = "IES")]
  243. [HttpPost("get-scorecalc-All")]
  244. public async Task<IActionResult> GetSscoreCalcAll(JsonElement request)
  245. {
  246. try
  247. {
  248. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  249. //var client = _azureCosmos.GetCosmosClient();
  250. var client = _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher);
  251. #region ====取得學生資料===
  252. string sql = $"select b.id, b.name, b.no from c join b in c.members where c.id = '{id}'";
  253. List<ScoreCalcMember> members = new List<ScoreCalcMember>();
  254. List<Object> scoreCalcAct = new List<Object>();
  255. List<ScoreCalcFunc> scoreCalcFunc = new List<ScoreCalcFunc>();
  256. await foreach (var item in client.GetItemQueryIterator<ScoreCalcMember>(queryText: sql))
  257. {
  258. members.Add(item);
  259. }
  260. #endregion
  261. #region ====取得非課堂紀錄的項目資料===
  262. string sql_Items = $"SELECT c.id, c.name, c.type, c.attendRate, c.pointRate, c.itactRate, c.rate, c.items, c.itemRates, c.itemRateType, c.score, c.scoreOrg, c.stuActScores, c.stuActScoresOrg, c.editScores FROM c where c.scorecalcId = '{id}' and c.type <> 'lessonrecord' ";
  263. List<ScoreCalcActivity> scoreCalcActivity = new List<ScoreCalcActivity>();
  264. await foreach (var item in client.GetItemQueryIterator<ScoreCalcActivity>(queryText: sql_Items))
  265. {
  266. scoreCalcActivity.Add(item);
  267. }
  268. #endregion
  269. #region ====取得課堂紀錄的項目資料===
  270. string sql_LessonRecordItems = $"SELECT c.id, c.code, c.name, c.type, c.attendRate, c.pointRate, c.itactRate, c.rate, c.items, c.itemRates, c.stuAttendFunctionId, c.stuPointFunctionId, c. stuItactFunctionId, c.stuActAttendOrgVals, c.stuActAttendScores, c.stuActPointOrgVals, c.stuActPointScores, c.stuActItactOrgVals, c.stuActItactScores, c.score, c.scoreOrg, c.stuActScores, c.stuActScoresOrg, c.editScores FROM c where c.scorecalcId = '{id}' and c.type = 'lessonrecord' ";
  271. List<ScoreCalcLsRecord> scoreCalcLsRecord = new List<ScoreCalcLsRecord>();
  272. await foreach (var item in client.GetItemQueryIterator<ScoreCalcLsRecord>(queryText: sql_LessonRecordItems))
  273. {
  274. scoreCalcLsRecord.Add(item);
  275. }
  276. #endregion
  277. #region ====取得公式的資料===
  278. string sql_FuncItems = $"SELECT c.id, c.code, c.name, c.scorecalcActId, c.type, c.method, c.template, c.keyvals, c.content from c where c.code = '{scoreCalcLsRecord[0].code.Replace("ScoreCalcAct", "ScoreCalcActFormula")}'";
  279. await foreach (var item in client.GetItemQueryIterator<ScoreCalcFunc>(queryText: sql_FuncItems))
  280. {
  281. scoreCalcFunc.Add(item);
  282. }
  283. #endregion
  284. #region====整理課堂紀錄回傳格式===
  285. ScoreCalcLsRecordActDto scoreCalcLsRecordActDto = new ScoreCalcLsRecordActDto();
  286. scoreCalcLsRecordActDto.id = scoreCalcLsRecord[0].id;
  287. scoreCalcLsRecordActDto.name = scoreCalcLsRecord[0].name;
  288. scoreCalcLsRecordActDto.type = scoreCalcLsRecord[0].type;
  289. scoreCalcLsRecordActDto.attendRate = scoreCalcLsRecord[0].attendRate;
  290. scoreCalcLsRecordActDto.pointRate = scoreCalcLsRecord[0].pointRate;
  291. scoreCalcLsRecordActDto.itactRate = scoreCalcLsRecord[0].itactRate;
  292. scoreCalcLsRecordActDto.rate = scoreCalcLsRecord[0].rate;
  293. scoreCalcLsRecordActDto.stuAttendFunctionId = scoreCalcLsRecord[0].stuAttendFunctionId;
  294. scoreCalcLsRecordActDto.stuPointFunctionId = scoreCalcLsRecord[0].stuPointFunctionId;
  295. scoreCalcLsRecordActDto.stuItactFunctionId = scoreCalcLsRecord[0].stuItactFunctionId;
  296. #region====整理出席狀態資料===
  297. // 先塞入學生數量的出席狀態物件
  298. List<AttendStatesCalc> listAttendStatesCalc = new List<AttendStatesCalc>();
  299. for (int i = 0; i < members.Count; i++)
  300. {
  301. AttendStatesCalc attendStatesCalc = new AttendStatesCalc();
  302. attendStatesCalc.Absent = 0;
  303. attendStatesCalc.Absent_Sick = 0;
  304. attendStatesCalc.Absent_Personal = 0;
  305. attendStatesCalc.Absent_Official = 0;
  306. listAttendStatesCalc.Add(attendStatesCalc);
  307. }
  308. for (int i = 0; i < scoreCalcLsRecord[0].stuActAttendOrgVals.Count; i++)
  309. {
  310. for (int j = 0; j < scoreCalcLsRecord[0].stuActAttendOrgVals[i].Count; j++)
  311. {
  312. switch (scoreCalcLsRecord[0].stuActAttendOrgVals[i][j])
  313. {
  314. //Absent,2(缺席)
  315. //DayOff,3(請假)
  316. //Absent_Sick,4(病假)
  317. //Absent_Personal,5(事假)
  318. //Absent_Official,6(公假)
  319. case 2:
  320. listAttendStatesCalc[j].Absent = listAttendStatesCalc[j].Absent + 1;
  321. break;
  322. case 4:
  323. listAttendStatesCalc[j].Absent_Sick = listAttendStatesCalc[j].Absent_Sick + 1;
  324. break;
  325. case 5:
  326. listAttendStatesCalc[j].Absent_Personal = listAttendStatesCalc[j].Absent_Personal + 1;
  327. break;
  328. case 6:
  329. listAttendStatesCalc[j].Absent_Official = listAttendStatesCalc[j].Absent_Official + 1;
  330. break;
  331. }
  332. }
  333. }
  334. #endregion
  335. scoreCalcLsRecordActDto.attendStates = listAttendStatesCalc;
  336. for (int i = 0; i < scoreCalcLsRecord[0].items.Count; i++)
  337. {
  338. SubActLsRecord subActLsRecord = new SubActLsRecord();
  339. subActLsRecord.id = scoreCalcLsRecord[0].items[i].id;
  340. subActLsRecord.name = scoreCalcLsRecord[0].items[i].name;
  341. // 子項目比重由外層取得
  342. subActLsRecord.rate = scoreCalcLsRecord[0].itemRates[i];
  343. subActLsRecord.use = scoreCalcLsRecord[0].items[i].use;
  344. // 子項目 出席 / 記分板 / 互動 成績由外層取得
  345. subActLsRecord.stuActAttendScores = scoreCalcLsRecord[0].stuActAttendScores[i];
  346. subActLsRecord.stuActPointScores = scoreCalcLsRecord[0].stuActPointScores[i];
  347. subActLsRecord.stuActItactScores = scoreCalcLsRecord[0].stuActItactScores[i];
  348. scoreCalcLsRecordActDto.items.Add(subActLsRecord);
  349. }
  350. scoreCalcLsRecordActDto.editScores = scoreCalcLsRecord[0].editScores;
  351. scoreCalcAct.Add(scoreCalcLsRecordActDto);
  352. #endregion
  353. #region====整理非課堂紀錄回傳格式===
  354. for (int i = 0; i < scoreCalcActivity.Count; i++)
  355. {
  356. ScoreCalcActivityActDto scoreCalcActivityActDto = new ScoreCalcActivityActDto();
  357. scoreCalcActivityActDto.id = scoreCalcActivity[i].id;
  358. scoreCalcActivityActDto.name = scoreCalcActivity[i].name;
  359. scoreCalcActivityActDto.type = scoreCalcActivity[i].type;
  360. scoreCalcActivityActDto.rate = scoreCalcActivity[i].rate;
  361. for (int j = 0; j < scoreCalcActivity[i].items.Count; j++)
  362. {
  363. SubActActivity subActActivity = new SubActActivity();
  364. subActActivity.id = scoreCalcActivity[i].items[j].id;
  365. subActActivity.name = scoreCalcActivity[i].items[j].name;
  366. // 子項目比重由外層取得
  367. subActActivity.rate = scoreCalcActivity[i].itemRates[j];
  368. subActActivity.use = scoreCalcActivity[i].items[j].use;
  369. subActActivity.scores = scoreCalcActivity[i].stuActScores[j];
  370. scoreCalcActivityActDto.items.Add(subActActivity);
  371. }
  372. scoreCalcActivityActDto.editScores = scoreCalcActivity[i].editScores;
  373. scoreCalcAct.Add(scoreCalcActivityActDto);
  374. }
  375. #endregion
  376. var result = new
  377. {
  378. members = members,
  379. scoreCalcAct = scoreCalcAct,
  380. scoreCalcFunc = scoreCalcFunc
  381. };
  382. return Ok(result);
  383. }
  384. catch (Exception e)
  385. {
  386. //await _dingDing.SendBotMsg($"OS,{_option.Location},open-api/upsert()\n{e.Message}\n{e.StackTrace}\n{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
  387. return BadRequest();
  388. }
  389. }
  390. /// <summary>
  391. /// (三)新增成績統計列(包含預設公式)
  392. /// </summary>
  393. /// <param name="request"></param>
  394. /// <returns></returns>
  395. [ProducesDefaultResponseType]
  396. [Authorize(Roles = "IES")]
  397. [HttpPost("add-scorecalc")]
  398. public async Task<IActionResult> AddSscoreCalc(JsonElement request)
  399. {
  400. try
  401. {
  402. if (!request.TryGetProperty("courseId", out JsonElement courseId)) return BadRequest();
  403. if (!request.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
  404. bool ishaveClassId = request.TryGetProperty("classId", out JsonElement classId);
  405. bool ishaveGrouplistId = request.TryGetProperty("grouplistId", out JsonElement grouplistId);
  406. bool ishaveTeammodelId = request.TryGetProperty("teammodelId", out JsonElement teammodelId);
  407. bool ishaveSchoolId = request.TryGetProperty("schoolId", out JsonElement schoolId);
  408. // classId 跟 grouplistId 兩個必須有一個必填
  409. if (!ishaveClassId)
  410. {
  411. if (!ishaveGrouplistId)
  412. {
  413. return BadRequest();
  414. }
  415. else
  416. {
  417. if (!ishaveTeammodelId) return BadRequest();
  418. }
  419. }
  420. else
  421. {
  422. if (!ishaveSchoolId) return BadRequest();
  423. }
  424. // 設定活動預設值
  425. ScoreCalcLsRecord scoreCalcLsRecord = new ScoreCalcLsRecord();
  426. ScoreCalcActivity scoreCalcActivity_eaxm = new ScoreCalcActivity();
  427. ScoreCalcActivity scoreCalcActivity_homework = new ScoreCalcActivity();
  428. var clientTeacher = _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher);
  429. ////班級
  430. List<ScoreCalcMember> members = new List<ScoreCalcMember>();
  431. #region ==== 1~4. 取出系統資料====
  432. var isOKRequest = await getSystemScoresDate(courseId, scope, classId, grouplistId, teammodelId, schoolId, ishaveClassId, ishaveGrouplistId, members, scoreCalcLsRecord, scoreCalcActivity_eaxm, scoreCalcActivity_homework);
  433. if (!isOKRequest) { return BadRequest(); }
  434. //// 根據學生數量設定加減分預設值陣列
  435. List<double> editScores = new List<double>();
  436. for (int j = 0; j < members.Count; j++)
  437. {
  438. editScores.Add(0);
  439. }
  440. #endregion
  441. #region ==== 5. 寫入成績統計資料====
  442. #region ==== 5.1 寫入成績統計主表 ScoreCalc====
  443. ScoreCalcBase scoreCalcBase = new ScoreCalcBase();
  444. scoreCalcBase.name = "成績統計";
  445. scoreCalcBase.courseId = courseId.ToString();
  446. scoreCalcBase.classId = classId.ToString();
  447. scoreCalcBase.grouplistId = grouplistId.ToString();
  448. scoreCalcBase.members = members;
  449. scoreCalcBase.editScores = editScores;
  450. scoreCalcBase.rateType = "percentage";
  451. scoreCalcBase.id = Guid.NewGuid().ToString();
  452. scoreCalcBase.code = scoreCalcBase.pk + "-" + teammodelId;
  453. //取得目前成績統計總數
  454. int count = 0;
  455. string sql = "";
  456. if (!ishaveClassId)
  457. {
  458. sql = $"SELECT c.id FROM c where c.courseId = '{courseId}' and c.grouplistId = '{grouplistId}' ";
  459. }
  460. else
  461. {
  462. sql = $"SELECT c.id FROM c where c.courseId = '{courseId}' and c.classId = '{classId}' ";
  463. }
  464. await foreach (var item in clientTeacher.GetItemQueryIterator<ItemId>(queryText: sql))
  465. {
  466. count++;
  467. }
  468. scoreCalcBase.sort = count + 1;
  469. scoreCalcBase = await clientTeacher.CreateItemAsync(scoreCalcBase, new PartitionKey($"{scoreCalcBase.code}"));
  470. #endregion
  471. #region ==== 5.2 用ScoreCalc的id 寫入成績統計項目表ScoreCalcAct====
  472. #region ==== 5.2.1 寫入課堂紀錄====
  473. scoreCalcLsRecord.id = Guid.NewGuid().ToString();
  474. scoreCalcLsRecord.scorecalcId = scoreCalcBase.id;
  475. scoreCalcLsRecord.name = "課堂紀錄";
  476. scoreCalcLsRecord.type = "lessonrecord";
  477. scoreCalcLsRecord.rate = 40;
  478. scoreCalcLsRecord.attendRate = 40;
  479. scoreCalcLsRecord.pointRate = 30;
  480. scoreCalcLsRecord.itactRate = 30;
  481. scoreCalcLsRecord.stuAttendFunctionId = Guid.NewGuid().ToString();
  482. scoreCalcLsRecord.stuPointFunctionId = Guid.NewGuid().ToString();
  483. scoreCalcLsRecord.stuItactFunctionId = Guid.NewGuid().ToString();
  484. for (int j = 0; j < scoreCalcLsRecord.items.Count; j++)
  485. {
  486. scoreCalcLsRecord.itemRates.Add(1);
  487. scoreCalcLsRecord.items[j].sort = j + 1;
  488. }
  489. scoreCalcLsRecord.editScores = editScores;
  490. scoreCalcLsRecord.code = scoreCalcLsRecord.pk + "-" + teammodelId;
  491. scoreCalcLsRecord.sort = 1;
  492. scoreCalcLsRecord = await clientTeacher.CreateItemAsync(scoreCalcLsRecord, new PartitionKey($"{scoreCalcLsRecord.code}"));
  493. //scoreCalcAct.Add(scoreCalcLsRecord);
  494. #endregion
  495. #region ==== 5.2.2 寫入評量活動====
  496. scoreCalcActivity_eaxm.id = Guid.NewGuid().ToString();
  497. scoreCalcActivity_eaxm.scorecalcId = scoreCalcBase.id;
  498. scoreCalcActivity_eaxm.name = "評量活動";
  499. scoreCalcActivity_eaxm.type = "exam";
  500. scoreCalcActivity_eaxm.rate = 30;
  501. scoreCalcActivity_eaxm.sort = 2;
  502. for (int j = 0; j < scoreCalcActivity_eaxm.items.Count; j++)
  503. {
  504. scoreCalcActivity_eaxm.itemRates.Add(1);
  505. scoreCalcActivity_eaxm.items[j].sort = j + 1;
  506. }
  507. scoreCalcActivity_eaxm.editScores = editScores;
  508. scoreCalcActivity_eaxm.code = scoreCalcActivity_eaxm.pk + "-" + teammodelId;
  509. scoreCalcActivity_eaxm = await clientTeacher.CreateItemAsync(scoreCalcActivity_eaxm, new PartitionKey($"{scoreCalcActivity_eaxm.code}"));
  510. //scoreCalcAct.Add(scoreCalcActivity_eaxm);
  511. #endregion
  512. #region ==== 5.2.3 寫入作業活動====
  513. scoreCalcActivity_homework.id = Guid.NewGuid().ToString();
  514. scoreCalcActivity_homework.scorecalcId = scoreCalcBase.id;
  515. scoreCalcActivity_homework.name = "作業活動";
  516. scoreCalcActivity_homework.type = "homework";
  517. scoreCalcActivity_homework.rate = 30;
  518. scoreCalcActivity_homework.sort = 3;
  519. for (int j = 0; j < scoreCalcActivity_homework.items.Count; j++)
  520. {
  521. scoreCalcActivity_homework.itemRates.Add(1);
  522. scoreCalcActivity_homework.items[j].sort = j + 1;
  523. }
  524. scoreCalcActivity_homework.editScores = editScores;
  525. scoreCalcActivity_homework.code = scoreCalcActivity_homework.pk + "-" + teammodelId;
  526. scoreCalcActivity_homework = await clientTeacher.CreateItemAsync(scoreCalcActivity_homework, new PartitionKey($"{scoreCalcActivity_homework.code}"));
  527. //scoreCalcAct.Add(scoreCalcActivity_homework);
  528. #endregion
  529. #endregion
  530. #region ==== 5.3 用ScoreCalcAct的id 寫入課堂紀錄公式表ScoreCalcActFormula====
  531. #region ==== 出席-簡單出席計算法====
  532. ScoreCalcFunc scoreCalcFunc_simpleAttend = new ScoreCalcFunc();
  533. scoreCalcFunc_simpleAttend.code = scoreCalcFunc_simpleAttend.pk + "-" + teammodelId;
  534. scoreCalcFunc_simpleAttend.id = scoreCalcLsRecord.stuAttendFunctionId;
  535. scoreCalcFunc_simpleAttend.name = "簡單出席計算法";
  536. scoreCalcFunc_simpleAttend.scorecalcActId = scoreCalcLsRecord.id;
  537. scoreCalcFunc_simpleAttend.type = "lessonrecord";
  538. scoreCalcFunc_simpleAttend.method = "attend";
  539. scoreCalcFunc_simpleAttend.template = "simpleAttend";
  540. scoreCalcFunc_simpleAttend.keyvals.Add(new ScoreCalcFuncTemplateKeyval() { key = "一次扣幾分", val = "5" });
  541. scoreCalcFunc_simpleAttend.keyvals.Add(new ScoreCalcFuncTemplateKeyval() { key = "Absent_Sick", val = "true" });
  542. scoreCalcFunc_simpleAttend.keyvals.Add(new ScoreCalcFuncTemplateKeyval() { key = "Absent", val = "true" });
  543. scoreCalcFunc_simpleAttend.keyvals.Add(new ScoreCalcFuncTemplateKeyval() { key = "Absent_Personal", val = "true" });
  544. scoreCalcFunc_simpleAttend.keyvals.Add(new ScoreCalcFuncTemplateKeyval() { key = "Absent_Official", val = "true" });
  545. scoreCalcFunc_simpleAttend.content = " 100 - ( ( 病假次數 + 缺席次數 + 事假次數 + 公假次數 ) * 一次扣幾分 ) ";
  546. #endregion
  547. #region ==== 出席-出席率計算法====
  548. ScoreCalcFunc scoreCalcFunc_attendRate = new ScoreCalcFunc();
  549. scoreCalcFunc_attendRate.code = scoreCalcFunc_attendRate.pk + "-" + teammodelId;
  550. scoreCalcFunc_attendRate.id = Guid.NewGuid().ToString();
  551. scoreCalcFunc_attendRate.name = "出席率計算法";
  552. scoreCalcFunc_attendRate.scorecalcActId = scoreCalcLsRecord.id;
  553. scoreCalcFunc_attendRate.type = "lessonrecord";
  554. scoreCalcFunc_attendRate.method = "attend";
  555. scoreCalcFunc_attendRate.template = "attendRate";
  556. scoreCalcFunc_attendRate.keyvals.Add(new ScoreCalcFuncTemplateKeyval() { key = "每缺席1%扣幾分", val = "1" });
  557. scoreCalcFunc_attendRate.keyvals.Add(new ScoreCalcFuncTemplateKeyval() { key = "出席率超過%為滿分", val = "90" });
  558. scoreCalcFunc_attendRate.keyvals.Add(new ScoreCalcFuncTemplateKeyval() { key = "課堂總次數", val = "X" });
  559. scoreCalcFunc_attendRate.keyvals.Add(new ScoreCalcFuncTemplateKeyval() { key = "Absent_Sick", val = "true" });
  560. scoreCalcFunc_attendRate.keyvals.Add(new ScoreCalcFuncTemplateKeyval() { key = "Absent", val = "true" });
  561. scoreCalcFunc_attendRate.keyvals.Add(new ScoreCalcFuncTemplateKeyval() { key = "Absent_Personal", val = "true" });
  562. scoreCalcFunc_attendRate.keyvals.Add(new ScoreCalcFuncTemplateKeyval() { key = "Absent_Official", val = "true" });
  563. scoreCalcFunc_attendRate.content = " 100 - ( 出席率超過%為滿分 – ( ( 課堂總次數 - 病假次數 - 缺席次數 - 事假次數 - 公假次數 )/ 課堂總次數 * 100 ) ) * 每缺席1%扣幾分 ";
  564. #endregion
  565. #region ==== 記分板-標準化評分====
  566. ScoreCalcFunc scoreCalcFunc_standard = new ScoreCalcFunc();
  567. scoreCalcFunc_standard.code = scoreCalcFunc_standard.pk + "-" + teammodelId;
  568. scoreCalcFunc_standard.id = scoreCalcLsRecord.stuPointFunctionId;
  569. scoreCalcFunc_standard.name = "標準化評分";
  570. scoreCalcFunc_standard.scorecalcActId = scoreCalcLsRecord.id;
  571. scoreCalcFunc_standard.type = "lessonrecord";
  572. scoreCalcFunc_standard.method = "point";
  573. scoreCalcFunc_standard.template = "standard";
  574. scoreCalcFunc_standard.keyvals.Add(new ScoreCalcFuncTemplateKeyval() { key = "原始分數", val = "X" });
  575. scoreCalcFunc_standard.keyvals.Add(new ScoreCalcFuncTemplateKeyval() { key = "平均分數", val = "Y" });
  576. scoreCalcFunc_standard.keyvals.Add(new ScoreCalcFuncTemplateKeyval() { key = "平均數", val = "50" });
  577. scoreCalcFunc_standard.keyvals.Add(new ScoreCalcFuncTemplateKeyval() { key = "標準差", val = "50" });
  578. scoreCalcFunc_standard.content = " 10 * ( ( 原始分數 - 平均分數 ) / 標準差 ) + 平均數 ";
  579. #endregion
  580. #region ==== 記分板-百分比評分====
  581. ScoreCalcFunc scoreCalcFunc_percent = new ScoreCalcFunc();
  582. scoreCalcFunc_percent.code = scoreCalcFunc_percent.pk + "-" + teammodelId;
  583. scoreCalcFunc_percent.id = Guid.NewGuid().ToString();
  584. scoreCalcFunc_percent.name = "百分比評分";
  585. scoreCalcFunc_percent.scorecalcActId = scoreCalcLsRecord.id;
  586. scoreCalcFunc_percent.type = "lessonrecord";
  587. scoreCalcFunc_percent.method = "point";
  588. scoreCalcFunc_percent.template = "percent";
  589. scoreCalcFunc_percent.keyvals.Add(new ScoreCalcFuncTemplateKeyval() { key = "原始分數", val = "X" });
  590. scoreCalcFunc_percent.keyvals.Add(new ScoreCalcFuncTemplateKeyval() { key = "最高分數", val = "Y" });
  591. scoreCalcFunc_percent.content = " 100 * ( 原始分數 / 最高分數 )";
  592. #endregion
  593. #region ==== 互動-標準化評分====
  594. ScoreCalcFunc scoreCalcFunc_standard_interaction = new ScoreCalcFunc();
  595. scoreCalcFunc_standard_interaction.code = scoreCalcFunc_standard_interaction.pk + "-" + teammodelId;
  596. scoreCalcFunc_standard_interaction.id = scoreCalcLsRecord.stuItactFunctionId;
  597. scoreCalcFunc_standard_interaction.name = "標準化評分";
  598. scoreCalcFunc_standard_interaction.scorecalcActId = scoreCalcLsRecord.id;
  599. scoreCalcFunc_standard_interaction.type = "lessonrecord";
  600. scoreCalcFunc_standard_interaction.method = "interaction";
  601. scoreCalcFunc_standard_interaction.template = "standard";
  602. scoreCalcFunc_standard_interaction.keyvals.Add(new ScoreCalcFuncTemplateKeyval() { key = "原始分數", val = "X" });
  603. scoreCalcFunc_standard_interaction.keyvals.Add(new ScoreCalcFuncTemplateKeyval() { key = "平均分數", val = "Y" });
  604. scoreCalcFunc_standard_interaction.keyvals.Add(new ScoreCalcFuncTemplateKeyval() { key = "平均數", val = "50" });
  605. scoreCalcFunc_standard_interaction.keyvals.Add(new ScoreCalcFuncTemplateKeyval() { key = "標準差", val = "50" });
  606. scoreCalcFunc_standard_interaction.content = " 10 * ( ( 原始分數 - 平均分數 ) / 標準差 ) + 平均數 ";
  607. #endregion
  608. #region ==== 互動-百分比評分====
  609. ScoreCalcFunc scoreCalcFunc_percent_interaction = new ScoreCalcFunc();
  610. scoreCalcFunc_percent_interaction.code = scoreCalcFunc_percent_interaction.pk + "-" + teammodelId;
  611. scoreCalcFunc_percent_interaction.id = Guid.NewGuid().ToString();
  612. scoreCalcFunc_percent_interaction.name = "百分比評分";
  613. scoreCalcFunc_percent_interaction.scorecalcActId = scoreCalcLsRecord.id;
  614. scoreCalcFunc_percent_interaction.type = "lessonrecord";
  615. scoreCalcFunc_percent_interaction.method = "interaction";
  616. scoreCalcFunc_percent_interaction.template = "percent";
  617. scoreCalcFunc_percent_interaction.keyvals.Add(new ScoreCalcFuncTemplateKeyval() { key = "原始分數", val = "X" });
  618. scoreCalcFunc_percent_interaction.keyvals.Add(new ScoreCalcFuncTemplateKeyval() { key = "最高分數", val = "Y" });
  619. scoreCalcFunc_percent_interaction.content = " 100 * ( 原始分數 / 最高分數 )";
  620. #endregion
  621. scoreCalcFunc_simpleAttend = await clientTeacher.CreateItemAsync(scoreCalcFunc_simpleAttend, new PartitionKey($"{scoreCalcFunc_simpleAttend.code}"));
  622. scoreCalcFunc_attendRate = await clientTeacher.CreateItemAsync(scoreCalcFunc_attendRate, new PartitionKey($"{scoreCalcFunc_attendRate.code}"));
  623. scoreCalcFunc_standard = await clientTeacher.CreateItemAsync(scoreCalcFunc_standard, new PartitionKey($"{scoreCalcFunc_standard.code}"));
  624. scoreCalcFunc_percent = await clientTeacher.CreateItemAsync(scoreCalcFunc_percent, new PartitionKey($"{scoreCalcFunc_percent.code}"));
  625. scoreCalcFunc_standard_interaction = await clientTeacher.CreateItemAsync(scoreCalcFunc_standard_interaction, new PartitionKey($"{scoreCalcFunc_standard_interaction.code}"));
  626. scoreCalcFunc_percent_interaction = await clientTeacher.CreateItemAsync(scoreCalcFunc_percent_interaction, new PartitionKey($"{scoreCalcFunc_percent_interaction.code}"));
  627. #endregion
  628. #endregion
  629. var result = new
  630. {
  631. id = scoreCalcBase.id
  632. };
  633. return Ok(result);
  634. }
  635. catch (Exception e)
  636. {
  637. //await _dingDing.SendBotMsg($"OS,{_option.Location},open-api/upsert()\n{e.Message}\n{e.StackTrace}\n{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
  638. return BadRequest();
  639. }
  640. }
  641. /// <summary>
  642. /// (四)更新成績統計首頁表資料
  643. /// </summary>
  644. /// <param name="request"></param>
  645. /// <returns></returns>
  646. [ProducesDefaultResponseType]
  647. [Authorize(Roles = "IES")]
  648. [HttpPost("update-scorecalc")]
  649. public async Task<IActionResult> UpdateSscoreCalc(JsonElement request)
  650. {
  651. List<Object> scoreCalc = new List<object>();
  652. try
  653. {
  654. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  655. if (!request.TryGetProperty("teammodelId", out JsonElement teammodelId)) return BadRequest();
  656. var clientTeacher = _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher);
  657. UpdateSscoreCalcRq updateSscoreCalcRq = JsonConvert.DeserializeObject<UpdateSscoreCalcRq>(request.ToString());
  658. // 取主表資料
  659. ScoreCalcBase scoreCalcBase = await clientTeacher.ReadItemAsync<ScoreCalcBase>(id.ToString(), new PartitionKey($"ScoreCalc-{teammodelId}"));
  660. scoreCalc.Add(scoreCalcBase);
  661. #region 更新主表
  662. scoreCalcBase.name = updateSscoreCalcRq.name;
  663. scoreCalcBase.editScores = updateSscoreCalcRq.editScores;
  664. scoreCalcBase = await clientTeacher.ReplaceItemAsync(scoreCalcBase, $"{scoreCalcBase.id}", new PartitionKey(scoreCalcBase.code));
  665. #endregion
  666. #region 更新項目表
  667. for (int i = 0; i < updateSscoreCalcRq.ScoreCalcAct.Count; i++)
  668. {
  669. if (updateSscoreCalcRq.ScoreCalcAct[i].type == "lessonrecord")
  670. {
  671. // 取課堂紀錄資料
  672. ScoreCalcLsRecord scoreCalcLsRecord = await clientTeacher.ReadItemAsync<ScoreCalcLsRecord>(updateSscoreCalcRq.ScoreCalcAct[i].id, new PartitionKey($"ScoreCalcAct-{teammodelId}"));
  673. scoreCalcLsRecord.rate = updateSscoreCalcRq.ScoreCalcAct[i].rate;
  674. scoreCalcLsRecord.editScores = updateSscoreCalcRq.ScoreCalcAct[i].editScores;
  675. scoreCalcLsRecord.attendRate = updateSscoreCalcRq.ScoreCalcAct[i].attendRate;
  676. scoreCalcLsRecord.pointRate = updateSscoreCalcRq.ScoreCalcAct[i].pointRate;
  677. scoreCalcLsRecord.itactRate = updateSscoreCalcRq.ScoreCalcAct[i].itactRate;
  678. scoreCalcLsRecord = await clientTeacher.ReplaceItemAsync(scoreCalcLsRecord, $"{scoreCalcLsRecord.id}", new PartitionKey(scoreCalcLsRecord.code));
  679. }
  680. else
  681. {
  682. // 取其他活動資料
  683. ScoreCalcActivity scoreCalcActivity = await clientTeacher.ReadItemAsync<ScoreCalcActivity>(updateSscoreCalcRq.ScoreCalcAct[i].id, new PartitionKey($"ScoreCalcAct-{teammodelId}"));
  684. scoreCalcActivity.rate = updateSscoreCalcRq.ScoreCalcAct[i].rate;
  685. scoreCalcActivity.editScores = updateSscoreCalcRq.ScoreCalcAct[i].editScores;
  686. scoreCalcActivity = await clientTeacher.ReplaceItemAsync(scoreCalcActivity, $"{scoreCalcActivity.id}", new PartitionKey(scoreCalcActivity.code));
  687. }
  688. }
  689. #endregion
  690. var result = new
  691. {
  692. RtCode = "0",
  693. RtMsg = "OK"
  694. };
  695. return Ok(result);
  696. }
  697. catch (Exception e)
  698. {
  699. //await _dingDing.SendBotMsg($"OS,{_option.Location},open-api/upsert()\n{e.Message}\n{e.StackTrace}\n{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
  700. return BadRequest();
  701. }
  702. }
  703. /// <summary>
  704. /// (五)刪除成績統計
  705. /// </summary>
  706. /// <param name="request"></param>
  707. /// <returns></returns>
  708. [ProducesDefaultResponseType]
  709. [Authorize(Roles = "IES")]
  710. [HttpPost("delete-scorecalc")]
  711. public async Task<IActionResult> DeleteSscoreCalc(JsonElement request)
  712. {
  713. try
  714. {
  715. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  716. if (!request.TryGetProperty("teammodelId", out JsonElement teammodelId)) return BadRequest();
  717. var clientTeacher = _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher);
  718. List<string> idslist = new List<string>();
  719. List<string> scorecalcIdslist = new List<string>();
  720. List<string> formulaIdslist = new List<string>();
  721. idslist.Add(id.ToString());
  722. // 取項目表的 Id
  723. string sql = $"SELECT c.id FROM c where c.scorecalcId = '{id}' ";
  724. await foreach (var item in clientTeacher.GetItemQueryIterator<ItemId>(queryText: sql))
  725. {
  726. scorecalcIdslist.Add(item.id);
  727. }
  728. StringBuilder sb = new StringBuilder();
  729. for (int i = 0; i < scorecalcIdslist.Count; i++)
  730. {
  731. sb.Append($"'{scorecalcIdslist[i]}',");
  732. }
  733. // 取公式表的 id
  734. string sql_Formula = $"SELECT c.id FROM c where c.scorecalcActId in ({sb.ToString().Remove(sb.Length - 1, 1)}) ";
  735. await foreach (var item in clientTeacher.GetItemQueryIterator<ItemId>(queryText: sql_Formula))
  736. {
  737. formulaIdslist.Add(item.id);
  738. }
  739. //刪除主表 用傳進來的主表id 刪除資料
  740. var response = await clientTeacher.DeleteItemStreamAsync(id.ToString(), new PartitionKey($"ScoreCalc-{teammodelId}"));
  741. //await clientTeacher.DeleteItemsStreamAsync(idslist, $"ScoreCalc-{teammodelId}");
  742. //刪除項目表
  743. await clientTeacher.DeleteItemsStreamAsync(scorecalcIdslist, $"ScoreCalcAct-{teammodelId}");
  744. //刪除公式表
  745. await clientTeacher.DeleteItemsStreamAsync(formulaIdslist, $"ScoreCalcActFormula-{teammodelId}");
  746. var result = new
  747. {
  748. RtCode = "0",
  749. RtMsg = "OK"
  750. };
  751. return Ok(result);
  752. }
  753. catch (Exception e)
  754. {
  755. //await _dingDing.SendBotMsg($"OS,{_option.Location},open-api/upsert()\n{e.Message}\n{e.StackTrace}\n{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
  756. return BadRequest();
  757. }
  758. }
  759. /// <summary>
  760. /// (六)更新公式設定(一次可以處理多個公式)
  761. /// </summary>
  762. /// <param name="request"></param>
  763. /// <returns></returns>
  764. [ProducesDefaultResponseType]
  765. [Authorize(Roles = "IES")]
  766. [HttpPost("update-formula")]
  767. public async Task<IActionResult> UpdateFormula(JsonElement request)
  768. {
  769. try
  770. {
  771. if (!request.TryGetProperty("scoreCalcActId", out JsonElement scoreCalcActId)) return BadRequest();
  772. if (!request.TryGetProperty("teammodelId", out JsonElement teammodelId)) return BadRequest();
  773. var clientTeacher = _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher);
  774. UpdateFormulaRq updateFormulaRq = JsonConvert.DeserializeObject<UpdateFormulaRq>(request.ToString());
  775. List<ScoreCalcFunc> scoreCalcFuncs = new List<ScoreCalcFunc>();
  776. // 取公式表的 資料
  777. string sql = $"SELECT * FROM c where c.scorecalcActId = '{scoreCalcActId}' ";
  778. await foreach (var item in clientTeacher.GetItemQueryIterator<ScoreCalcFunc>(queryText: sql))
  779. {
  780. scoreCalcFuncs.Add(item);
  781. }
  782. // 比對資料 決定哪些公式及項目表要更新
  783. for (int i = 0; i < updateFormulaRq.scoreCalcFunc.Count; i++)
  784. {
  785. #region 更新項目表公式id
  786. if (updateFormulaRq.scoreCalcFunc[i].use)
  787. {
  788. // 更新項目使用的公式id
  789. // 取課堂紀錄資料
  790. // ToDo...以後可能需要其他活動也可以用公式
  791. ScoreCalcLsRecord scoreCalcLsRecord = await clientTeacher.ReadItemAsync<ScoreCalcLsRecord>(updateFormulaRq.scoreCalcActId, new PartitionKey($"ScoreCalcAct-{teammodelId}"));
  792. switch (updateFormulaRq.method)
  793. {
  794. case "attend":
  795. scoreCalcLsRecord.stuAttendFunctionId = updateFormulaRq.scoreCalcFunc[i].id;
  796. break;
  797. case "point":
  798. scoreCalcLsRecord.stuPointFunctionId = updateFormulaRq.scoreCalcFunc[i].id;
  799. break;
  800. case "interaction":
  801. scoreCalcLsRecord.stuItactFunctionId = updateFormulaRq.scoreCalcFunc[i].id;
  802. break;
  803. }
  804. scoreCalcLsRecord = await clientTeacher.ReplaceItemAsync(scoreCalcLsRecord, $"{scoreCalcLsRecord.id}", new PartitionKey(scoreCalcLsRecord.code));
  805. }
  806. #endregion
  807. #region 更新 or 新增公式
  808. for (int j = 0; j < scoreCalcFuncs.Count; j++)
  809. {
  810. if (updateFormulaRq.scoreCalcFunc[i].id == scoreCalcFuncs[j].id)
  811. {// 如果公式Id有代入 則更新公式
  812. // 取公式資料
  813. scoreCalcFuncs[j].name = updateFormulaRq.scoreCalcFunc[i].name;
  814. scoreCalcFuncs[j].keyvals = updateFormulaRq.scoreCalcFunc[i].keyvals;
  815. scoreCalcFuncs[j].content = updateFormulaRq.scoreCalcFunc[i].content;
  816. scoreCalcFuncs[j] = await clientTeacher.ReplaceItemAsync(scoreCalcFuncs[j], $"{scoreCalcFuncs[j].id}", new PartitionKey(scoreCalcFuncs[j].code));
  817. }
  818. }
  819. if (updateFormulaRq.scoreCalcFunc[i].id == "")
  820. {// 如果公式Id沒有代入 則新增公式
  821. ScoreCalcFunc scoreCalcFunc = new ScoreCalcFunc();
  822. scoreCalcFunc.code = $"ScoreCalcActFormula-{teammodelId}";
  823. scoreCalcFunc.id = Guid.NewGuid().ToString();
  824. scoreCalcFunc.name = updateFormulaRq.scoreCalcFunc[i].name;
  825. scoreCalcFunc.scorecalcActId = updateFormulaRq.scoreCalcActId;
  826. // ToDo...以後可能需要其他活動也可以用公式
  827. scoreCalcFunc.type = "lessonrecord";
  828. scoreCalcFunc.method = updateFormulaRq.method;
  829. scoreCalcFunc.template = updateFormulaRq.scoreCalcFunc[i].template;
  830. scoreCalcFunc.keyvals = updateFormulaRq.scoreCalcFunc[i].keyvals;
  831. scoreCalcFunc.content = updateFormulaRq.scoreCalcFunc[i].content;
  832. scoreCalcFunc = await clientTeacher.CreateItemAsync(scoreCalcFunc, new PartitionKey($"{scoreCalcFunc.code}"));
  833. }
  834. #endregion
  835. }
  836. var result = new
  837. {
  838. RtCode = "0",
  839. RtMsg = "OK"
  840. };
  841. return Ok(result);
  842. }
  843. catch (Exception e)
  844. {
  845. //await _dingDing.SendBotMsg($"OS,{_option.Location},open-api/upsert()\n{e.Message}\n{e.StackTrace}\n{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
  846. return BadRequest();
  847. }
  848. }
  849. /// <summary>
  850. ///(七)新增自訂項目及其子項目資料
  851. /// </summary>
  852. /// <param name="request"></param>
  853. /// <returns></returns>
  854. [ProducesDefaultResponseType]
  855. [Authorize(Roles = "IES")]
  856. [HttpPost("add-scorecalcact")]
  857. public async Task<IActionResult> AddScoreCalcAct(JsonElement request)
  858. {
  859. try
  860. {
  861. if (!request.TryGetProperty("scorecalcId", out JsonElement scorecalcId)) return BadRequest();
  862. if (!request.TryGetProperty("teammodelId", out JsonElement teammodelId)) return BadRequest();
  863. var clientTeacher = _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher);
  864. // 取主表資料
  865. ScoreCalcBase scoreCalcBase = await clientTeacher.ReadItemAsync<ScoreCalcBase>(scorecalcId.ToString(), new PartitionKey($"ScoreCalc-{teammodelId}"));
  866. #region 寫入DB 新增自訂項目及其子項目資料
  867. // 設定預設值
  868. ScoreCalcActivity scoreCalcActivity = new ScoreCalcActivity();
  869. scoreCalcActivity.id = Guid.NewGuid().ToString();
  870. scoreCalcActivity.code = $"ScoreCalcAct-{teammodelId}";
  871. ScoreCalcActivityItems scoreCalcActivityItems = new ScoreCalcActivityItems();
  872. scoreCalcActivityItems.id = Guid.NewGuid().ToString();
  873. scoreCalcActivityItems.name = "自訂項目名稱";
  874. scoreCalcActivityItems.use = true;
  875. scoreCalcActivityItems.sort = 1;
  876. scoreCalcActivity.items.Add(scoreCalcActivityItems);
  877. // 根據學生數量設定預設值
  878. List<double> zeroScores = new List<double>();
  879. for (int j = 0; j < scoreCalcBase.members.Count; j++)
  880. {
  881. zeroScores.Add(0);
  882. }
  883. scoreCalcActivity.stuActScores.Add(zeroScores);
  884. scoreCalcActivity.stuActScoresOrg.Add(zeroScores);
  885. scoreCalcActivity.scorecalcId = scorecalcId.ToString();
  886. scoreCalcActivity.name = "自訂活動名稱";
  887. scoreCalcActivity.type = "custom";
  888. scoreCalcActivity.rate = 10;
  889. scoreCalcActivity.editScores = zeroScores;
  890. scoreCalcActivity.itemRates = new List<double>() { 1 };
  891. //取得目前項目總數
  892. int count = 0;
  893. string sql = $"SELECT c.id FROM c where c.scorecalcId = '{scorecalcId.ToString()}' ";
  894. await foreach (var item in clientTeacher.GetItemQueryIterator<ItemId>(queryText: sql))
  895. {
  896. count++;
  897. }
  898. scoreCalcActivity.sort = count + 1;
  899. // 新增項目及子項目
  900. scoreCalcActivity = await clientTeacher.CreateItemAsync(scoreCalcActivity, new PartitionKey($"{scoreCalcActivity.code}"));
  901. #endregion
  902. #region 組合回傳格式
  903. ScoreCalcActivityActDto scoreCalcActivityActDto = new ScoreCalcActivityActDto();
  904. scoreCalcActivityActDto.id = scoreCalcActivity.id;
  905. scoreCalcActivityActDto.name = scoreCalcActivity.name;
  906. scoreCalcActivityActDto.type = scoreCalcActivity.type;
  907. scoreCalcActivityActDto.rate = scoreCalcActivity.rate;
  908. SubActActivity subActActivity = new SubActActivity();
  909. subActActivity.id = scoreCalcActivity.items[0].id;
  910. subActActivity.name = scoreCalcActivity.items[0].name;
  911. // 子項目比重由外層取得
  912. subActActivity.rate = scoreCalcActivity.itemRates[0];
  913. subActActivity.use = scoreCalcActivity.items[0].use;
  914. subActActivity.scores = scoreCalcActivity.stuActScores[0];
  915. scoreCalcActivityActDto.items.Add(subActActivity);
  916. scoreCalcActivityActDto.editScores = scoreCalcActivity.editScores;
  917. #endregion
  918. return Ok(scoreCalcActivityActDto);
  919. }
  920. catch (Exception e)
  921. {
  922. //await _dingDing.SendBotMsg($"OS,{_option.Location},open-api/upsert()\n{e.Message}\n{e.StackTrace}\n{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
  923. return BadRequest();
  924. }
  925. }
  926. /// <summary>
  927. ///(八)新增子項目
  928. /// </summary>
  929. /// <param name="request"></param>
  930. /// <returns></returns>
  931. [ProducesDefaultResponseType]
  932. [Authorize(Roles = "IES")]
  933. [HttpPost("add-scorecalcact-item")]
  934. public async Task<IActionResult> AddScoreCalcActItem(JsonElement request)
  935. {
  936. try
  937. {
  938. if (!request.TryGetProperty("scoreCalcActId", out JsonElement scoreCalcActId)) return BadRequest();
  939. if (!request.TryGetProperty("teammodelId", out JsonElement teammodelId)) return BadRequest();
  940. var clientTeacher = _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher);
  941. // 取項目表資料
  942. ScoreCalcActivityBase scoreCalcActivityBase = await clientTeacher.ReadItemAsync<ScoreCalcActivityBase>(scoreCalcActId.ToString(), new PartitionKey($"ScoreCalcAct-{teammodelId}"));
  943. // 取主表資料
  944. ScoreCalcBase scoreCalcBase = await clientTeacher.ReadItemAsync<ScoreCalcBase>(scoreCalcActivityBase.scorecalcId.ToString(), new PartitionKey($"ScoreCalc-{teammodelId}"));
  945. // 根據學生數量設定預設值
  946. List<double> zeroScores = new List<double>();
  947. for (int j = 0; j < scoreCalcBase.members.Count; j++)
  948. {
  949. zeroScores.Add(0);
  950. }
  951. // 設定子項目的預設值
  952. ScoreCalcActivityItems scoreCalcActivityItems = new ScoreCalcActivityItems();
  953. scoreCalcActivityItems.id = Guid.NewGuid().ToString();
  954. scoreCalcActivityItems.name = "自訂項目名稱";
  955. scoreCalcActivityItems.use = true;
  956. // 先判斷是否為課堂紀錄 根據項目的類別寫入的欄位需要調整
  957. if (scoreCalcActivityBase.type == "lessonrecord")
  958. {
  959. ScoreCalcLsRecord scoreCalcLsRecord = await clientTeacher.ReadItemAsync<ScoreCalcLsRecord>(scoreCalcActId.ToString(), new PartitionKey($"ScoreCalcAct-{teammodelId}"));
  960. scoreCalcLsRecord.items.Add(scoreCalcActivityItems);
  961. scoreCalcLsRecord.stuActAttendOrgVals.Add(zeroScores);
  962. scoreCalcLsRecord.stuActAttendScores.Add(zeroScores);
  963. scoreCalcLsRecord.stuActPointOrgVals.Add(zeroScores);
  964. scoreCalcLsRecord.stuActPointScores.Add(zeroScores);
  965. scoreCalcLsRecord.stuActItactOrgVals.Add(zeroScores);
  966. scoreCalcLsRecord.stuActItactScores.Add(zeroScores);
  967. scoreCalcLsRecord.itemRates.Add(1);
  968. scoreCalcLsRecord = await clientTeacher.ReplaceItemAsync(scoreCalcLsRecord, $"{scoreCalcLsRecord.id}", new PartitionKey(scoreCalcLsRecord.code));
  969. #region 組合回傳格式
  970. SubActLsRecord subActLsRecord = new SubActLsRecord();
  971. subActLsRecord.id = scoreCalcLsRecord.items[scoreCalcLsRecord.items.Count - 1].id;
  972. subActLsRecord.name = scoreCalcLsRecord.items[scoreCalcLsRecord.items.Count - 1].name;
  973. subActLsRecord.rate = scoreCalcLsRecord.itemRates[scoreCalcLsRecord.itemRates.Count - 1];
  974. subActLsRecord.use = scoreCalcLsRecord.items[scoreCalcLsRecord.items.Count - 1].use;
  975. subActLsRecord.stuActAttendScores = scoreCalcLsRecord.stuActAttendScores[scoreCalcLsRecord.stuActAttendScores.Count - 1];
  976. subActLsRecord.stuActPointScores = scoreCalcLsRecord.stuActPointScores[scoreCalcLsRecord.stuActPointScores.Count - 1];
  977. subActLsRecord.stuActItactScores = scoreCalcLsRecord.stuActItactScores[scoreCalcLsRecord.stuActItactScores.Count - 1];
  978. #endregion
  979. return Ok(subActLsRecord);
  980. }
  981. else
  982. {
  983. ScoreCalcActivity scoreCalcActivity = await clientTeacher.ReadItemAsync<ScoreCalcActivity>(scoreCalcActId.ToString(), new PartitionKey($"ScoreCalcAct-{teammodelId}"));
  984. scoreCalcActivity.items.Add(scoreCalcActivityItems);
  985. scoreCalcActivity.stuActScores.Add(zeroScores);
  986. scoreCalcActivity.stuActScoresOrg.Add(zeroScores);
  987. scoreCalcActivity.itemRates.Add(1);
  988. scoreCalcActivity = await clientTeacher.ReplaceItemAsync(scoreCalcActivity, $"{scoreCalcActivity.id}", new PartitionKey(scoreCalcActivity.code));
  989. #region 組合回傳格式
  990. SubActActivity subActActivity = new SubActActivity();
  991. subActActivity.id = scoreCalcActivity.items[scoreCalcActivity.items.Count - 1].id;
  992. subActActivity.name = scoreCalcActivity.items[scoreCalcActivity.items.Count - 1].name;
  993. subActActivity.rate = scoreCalcActivity.itemRates[scoreCalcActivity.itemRates.Count - 1];
  994. subActActivity.use = scoreCalcActivity.items[scoreCalcActivity.items.Count - 1].use;
  995. subActActivity.scores = scoreCalcActivity.stuActScores[scoreCalcActivity.stuActScores.Count - 1];
  996. #endregion
  997. return Ok(subActActivity);
  998. }
  999. }
  1000. catch (Exception e)
  1001. {
  1002. //await _dingDing.SendBotMsg($"OS,{_option.Location},open-api/upsert()\n{e.Message}\n{e.StackTrace}\n{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
  1003. return BadRequest();
  1004. }
  1005. }
  1006. /// <summary>
  1007. /// (九)更新項目及子項目資料
  1008. /// </summary>
  1009. /// <param name="request"></param>
  1010. /// <returns></returns>
  1011. [ProducesDefaultResponseType]
  1012. [Authorize(Roles = "IES")]
  1013. [HttpPost("update-scorecalcact")]
  1014. public async Task<IActionResult> UpdateScoreCalcAct(JsonElement request)
  1015. {
  1016. try
  1017. {
  1018. if (!request.TryGetProperty("scoreCalcActId", out JsonElement scoreCalcActId)) return BadRequest();
  1019. if (!request.TryGetProperty("teammodelId", out JsonElement teammodelId)) return BadRequest();
  1020. var clientTeacher = _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher);
  1021. // 取項目表資料
  1022. ScoreCalcActivity scoreCalcActivity = await clientTeacher.ReadItemAsync<ScoreCalcActivity>(scoreCalcActId.ToString(), new PartitionKey($"ScoreCalcAct-{teammodelId}"));
  1023. UpdateActivityActRq updateActivityActRq = JsonConvert.DeserializeObject<UpdateActivityActRq>(request.ToString());
  1024. //設定需更新的欄位值
  1025. scoreCalcActivity.name = updateActivityActRq.name;
  1026. scoreCalcActivity.rate = updateActivityActRq.rate;
  1027. for (int i = 0; i < scoreCalcActivity.items.Count; i++)
  1028. {
  1029. for (int j = 0; j < updateActivityActRq.items.Count; j++)
  1030. {
  1031. if (scoreCalcActivity.items[i].id == updateActivityActRq.items[j].id)
  1032. {
  1033. scoreCalcActivity.items[i].name = updateActivityActRq.items[j].name;
  1034. scoreCalcActivity.items[i].use = updateActivityActRq.items[j].use;
  1035. scoreCalcActivity.itemRates[i] = updateActivityActRq.items[j].rate;
  1036. }
  1037. }
  1038. }
  1039. //更新
  1040. scoreCalcActivity = await clientTeacher.ReplaceItemAsync(scoreCalcActivity, $"{scoreCalcActivity.id}", new PartitionKey(scoreCalcActivity.code));
  1041. var result = new
  1042. {
  1043. RtCode = "0",
  1044. RtMsg = "OK"
  1045. };
  1046. return Ok(result);
  1047. }
  1048. catch (Exception e)
  1049. {
  1050. //await _dingDing.SendBotMsg($"OS,{_option.Location},open-api/upsert()\n{e.Message}\n{e.StackTrace}\n{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
  1051. return BadRequest();
  1052. }
  1053. }
  1054. /// <summary>
  1055. ///(十)刪除自訂項目
  1056. /// </summary>
  1057. /// <param name="request"></param>
  1058. /// <returns></returns>
  1059. [ProducesDefaultResponseType]
  1060. [Authorize(Roles = "IES")]
  1061. [HttpPost("delete-scorecalcact")]
  1062. public async Task<IActionResult> DeleteSscoreCalcAct(JsonElement request)
  1063. {
  1064. try
  1065. {
  1066. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  1067. if (!request.TryGetProperty("teammodelId", out JsonElement teammodelId)) return BadRequest();
  1068. var clientTeacher = _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher);
  1069. ScoreCalcActivityBase scoreCalcActivityBase = await clientTeacher.ReadItemAsync<ScoreCalcActivityBase>(id.ToString(), new PartitionKey($"ScoreCalcAct-{teammodelId}"));
  1070. // 先檢查
  1071. if (scoreCalcActivityBase.type == "lessonrecord" || scoreCalcActivityBase.type == "exam" || scoreCalcActivityBase.type == "homework")
  1072. {
  1073. return BadRequest();
  1074. }
  1075. else
  1076. {
  1077. //刪除項目表
  1078. var response = await clientTeacher.DeleteItemStreamAsync(id.ToString(), new PartitionKey($"ScoreCalcAct-{teammodelId}"));
  1079. var result = new
  1080. {
  1081. RtCode = "0",
  1082. RtMsg = "OK"
  1083. };
  1084. return Ok(result);
  1085. }
  1086. }
  1087. catch (Exception e)
  1088. {
  1089. //await _dingDing.SendBotMsg($"OS,{_option.Location},open-api/upsert()\n{e.Message}\n{e.StackTrace}\n{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
  1090. return BadRequest();
  1091. }
  1092. }
  1093. /// <summary>
  1094. ///(十一)刪除子項目
  1095. /// </summary>
  1096. /// <param name="request"></param>
  1097. /// <returns></returns>
  1098. [ProducesDefaultResponseType]
  1099. [Authorize(Roles = "IES")]
  1100. [HttpPost("delete-scorecalcactitem")]
  1101. public async Task<IActionResult> DeleteSscoreCalcItem(JsonElement request)
  1102. {
  1103. try
  1104. {
  1105. if (!request.TryGetProperty("scoreCalcActId", out JsonElement scoreCalcActId)) return BadRequest();
  1106. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  1107. if (!request.TryGetProperty("teammodelId", out JsonElement teammodelId)) return BadRequest();
  1108. var clientTeacher = _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher);
  1109. // 取項目表資料
  1110. ScoreCalcActivityBase scoreCalcActivityBase = await clientTeacher.ReadItemAsync<ScoreCalcActivityBase>(scoreCalcActId.ToString(), new PartitionKey($"ScoreCalcAct-{teammodelId}"));
  1111. var result = new
  1112. {
  1113. RtCode = "0",
  1114. RtMsg = "OK"
  1115. };
  1116. // 先判斷是否為課堂紀錄 根據項目的類別刪除的欄位需要調整
  1117. if (scoreCalcActivityBase.type == "lessonrecord")
  1118. {
  1119. ScoreCalcLsRecord scoreCalcLsRecord = await clientTeacher.ReadItemAsync<ScoreCalcLsRecord>(scoreCalcActId.ToString(), new PartitionKey($"ScoreCalcAct-{teammodelId}"));
  1120. // 先尋找要刪除的子項目
  1121. for (int i = 0; i < scoreCalcLsRecord.items.Count; i++)
  1122. {
  1123. if (scoreCalcLsRecord.items[i].id == id.ToString())
  1124. {// 比對中了 移除該項目
  1125. scoreCalcLsRecord.items.Remove(scoreCalcLsRecord.items[i]);
  1126. scoreCalcLsRecord.stuActAttendOrgVals.Remove(scoreCalcLsRecord.stuActAttendOrgVals[i]);
  1127. scoreCalcLsRecord.stuActAttendScores.Remove(scoreCalcLsRecord.stuActAttendScores[i]);
  1128. scoreCalcLsRecord.stuActPointOrgVals.Remove(scoreCalcLsRecord.stuActPointOrgVals[i]);
  1129. scoreCalcLsRecord.stuActPointScores.Remove(scoreCalcLsRecord.stuActPointScores[i]);
  1130. scoreCalcLsRecord.stuActItactOrgVals.Remove(scoreCalcLsRecord.stuActItactOrgVals[i]);
  1131. scoreCalcLsRecord.stuActItactScores.Remove(scoreCalcLsRecord.stuActItactScores[i]);
  1132. scoreCalcLsRecord.itemRates.Remove(scoreCalcLsRecord.itemRates[i]);
  1133. }
  1134. }
  1135. scoreCalcLsRecord = await clientTeacher.ReplaceItemAsync(scoreCalcLsRecord, $"{scoreCalcLsRecord.id}", new PartitionKey(scoreCalcLsRecord.code));
  1136. return Ok(result);
  1137. }
  1138. else
  1139. {
  1140. ScoreCalcActivity scoreCalcActivity = await clientTeacher.ReadItemAsync<ScoreCalcActivity>(scoreCalcActId.ToString(), new PartitionKey($"ScoreCalcAct-{teammodelId}"));
  1141. // 先尋找要刪除的子項目
  1142. for (int i = 0; i < scoreCalcActivity.items.Count; i++)
  1143. {
  1144. if (scoreCalcActivity.items[i].id == id.ToString())
  1145. {// 比對中了 移除該項目
  1146. scoreCalcActivity.items.Remove(scoreCalcActivity.items[i]);
  1147. scoreCalcActivity.stuActScores.Remove(scoreCalcActivity.stuActScores[i]);
  1148. scoreCalcActivity.stuActScoresOrg.Remove(scoreCalcActivity.stuActScoresOrg[i]);
  1149. scoreCalcActivity.itemRates.Remove(scoreCalcActivity.itemRates[i]);
  1150. }
  1151. }
  1152. scoreCalcActivity = await clientTeacher.ReplaceItemAsync(scoreCalcActivity, $"{scoreCalcActivity.id}", new PartitionKey(scoreCalcActivity.code));
  1153. return Ok(result);
  1154. }
  1155. }
  1156. catch (Exception e)
  1157. {
  1158. //await _dingDing.SendBotMsg($"OS,{_option.Location},open-api/upsert()\n{e.Message}\n{e.StackTrace}\n{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
  1159. return BadRequest();
  1160. }
  1161. }
  1162. /// <summary>
  1163. ///(十二)登錄指定子項目成績
  1164. /// </summary>
  1165. /// <param name="request"></param>
  1166. /// <returns></returns>
  1167. [ProducesDefaultResponseType]
  1168. [Authorize(Roles = "IES")]
  1169. [HttpPost("update-itemscore")]
  1170. public async Task<IActionResult> UpdateItemScore(JsonElement request)
  1171. {
  1172. try
  1173. {
  1174. if (!request.TryGetProperty("scoreCalcActId", out JsonElement scoreCalcActId)) return BadRequest();
  1175. if (!request.TryGetProperty("teammodelId", out JsonElement teammodelId)) return BadRequest();
  1176. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  1177. var clientTeacher = _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher);
  1178. // 取項目表資料Base的部分
  1179. ScoreCalcActivityBase scoreCalcActivityBase = await clientTeacher.ReadItemAsync<ScoreCalcActivityBase>(scoreCalcActId.ToString(), new PartitionKey($"ScoreCalcAct-{teammodelId}"));
  1180. // 先判斷是否為課堂紀錄 根據項目的類別刪除的欄位需要調整
  1181. if (scoreCalcActivityBase.type == "lessonrecord")
  1182. {
  1183. UpdateScoreLessonRq updateScoreLessonRq = JsonConvert.DeserializeObject<UpdateScoreLessonRq>(request.ToString());
  1184. // 取課堂紀錄資料
  1185. ScoreCalcLsRecord scoreCalcLsRecord = await clientTeacher.ReadItemAsync<ScoreCalcLsRecord>(scoreCalcActId.ToString(), new PartitionKey($"ScoreCalcAct-{teammodelId}"));
  1186. for (int i = 0; i < scoreCalcLsRecord.items.Count; i++)
  1187. {
  1188. if (scoreCalcLsRecord.items[i].id == updateScoreLessonRq.id)
  1189. {
  1190. scoreCalcLsRecord.stuActAttendScores[i] = updateScoreLessonRq.stuActAttendScores;
  1191. scoreCalcLsRecord.stuActPointScores[i] = updateScoreLessonRq.stuActPointScores;
  1192. scoreCalcLsRecord.stuActItactScores[i] = updateScoreLessonRq.stuActItactScores;
  1193. }
  1194. }
  1195. //更新
  1196. scoreCalcLsRecord = await clientTeacher.ReplaceItemAsync(scoreCalcLsRecord, $"{scoreCalcLsRecord.id}", new PartitionKey(scoreCalcLsRecord.code));
  1197. }
  1198. else
  1199. {
  1200. UpdateScoreActivityRq updateScoreActivityRq = JsonConvert.DeserializeObject<UpdateScoreActivityRq>(request.ToString());
  1201. // 取其他活動資料
  1202. ScoreCalcActivity scoreCalcActivity = await clientTeacher.ReadItemAsync<ScoreCalcActivity>(scoreCalcActId.ToString(), new PartitionKey($"ScoreCalcAct-{teammodelId}"));
  1203. for (int i = 0; i < scoreCalcActivity.items.Count; i++)
  1204. {
  1205. if (scoreCalcActivity.items[i].id == updateScoreActivityRq.id)
  1206. {
  1207. scoreCalcActivity.stuActScores[i] = updateScoreActivityRq.scores;
  1208. }
  1209. }
  1210. //更新
  1211. scoreCalcActivity = await clientTeacher.ReplaceItemAsync(scoreCalcActivity, $"{scoreCalcActivity.id}", new PartitionKey(scoreCalcActivity.code));
  1212. }
  1213. var result = new
  1214. {
  1215. RtCode = "0",
  1216. RtMsg = "OK"
  1217. };
  1218. return Ok(result);
  1219. }
  1220. catch (Exception e)
  1221. {
  1222. //await _dingDing.SendBotMsg($"OS,{_option.Location},open-api/upsert()\n{e.Message}\n{e.StackTrace}\n{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
  1223. return BadRequest();
  1224. }
  1225. }
  1226. /// <summary>
  1227. ///(十三)匯出原始成績資料
  1228. /// </summary>
  1229. /// <param name="request"></param>
  1230. /// <returns></returns>
  1231. [ProducesDefaultResponseType]
  1232. [Authorize(Roles = "IES")]
  1233. [HttpPost("export-orgscore")]
  1234. public async Task<IActionResult> ExportOrgScore(JsonElement request)
  1235. {
  1236. try
  1237. {
  1238. if (!request.TryGetProperty("courseId", out JsonElement courseId)) return BadRequest();
  1239. if (!request.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
  1240. bool ishaveClassId = request.TryGetProperty("classId", out JsonElement classId);
  1241. bool ishaveGrouplistId = request.TryGetProperty("grouplistId", out JsonElement grouplistId);
  1242. bool ishaveTeammodelId = request.TryGetProperty("teammodelId", out JsonElement teammodelId);
  1243. bool ishaveSchoolId = request.TryGetProperty("schoolId", out JsonElement schoolId);
  1244. // classId 跟 grouplistId 兩個必須有一個必填
  1245. if (!ishaveClassId)
  1246. {
  1247. if (!ishaveGrouplistId)
  1248. {
  1249. return BadRequest();
  1250. }
  1251. else
  1252. {
  1253. if (!ishaveTeammodelId) return BadRequest();
  1254. }
  1255. }
  1256. else
  1257. {
  1258. if (!ishaveSchoolId) return BadRequest();
  1259. }
  1260. //班級
  1261. List<ScoreCalcMember> members = new List<ScoreCalcMember>();
  1262. // 設定活動預設值
  1263. ScoreCalcLsRecord scoreCalcLsRecord = new ScoreCalcLsRecord();
  1264. ScoreCalcActivity scoreCalcActivity_eaxm = new ScoreCalcActivity();
  1265. ScoreCalcActivity scoreCalcActivity_homework = new ScoreCalcActivity();
  1266. var isOKRequest = await getSystemScoresDate(courseId, scope, classId, grouplistId, teammodelId, schoolId, ishaveClassId, ishaveGrouplistId, members, scoreCalcLsRecord, scoreCalcActivity_eaxm, scoreCalcActivity_homework);
  1267. if (!isOKRequest) { return BadRequest(); }
  1268. #region 調整資料回傳格式
  1269. List<ExportOrgLsRecordData> exportlessonrecordData = new List<ExportOrgLsRecordData>();
  1270. List<ExportOrgActivityData> exporthomeworkData = new List<ExportOrgActivityData>();
  1271. List<ExportOrgActivityData> exportexamData = new List<ExportOrgActivityData>();
  1272. // 調整課程紀錄回傳格式
  1273. for (int i = 0; i < scoreCalcLsRecord.items.Count; i++)
  1274. {
  1275. ExportOrgLsRecordData exportOrgLsRecordData = new ExportOrgLsRecordData();
  1276. exportOrgLsRecordData.name = scoreCalcLsRecord.items[i].name;
  1277. for (int j = 0; j < members.Count; j++)
  1278. {
  1279. LessonScores lessonScores = new LessonScores();
  1280. lessonScores.id = members[j].id;
  1281. lessonScores.name = members[j].name;
  1282. lessonScores.no = members[j].no;
  1283. lessonScores.attend = scoreCalcLsRecord.stuActAttendOrgVals[i][j];
  1284. lessonScores.point = scoreCalcLsRecord.stuActPointOrgVals[i][j];
  1285. lessonScores.interaction = scoreCalcLsRecord.stuActItactOrgVals[i][j];
  1286. exportOrgLsRecordData.data.Add(lessonScores);
  1287. }
  1288. exportlessonrecordData.Add(exportOrgLsRecordData);
  1289. }
  1290. // 調整評量活動回傳格式
  1291. for (int i = 0; i < scoreCalcActivity_eaxm.items.Count; i++)
  1292. {
  1293. ExportOrgActivityData exportOrgActivityData = new ExportOrgActivityData();
  1294. exportOrgActivityData.name = scoreCalcActivity_eaxm.items[i].name;
  1295. for (int j = 0; j < members.Count; j++)
  1296. {
  1297. ActivityScores activityScores = new ActivityScores();
  1298. activityScores.id = members[j].id;
  1299. activityScores.name = members[j].name;
  1300. activityScores.no = members[j].no;
  1301. activityScores.score = scoreCalcActivity_eaxm.stuActScoresOrg[i][j];
  1302. exportOrgActivityData.data.Add(activityScores);
  1303. }
  1304. exportexamData.Add(exportOrgActivityData);
  1305. }
  1306. // 調整作業活動回傳格式
  1307. for (int i = 0; i < scoreCalcActivity_homework.items.Count; i++)
  1308. {
  1309. ExportOrgActivityData exportOrgActivityData = new ExportOrgActivityData();
  1310. exportOrgActivityData.name = scoreCalcActivity_homework.items[i].name;
  1311. for (int j = 0; j < members.Count; j++)
  1312. {
  1313. ActivityScores activityScores = new ActivityScores();
  1314. activityScores.id = members[j].id;
  1315. activityScores.name = members[j].name;
  1316. activityScores.no = members[j].no;
  1317. activityScores.score = scoreCalcActivity_homework.stuActScoresOrg[i][j];
  1318. exportOrgActivityData.data.Add(activityScores);
  1319. }
  1320. exporthomeworkData.Add(exportOrgActivityData);
  1321. }
  1322. #endregion
  1323. var orgData1 = new
  1324. {
  1325. lessonrecord = exportlessonrecordData,
  1326. homework = exporthomeworkData,
  1327. exam = exportexamData
  1328. };
  1329. return Ok(orgData1);
  1330. }
  1331. catch (Exception e)
  1332. {
  1333. //await _dingDing.SendBotMsg($"OS,{_option.Location},open-api/upsert()\n{e.Message}\n{e.StackTrace}\n{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
  1334. return BadRequest();
  1335. }
  1336. }
  1337. private async Task<bool> getSystemScoresDate(JsonElement courseId, JsonElement scope, JsonElement classId, JsonElement grouplistId, JsonElement teammodelId, JsonElement schoolId, bool ishaveClassId, bool ishaveGrouplistId, List<ScoreCalcMember> members, ScoreCalcLsRecord scoreCalcLsRecord, ScoreCalcActivity scoreCalcActivity_eaxm, ScoreCalcActivity scoreCalcActivity_homework)
  1338. {
  1339. var clientStudent = _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student);
  1340. var clientCommon = _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common);
  1341. var clientSchool = _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School);
  1342. var clientTeacher = _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher);
  1343. #region ==== 1~4. 取出系統資料====
  1344. //評量資料
  1345. List<ExamItem> examItem = new List<ExamItem>();
  1346. //評量名稱
  1347. List<ExamItem> examItemName = new List<ExamItem>();
  1348. //作業資料
  1349. List<HomeworkItem> homeworkItems = new List<HomeworkItem>();
  1350. //作業分數
  1351. List<HomeworkItem> homeworkItemsScore = new List<HomeworkItem>();
  1352. #region ==== 1. 取此班級所有學生====
  1353. string sql_members = "";
  1354. if (ishaveClassId)
  1355. {// 如果有classId 直接到student 取資料
  1356. sql_members = $"SELECT c.id, c.no, c.name FROM c WHERE c.classId= '{classId}'";
  1357. await foreach (var item in clientStudent.GetItemQueryIterator<ScoreCalcMember>(queryText: sql_members))
  1358. {
  1359. members.Add(item);
  1360. }
  1361. }
  1362. else if (scope.ToString() == "school")
  1363. {// 選課班 撈School 取id 撈student 取name no
  1364. sql_members = $"SELECT b.id FROM c join b in c.members WHERE c.id= '{grouplistId}'";
  1365. StringBuilder sb = new StringBuilder();
  1366. await foreach (var item in clientSchool.GetItemQueryIterator<ScoreCalcMember>(queryText: sql_members))
  1367. {
  1368. sb.Append($"'{item.id}',");
  1369. }
  1370. if (sb.Length > 0)
  1371. {
  1372. sql_members = $"SELECT c.id, c.no, c.name FROM c WHERE c.id in ({sb.ToString().Remove(sb.Length - 1, 1)})";
  1373. await foreach (var item in clientStudent.GetItemQueryIterator<ScoreCalcMember>(queryText: sql_members))
  1374. {
  1375. members.Add(item);
  1376. }
  1377. }
  1378. }
  1379. else if (scope.ToString() == "private")
  1380. {// 私人班 撈Teacher 取c.id, c.no 撈student 取name
  1381. sql_members = $"SELECT b.id FROM c join b in c.members WHERE c.id= '{grouplistId}'";
  1382. StringBuilder sb = new StringBuilder();
  1383. await foreach (var item in clientTeacher.GetItemQueryIterator<ScoreCalcMember>(queryText: sql_members))
  1384. {
  1385. sb.Append($"'{item.id}',");
  1386. }
  1387. if (sb.Length > 0)
  1388. {
  1389. sql_members = $"SELECT c.id, c.no, c.name FROM c WHERE c.id in ({sb.ToString().Remove(sb.Length - 1, 1)})";
  1390. await foreach (var item in clientStudent.GetItemQueryIterator<ScoreCalcMember>(queryText: sql_members))
  1391. {
  1392. members.Add(item);
  1393. }
  1394. }
  1395. }
  1396. else { return false; }
  1397. //orgData.Add(members);
  1398. #endregion
  1399. #region ==== 2. 取系統課堂紀錄成績====
  1400. #region ==== 取得開課紀錄====
  1401. StringBuilder sql = new StringBuilder();
  1402. sql.Append("select value(c) from c ");
  1403. int pageCount = 1000;
  1404. string sgroupIds = "";
  1405. if (ishaveClassId)
  1406. {
  1407. sgroupIds = classId + "";
  1408. }
  1409. else
  1410. {
  1411. sgroupIds = grouplistId + "";
  1412. }
  1413. JsonElement rqt = System.Text.Json.JsonSerializer.SerializeToElement(new
  1414. {
  1415. tmdid = teammodelId,
  1416. courseId = courseId,
  1417. groupIds = new List<string> { sgroupIds + "" }
  1418. });
  1419. Dictionary<string, object> dict = LessonService.GetLessonCond(rqt);
  1420. string continuationToken = null;
  1421. AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dict, sql);
  1422. string tbname = "";
  1423. string code = "";
  1424. string school = null;
  1425. string sqlPrivate = "";
  1426. List<string> autoTch = new List<string>();
  1427. if (scope.GetString().Equals("school"))
  1428. {
  1429. if (!string.IsNullOrEmpty($"{schoolId}"))
  1430. {
  1431. code = $"LessonRecord-{schoolId}";
  1432. tbname = "School";
  1433. school = $"{schoolId}";
  1434. List<string> ids = new List<string>();
  1435. //只查询某个老师的课例
  1436. if (!string.IsNullOrWhiteSpace($"{teammodelId}"))
  1437. {
  1438. ids.Add($"{teammodelId}");
  1439. }
  1440. else
  1441. {
  1442. string sqltch = "select distinct value(c.id) from c ";
  1443. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School)
  1444. .GetItemQueryIterator<string>(queryText: sqltch, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Teacher-{schoolId}") }))
  1445. {
  1446. ids.Add(item);
  1447. }
  1448. }
  1449. if (ids.Any())
  1450. {
  1451. string sqlTechbase = $"select distinct value(c.id) from c where c.id in ({string.Join(",", ids.Select(x => $"'{x}'"))}) and (array_contains(c.lessonShow,'student') or array_contains(c.lessonShow,'all')) ";
  1452. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher)
  1453. .GetItemQueryIterator<string>(queryText: sqlTechbase, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Base") }))
  1454. {
  1455. autoTch.Add(item);
  1456. }
  1457. }
  1458. }
  1459. else
  1460. {
  1461. return false;
  1462. }
  1463. }
  1464. else if ($"{scope}".Equals("private"))
  1465. {
  1466. code = $"LessonRecord";
  1467. tbname = "Teacher";
  1468. if (!string.IsNullOrEmpty($"{teammodelId}"))
  1469. {
  1470. sqlPrivate = $" and c.tmdid='{teammodelId}'";
  1471. List<string> ids = new List<string>();
  1472. ids.Add($"{teammodelId}");
  1473. if (ids.Any())
  1474. {
  1475. string sqlTechbase = $"select distinct value(c.id) from c where c.id in ({string.Join(",", ids.Select(x => $"'{x}'"))}) and (array_contains(c.lessonShow,'student') or array_contains(c.lessonShow,'all')) ";
  1476. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher)
  1477. .GetItemQueryIterator<string>(queryText: sqlTechbase, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Base") }))
  1478. {
  1479. autoTch.Add(item);
  1480. }
  1481. }
  1482. }
  1483. else
  1484. {
  1485. //如果不传tmdid, 则必须传递,课程id或者名单列表
  1486. // 如果不传递tmdid
  1487. if (!string.IsNullOrWhiteSpace($"{grouplistId}"))
  1488. {
  1489. return false;
  1490. }
  1491. }
  1492. }
  1493. else
  1494. {
  1495. return false;
  1496. }
  1497. List<LessonRecord> lessonRecords = new List<LessonRecord>();
  1498. try
  1499. {
  1500. string sql_status_managePage = "(c.status<>404 or IS_DEFINED(c.status) = false ) and ";
  1501. cosmosDbQuery.QueryText = cosmosDbQuery.QueryText.Replace("where", $" where {sql_status_managePage} array_length(c.groupIds)>0 {sqlPrivate} and ");
  1502. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tbname)
  1503. .GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, continuationToken: continuationToken,
  1504. requestOptions: new QueryRequestOptions() { MaxItemCount = pageCount, PartitionKey = new PartitionKey(code) }))
  1505. {
  1506. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1507. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1508. {
  1509. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  1510. {
  1511. var rcd = obj.ToObject<LessonRecord>();
  1512. if (rcd.hitaClientCmpCount <= 0 && rcd.collateTaskCount > 0)
  1513. {
  1514. rcd.hitaClientCmpCount = rcd.collateTaskCount;
  1515. }
  1516. if (rcd.learningCategory == null)
  1517. {
  1518. rcd.learningCategory = new LearningCategory();
  1519. }
  1520. if (rcd.hitaClientCmpCount > 0)
  1521. {
  1522. rcd.learningCategory.cooperation = 1;
  1523. }
  1524. lessonRecords.Add(rcd);
  1525. }
  1526. continuationToken = item.GetContinuationToken();
  1527. break;
  1528. }
  1529. }
  1530. long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  1531. //查询时处理已经过期的课例。防止ServiceBus未触发的。
  1532. var expireRecords = lessonRecords.Where(x => x.expire > 0 && now > x.expire);
  1533. try
  1534. {
  1535. foreach (var item in expireRecords)
  1536. {
  1537. //item.status = 404;
  1538. //await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tbname).ReplaceItemAsync(item, item.id, new PartitionKey(item.code));
  1539. var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
  1540. var messageChange = new ServiceBusMessage(new { delete_id = item.id, tmdid = item.tmdid, scope = item.scope, opt = "delete", school = item.school }.ToJsonString());
  1541. messageChange.ApplicationProperties.Add("name", "LessonRecordEvent");
  1542. await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageChange);
  1543. }
  1544. }
  1545. catch (Exception ex)
  1546. {
  1547. await _dingDing.SendBotMsg($"{_option.Location},ServiceBus ,LessonRecordEvent 发送消息失败,检查是否配置正常。", GroupNames.成都开发測試群組);
  1548. }
  1549. var tmdids = lessonRecords.Select(x => x.tmdid).ToHashSet();
  1550. if (tmdids != null && tmdids.Count > 0)
  1551. {
  1552. List<IdNameCode> codes = new List<IdNameCode>();
  1553. string sqltmd = $"select c.id,c.name,c.picture from c where c.id in ({string.Join(",", tmdids.Select(x => $"'{x}'"))})";
  1554. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<IdNameCode>(queryText: sqltmd, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey("Base") }))
  1555. {
  1556. codes.Add(item);
  1557. }
  1558. if (codes.IsNotEmpty())
  1559. {
  1560. lessonRecords.ForEach(x =>
  1561. {
  1562. var tmd = codes.Find(z => z.id.Equals(x.tmdid));
  1563. if (tmd != null)
  1564. {
  1565. x.tmdname = tmd.name;
  1566. x.tmdpicture = tmd.picture;
  1567. }
  1568. });
  1569. }
  1570. }
  1571. var groupIds = lessonRecords.SelectMany(x => x.groupIds);
  1572. if (groupIds.Any())
  1573. {
  1574. List<GroupListDto> groupLists = await GroupListService.GetGroupListByListids(_azureCosmos.GetCosmosClient(), _dingDing, groupIds.ToList(), school);
  1575. lessonRecords.ForEach(x =>
  1576. {
  1577. List<string> groupNmae = new List<string>();
  1578. x.groupIds.ForEach(y =>
  1579. {
  1580. var dto = groupLists.Find(z => z.id.Equals(y));
  1581. string name = dto != null ? dto.name : "-";
  1582. groupNmae.Add(name);
  1583. });
  1584. x.groupNames = groupNmae;
  1585. });
  1586. }
  1587. //return Ok(new { currCount = lessonRecords.Count, continuationToken, lessonRecords });
  1588. }
  1589. catch (Exception)
  1590. {
  1591. continuationToken = null;
  1592. //return Ok(new { currCount = 0, continuationToken = continuationToken, lessonRecords });
  1593. }
  1594. #endregion
  1595. List<LessonBase> lessonBases = new List<LessonBase>();
  1596. string blobname = "";
  1597. if (ishaveClassId)
  1598. {// 如果有ClassId 要用schoolId去取JSON
  1599. blobname = $"{schoolId}";
  1600. }
  1601. else if (ishaveGrouplistId)
  1602. {// 如果沒有ClassId 要用teammodelId去取JSON
  1603. blobname = $"{teammodelId}";
  1604. }
  1605. foreach (var item in lessonRecords)
  1606. {// 先檢查課堂紀錄是否存在再取資料
  1607. if (_azureStorage.GetBlobContainerClient(blobname).GetBlobClient($"/records/{item.id}/IES/base.json").Exists())
  1608. {
  1609. ScoreCalcActivityItems scoreCalcActivityItems = new ScoreCalcActivityItems();
  1610. scoreCalcActivityItems.id = item.id;
  1611. scoreCalcActivityItems.use = true;
  1612. scoreCalcLsRecord.items.Add(scoreCalcActivityItems);
  1613. BlobDownloadResult baseblobDownload = await _azureStorage.GetBlobContainerClient(blobname).GetBlobClient($"/records/{item.id}/IES/base.json").DownloadContentAsync();
  1614. LessonBase lessonBase = baseblobDownload.Content.ToObjectFromJson<LessonBase>();
  1615. if (lessonBase != null && lessonBase.summary != null)
  1616. {
  1617. lessonBases.Add(lessonBase);
  1618. }
  1619. }
  1620. }
  1621. // 重新比對資料以防 班級人數跟分數的數量對不上
  1622. for (int i = 0; i < lessonBases.Count; i++)
  1623. {
  1624. for (int j = 0; j < lessonBases[i].student.Count; j++)
  1625. {
  1626. for (int k = 0; k < members.Count; k++)
  1627. {
  1628. var find = from data in lessonBases[i].student
  1629. where data.id == members[j].id
  1630. select data;
  1631. if (find.Count() == 0)
  1632. {// 如果學生ID不存在就補0
  1633. lessonBases[i].student.Insert(k, new LessonStudent() { id = members[j].id });
  1634. ClientSummaryList clientSummaryList = new ClientSummaryList();
  1635. clientSummaryList.attendState = 0;
  1636. clientSummaryList.score = 0;
  1637. clientSummaryList.tnteractScore = 0;
  1638. lessonBases[i].report.clientSummaryList.Insert(k, clientSummaryList);
  1639. }
  1640. }
  1641. }
  1642. }
  1643. for (int i = 0; i < lessonBases.Count; i++)
  1644. {
  1645. // 補上寫進DB的子項目名稱欄位
  1646. scoreCalcLsRecord.items[i].name = lessonBases[i].summary.meterialName;
  1647. List<double> stuActAttendScores = new List<double>();
  1648. List<double> stuActPointScores = new List<double>();
  1649. List<double> stuActItactScores = new List<double>();
  1650. if (lessonBases[i].report.clientSummaryList.Count > 0)
  1651. {
  1652. for (int j = 0; j < lessonBases[i].report.clientSummaryList.Count; j++)
  1653. {
  1654. stuActAttendScores.Add(lessonBases[i].report.clientSummaryList[j].attendState);
  1655. stuActPointScores.Add(lessonBases[i].report.clientSummaryList[j].score);
  1656. stuActItactScores.Add(lessonBases[i].report.clientSummaryList[j].tnteractScore);
  1657. }
  1658. }
  1659. // 分數填入
  1660. scoreCalcLsRecord.stuActAttendScores.Add(stuActAttendScores);
  1661. scoreCalcLsRecord.stuActPointScores.Add(stuActPointScores);
  1662. scoreCalcLsRecord.stuActItactScores.Add(stuActItactScores);
  1663. scoreCalcLsRecord.stuActAttendOrgVals.Add(stuActAttendScores);
  1664. scoreCalcLsRecord.stuActPointOrgVals.Add(stuActPointScores);
  1665. scoreCalcLsRecord.stuActItactOrgVals.Add(stuActItactScores);
  1666. }
  1667. #endregion
  1668. #region ==== 3. 取系統評量活動成績====
  1669. string sql_exam = "";
  1670. // 取評量分數
  1671. if (ishaveClassId)
  1672. {
  1673. sql_exam = $"SELECT c.examId, c.studentIds, c.sum FROM c where c.info.id = '{classId}'";
  1674. }
  1675. else
  1676. {
  1677. sql_exam = $"SELECT c.examId, c.studentIds, c.sum FROM c where c.info.id = '{grouplistId}'";
  1678. }
  1679. StringBuilder sb_examIds = new StringBuilder();
  1680. sb_examIds.Append("'',");
  1681. await foreach (var item in clientCommon.GetItemQueryIterator<ExamItem>(queryText: sql_exam))
  1682. {
  1683. examItem.Add(item);
  1684. }
  1685. for (int i = 0; i < examItem.Count; i++)
  1686. {
  1687. sb_examIds.Append($"'{examItem[i].examId}',");
  1688. }
  1689. // 取評量名稱
  1690. string sql_examName = $"SELECT c.name FROM c where c.pk = 'Exam' and c.id in ({sb_examIds.ToString().Remove(sb_examIds.Length - 1, 1)})";
  1691. await foreach (var item in clientCommon.GetItemQueryIterator<ExamItem>(queryText: sql_examName))
  1692. {
  1693. examItemName.Add(item);
  1694. }
  1695. // 重新比對資料以防 班級人數跟評量分數的數量對不上
  1696. for (int i = 0; i < examItem.Count; i++)
  1697. {
  1698. for (int j = 0; j < members.Count; j++)
  1699. {
  1700. var find = from data in examItem[i].studentIds
  1701. where data.ToString() == members[j].id
  1702. select data;
  1703. if (find.Count() == 0)
  1704. {// 如果學生ID不存在就補0
  1705. examItem[i].studentIds.Insert(j, members[j].id);
  1706. examItem[i].sum.Insert(j, 0);
  1707. }
  1708. }
  1709. }
  1710. //如果評量ID的數量跟撈出來的名稱數量不一致
  1711. // 合併成完整資料
  1712. for (int i = 0; i < examItem.Count; i++)
  1713. {
  1714. ScoreCalcActivityItems scoreCalcActivityItems = new ScoreCalcActivityItems();
  1715. scoreCalcActivityItems.id = examItem[i].examId;
  1716. scoreCalcActivityItems.name = examItemName[i].name;
  1717. scoreCalcActivityItems.use = true;
  1718. scoreCalcActivity_eaxm.items.Add(scoreCalcActivityItems);
  1719. scoreCalcActivity_eaxm.stuActScores.Add(examItem[i].sum);
  1720. scoreCalcActivity_eaxm.stuActScoresOrg.Add(examItem[i].sum);
  1721. }
  1722. #endregion
  1723. #region ==== 4. 取系統作業活動成績====
  1724. //1. 取得此班級全部作業活動的id
  1725. string sql_homeworkIds = "";
  1726. // 由classId判斷是取甚麼班級
  1727. if (ishaveClassId)
  1728. {
  1729. sql_homeworkIds = $"SELECT c.id, c.name FROM c WHERE c.pk = 'Homework' AND ARRAY_CONTAINS(c.classes, \"{classId}\", true)";
  1730. }
  1731. else
  1732. {
  1733. sql_homeworkIds = $"SELECT c.id, c.name FROM c WHERE c.pk = \"Homework\" AND ARRAY_CONTAINS(c.stuLists, \"{grouplistId}\", true)";
  1734. }
  1735. await foreach (var item in clientCommon.GetItemQueryIterator<HomeworkItem>(queryText: sql_homeworkIds))
  1736. {
  1737. homeworkItems.Add(item);
  1738. }
  1739. //2. 用此班級全部作業活動的id去查詢此班級全部作業活動的分數
  1740. StringBuilder sb_homeworkItemIds = new StringBuilder();
  1741. sb_homeworkItemIds.Append("'',");
  1742. for (int i = 0; i < homeworkItems.Count; i++)
  1743. {
  1744. List<double> scores = new List<double>();
  1745. for (int j = 0; j < members.Count; j++)
  1746. {
  1747. scores.Add(0);
  1748. }
  1749. ScoreCalcActivityItems scoreCalcActivityItems = new ScoreCalcActivityItems();
  1750. scoreCalcActivityItems.id = homeworkItems[i].id;
  1751. scoreCalcActivityItems.name = homeworkItems[i].name;
  1752. scoreCalcActivityItems.use = true;
  1753. scoreCalcActivity_homework.items.Add(scoreCalcActivityItems);
  1754. scoreCalcActivity_homework.stuActScores.Add(scores);
  1755. scoreCalcActivity_homework.stuActScoresOrg.Add(scores);
  1756. // 組合id
  1757. sb_homeworkItemIds.Append($"'{homeworkItems[i].id}',");
  1758. }
  1759. // 取分數
  1760. string sql_homeworkData = $"SELECT c.pk, c.school, c.code, c.id, c.score FROM c WHERE c.pk = 'HomeworkRecord' and c.id in ({sb_homeworkItemIds.ToString().Remove(sb_homeworkItemIds.Length - 1, 1)}) order by c.code ";
  1761. await foreach (var item in clientStudent.GetItemQueryIterator<HomeworkItem>(queryText: sql_homeworkData))
  1762. {
  1763. homeworkItemsScore.Add(item);
  1764. }
  1765. // 先以子項目id群組化分數
  1766. Dictionary<string, List<HomeworkItem>> hidDataList = homeworkItemsScore.GroupBy(o => o.id).ToDictionary(o => o.Key, o => o.ToList());
  1767. // 整理出完整的學生作業分數資料
  1768. for (int i = 0; i < scoreCalcActivity_homework.items.Count; i++)
  1769. {
  1770. if (hidDataList.ContainsKey(scoreCalcActivity_homework.items[i].id))
  1771. {
  1772. List<HomeworkItem> listhi = hidDataList[scoreCalcActivity_homework.items[i].id];
  1773. for (int j = 0; j < listhi.Count; j++)
  1774. {
  1775. for (int k = 0; k < members.Count; k++)
  1776. {
  1777. if (listhi[j].code == $"{listhi[j].pk}-{listhi[j].school}-{members[k].id}")
  1778. {
  1779. scoreCalcActivity_homework.stuActScores[i][k] = listhi[j].score;
  1780. scoreCalcActivity_homework.stuActScoresOrg[i][k] = listhi[j].score;
  1781. }
  1782. }
  1783. }
  1784. }
  1785. }
  1786. #endregion
  1787. #endregion
  1788. return true;
  1789. }
  1790. /// <summary>
  1791. /// (十四)更新成績統計順序
  1792. /// </summary>
  1793. /// <param name="request"></param>
  1794. /// <returns></returns>
  1795. [ProducesDefaultResponseType]
  1796. [Authorize(Roles = "IES")]
  1797. [HttpPost("update-scorecalc-sort")]
  1798. public async Task<IActionResult> UpdateScoreCalcSort(JsonElement request)
  1799. {
  1800. try
  1801. {
  1802. if (!request.TryGetProperty("teammodelId", out JsonElement teammodelId)) return BadRequest();
  1803. var clientTeacher = _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher);
  1804. UpdateCalcSortRq updateCalcSortRq = JsonConvert.DeserializeObject<UpdateCalcSortRq>(request.ToString());
  1805. for (int i = 0; i < updateCalcSortRq.calcSorts.Count; i++)
  1806. {
  1807. //取主表資料
  1808. ScoreCalcBase scoreCalcBase = await clientTeacher.ReadItemAsync<ScoreCalcBase>(updateCalcSortRq.calcSorts[i].id.ToString(), new PartitionKey($"ScoreCalc-{teammodelId}"));
  1809. scoreCalcBase.sort = updateCalcSortRq.calcSorts[i].sort;
  1810. //更新
  1811. await clientTeacher.ReplaceItemAsync(scoreCalcBase, $"{scoreCalcBase.id}", new PartitionKey(scoreCalcBase.code));
  1812. }
  1813. var result = new
  1814. {
  1815. RtCode = "0",
  1816. RtMsg = "OK"
  1817. };
  1818. return Ok(result);
  1819. }
  1820. catch (Exception e)
  1821. {
  1822. //await _dingDing.SendBotMsg($"OS,{_option.Location},open-api/upsert()\n{e.Message}\n{e.StackTrace}\n{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
  1823. return BadRequest();
  1824. }
  1825. }
  1826. }
  1827. }