Browse Source

統測架構試做

jeff 11 months ago
parent
commit
004f7087be

+ 11 - 2
TEAMModelOS.SDK/Models/Cosmos/Teacher/JointExam.cs

@@ -11,7 +11,7 @@ namespace TEAMModelOS.SDK.Models
         public string name { get; set; }
         public JointEventGeo geo { get; set; } = new JointEventGeo(); //可參加活動的國省市區限制
         public List<string> admin { get; set; } = new List<string>(); //管理者
-        public List<JointEventGroup> group { get; set; } = new List<JointEventGroup>(); //群組
+        public List<JointEventGroup> groups { get; set; } = new List<JointEventGroup>(); //群組
         public List<JointEventSchedule> schedule { get; set; } = new List<JointEventSchedule>(); //進程
         public long createTime { get; set; }
         public long startTime { get; set; }
@@ -21,6 +21,7 @@ namespace TEAMModelOS.SDK.Models
         {
             public string id { get; set; }
             public string name { get; set; }
+            public HashSet<string> assistants { get; set; } = new HashSet<string>(); //評審TMID列表
         }
         public class JointEventPaper
         {
@@ -39,7 +40,8 @@ namespace TEAMModelOS.SDK.Models
         public class JointEventSchedule
         {
             public string type { get; set; } //"exam":評量 "join":報名
-            public string examType { get; set; } //評量類型 "regular":一般競賽 "Custom":挑戰賽
+            public string examType { get; set; } //評量類型 "regular":一般競賽 "custom":挑戰賽
+            public bool examOverwrite { get; set; } //評量可否重複作答 true:可 false:不可
             public string id { get; set; } 
             public string name { get; set; }
             public long startTime { get; set; }
@@ -53,6 +55,7 @@ namespace TEAMModelOS.SDK.Models
     /// </summary>
     public class JointEventGroupBase
     {
+        public string scope { get; set; } //school:學校(選課班) private:個人 
         public string creatorId { get; set; }
         public string creatorName { get; set; }
         public string schoolId { get; set; } //老師個人課程時為null
@@ -60,6 +63,7 @@ namespace TEAMModelOS.SDK.Models
         public List<JointEventGroupCourse> courseLists { get; set; } = new();
         public class JointEventGroupCourse
         {
+            public string subjectId { get; set; } //老師個人課程時為null
             public string courseId { get; set; }
             public string courseName { get; set; }
             public List<JointEventGroupCourseGroup> groupLists { get; set; } = new();
@@ -94,6 +98,7 @@ namespace TEAMModelOS.SDK.Models
         public List<JointEventClassSchoolClass> classLists { get; set; } = new();
         public class JointEventClassSchoolClass
         {
+            public string subjectId { get; set; } //為了生成評量,只好請班級多帶科目ID
             public string classId { get; set; }
             public string className { get; set; }
         }
@@ -118,8 +123,12 @@ namespace TEAMModelOS.SDK.Models
     public class JointExam : CosmosEntity
     {
         public string jointEventId { get; set; }
+        public string jointScheduleId { get; set; }
+        public string jointGroupId { get; set; }
         public string creatorId { get; set; }
         public string name { get; set; }
+        public string examType { get; set; } //評量類型 "regular":一般競賽 "custom":挑戰賽
+        public bool examOverwrite { get; set; } //評量可否重複作答 true:可 false:不可
         public List<JointEventClassBase> classes { get; set; } = new();
         public List<JointEventGroupBase> stuLists { get; set; } = new();
         public List<PaperSimple> papers { get; set; } = new();

+ 170 - 17
TEAMModelOS/Controllers/Teacher/JointEventController.cs

@@ -19,6 +19,9 @@ using Azure.Cosmos;
 using System;
 using static TEAMModelOS.SDK.Models.JointEvent;
 using System.Linq;
+using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
+using TEAMModelOS.Models.Dto;
+using TEAMModelOS.SDK.Models.Dtos;
 
 namespace TEAMModelOS.Controllers.Common
 {
@@ -190,6 +193,7 @@ namespace TEAMModelOS.Controllers.Common
                 if (string.IsNullOrWhiteSpace(jointEventId)) return BadRequest();
                 string groupId = (request.TryGetProperty("groupId", out JsonElement _groupId)) ? _groupId.GetString() : string.Empty;
                 string name = (request.TryGetProperty("name", out JsonElement _name)) ? _name.ToString() : string.Empty;
+                HashSet<string> assistants = (request.TryGetProperty("assistants", out JsonElement _assistants)) ? _assistants.ToObject<HashSet<string>>() : null;
                 if (string.IsNullOrWhiteSpace(name)) return BadRequest();
 
                 JointEvent jointEvent = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<JointEvent>(jointEventId, new PartitionKey("JointEvent"));
@@ -200,7 +204,7 @@ namespace TEAMModelOS.Controllers.Common
                 JointEventGroup group = new JointEventGroup();
                 if (!string.IsNullOrWhiteSpace(groupId))
                 {
-                    group = jointEvent.group.Where(g => g.id.Equals(groupId)).FirstOrDefault();
+                    group = jointEvent.groups.Where(g => g.id.Equals(groupId)).FirstOrDefault();
                     if(group==null)
                     {
                         return Ok(new { errCode = "4", err = "Invalid groupId." });
@@ -209,12 +213,20 @@ namespace TEAMModelOS.Controllers.Common
                     {
                         group.name = name;
                     }
+                    if(assistants != null)
+                    {
+                        group.assistants = assistants;
+                    }
                 }
                 else
                 {
                     group.id = Guid.NewGuid().ToString();
                     group.name = name;
-                    jointEvent.group.Add(group);
+                    if (assistants != null)
+                    {
+                        group.assistants = assistants;
+                    }
+                    jointEvent.groups.Add(group);
                 }
                 await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<JointEvent>(jointEvent, jointEvent.id, new PartitionKey("JointEvent"));
                 return Ok(new { errCode = "", err = "" });
@@ -246,12 +258,12 @@ namespace TEAMModelOS.Controllers.Common
             {
                 return Ok(new { errCode = "3", err = "Invalid jointEventId." });
             }
-            JointEventGroup group = jointEvent.group.Where(g => g.id.Equals(groupId)).FirstOrDefault();
+            JointEventGroup group = jointEvent.groups.Where(g => g.id.Equals(groupId)).FirstOrDefault();
             if (group == null)
             {
                 return Ok(new { errCode = "4", err = "Invalid groupId." });
             }
-            jointEvent.group.Remove(group);
+            jointEvent.groups.Remove(group);
             await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<JointEvent>(jointEvent, jointEvent.id, new PartitionKey("JointEvent"));
             return Ok(new { errCode = "", err = "" });
         }
@@ -274,7 +286,8 @@ namespace TEAMModelOS.Controllers.Common
                 string jointEventId = (request.TryGetProperty("jointEventId", out JsonElement _jointEventId)) ? _jointEventId.ToString() : string.Empty;
                 string type = (request.TryGetProperty("type", out JsonElement _type)) ? _type.ToString() : string.Empty;
                 string examType = (request.TryGetProperty("examType", out JsonElement _examType)) ? _examType.ToString() : string.Empty;
-                if(type.Equals("exam") && (!examType.Equals("regular") && !examType.Equals("Custom"))) return BadRequest();
+                bool examOverwrite = (request.TryGetProperty("examOverwrite", out JsonElement _examOverwrite)) ? _examOverwrite.GetBoolean() : false;
+                if (type.Equals("exam") && (!examType.Equals("regular") && !examType.Equals("Custom"))) return BadRequest();
                 string name = (request.TryGetProperty("name", out JsonElement _name)) ? _name.ToString() : string.Empty;
                 if (string.IsNullOrWhiteSpace(jointEventId) || string.IsNullOrWhiteSpace(type) || string.IsNullOrWhiteSpace(name)) return BadRequest();
                 string scheduleId = (request.TryGetProperty("scheduleId", out JsonElement _scheduleId)) ? _scheduleId.ToString() : string.Empty;
@@ -297,6 +310,7 @@ namespace TEAMModelOS.Controllers.Common
                         jointEventSchedule.name = name;
                         jointEventSchedule.type = type;
                         jointEventSchedule.examType = (type.Equals("join")) ? null : examType;
+                        jointEventSchedule.examOverwrite = examOverwrite;
                         jointEventSchedule.startTime = startTime;
                         jointEventSchedule.endTime = endTime;
                         jointEventSchedule.progress = (startTime <= now && now <= endTime) ? "going" : (now < startTime) ? "pending" : "finish";
@@ -313,6 +327,7 @@ namespace TEAMModelOS.Controllers.Common
                     jointEventSchedule.name = name;
                     jointEventSchedule.type = type;
                     jointEventSchedule.examType = (type.Equals("join")) ? null : examType;
+                    jointEventSchedule.examOverwrite = examOverwrite;
                     jointEventSchedule.startTime = startTime;
                     jointEventSchedule.endTime = endTime;
                     jointEventSchedule.progress = (startTime <= now && now <= endTime) ? "going" : (now < startTime) ? "pending" : "finish";
@@ -388,8 +403,8 @@ namespace TEAMModelOS.Controllers.Common
         {
             try {
                 var client = _azureCosmos.GetCosmosClient();
-                List<JointEventGroup> JointCourse = new List<JointEventGroup>();
-                StringBuilder stringBuilder = new($"SELECT c.id, c.code, c.pk, c.jointEventId, c.jointGroupId, c.creatorId, c.creatorName, c.courseLists FROM c JOIN cs IN c.courseLists WHERE 1=1 ");
+                List<JointEventGroupDb> JointCourse = new List<JointEventGroupDb>();
+                StringBuilder stringBuilder = new($"SELECT * FROM c WHERE 1=1 ");
                 string jointEventId = (request.TryGetProperty("jointEventId", out JsonElement _jointEventId)) ? _jointEventId.ToString() : string.Empty;
                 string jointGroupId = (request.TryGetProperty("jointGroupId", out JsonElement _jointGroupId)) ? _jointGroupId.ToString() : string.Empty;
                 if (!string.IsNullOrWhiteSpace(jointEventId))
@@ -405,12 +420,7 @@ namespace TEAMModelOS.Controllers.Common
                 {
                     stringBuilder.Append($" AND c.creatorId = '{creatorId}' ");
                 }
-                string courseId = (request.TryGetProperty("courseId", out JsonElement _courseId)) ? _courseId.ToString() : string.Empty;
-                if (!string.IsNullOrWhiteSpace(courseId))
-                {
-                    stringBuilder.Append($" AND cs.courseId = '{courseId}' ");
-                }
-                if(string.IsNullOrWhiteSpace(jointEventId) && string.IsNullOrWhiteSpace(jointGroupId) && string.IsNullOrWhiteSpace(courseId))
+                if(string.IsNullOrWhiteSpace(jointEventId) && string.IsNullOrWhiteSpace(jointGroupId))
                 {
                     stringBuilder.Append($" AND c.id = '00' ");
                 }
@@ -421,10 +431,11 @@ namespace TEAMModelOS.Controllers.Common
                     {
                         foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
                         {
-                            JointCourse.Add(obj.ToObject<JointEventGroup>());
+                            JointCourse.Add(obj.ToObject<JointEventGroupDb>());
                         }
                     }
                 }
+
                 return Ok(new { data = JointCourse });
             }
             catch (Exception e)
@@ -451,8 +462,9 @@ namespace TEAMModelOS.Controllers.Common
                 string jointGroupId = (request.TryGetProperty("jointGroupId", out JsonElement _jointGroupId)) ? _jointGroupId.ToString() : string.Empty;
                 string creatorId = (request.TryGetProperty("creatorId", out JsonElement _creatorId)) ? _creatorId.ToString() : string.Empty;
                 string creatorName = (request.TryGetProperty("creatorName", out JsonElement _creatorName)) ? _creatorName.ToString() : string.Empty;
+                string scope = (request.TryGetProperty("scope", out JsonElement _scope)) ? _scope.ToString() : string.Empty;
                 List<JointEventGroupBase.JointEventGroupCourse> courseLists = (request.TryGetProperty("courseLists", out JsonElement _courseLists)) ? _courseLists.ToObject<List<JointEventGroupBase.JointEventGroupCourse>>() : null;
-                if (string.IsNullOrWhiteSpace(jointEventId) || string.IsNullOrWhiteSpace(jointGroupId) || string.IsNullOrWhiteSpace(creatorId) || courseLists == null)
+                if (string.IsNullOrWhiteSpace(jointEventId) || string.IsNullOrWhiteSpace(jointGroupId) || string.IsNullOrWhiteSpace(creatorId) || courseLists == null || string.IsNullOrWhiteSpace(scope))
                 {
                     return BadRequest();
                 }
@@ -472,6 +484,7 @@ namespace TEAMModelOS.Controllers.Common
                 if(string.IsNullOrWhiteSpace(jointCourse.id))
                 {
                     if(string.IsNullOrWhiteSpace(creatorName)) return BadRequest();
+                    jointCourse.scope = scope;
                     jointCourse.id = Guid.NewGuid().ToString();
                     jointCourse.code = "JointCourse";
                     jointCourse.pk = "JointCourse";
@@ -491,6 +504,26 @@ namespace TEAMModelOS.Controllers.Common
                 return BadRequest();
             }
         }
+        /// <summary>
+        /// 新建修改教師課程及組別
+        /// </summary>
+        [ProducesDefaultResponseType]
+        [Authorize(Roles = "IES")]
+#if !DEBUG
+        [AuthToken(Roles = "teacher")]
+#endif
+        [HttpPost("course/delete")]
+        public async Task<IActionResult> JointCourseDelete(JsonElement request)
+        {
+            var client = _azureCosmos.GetCosmosClient();
+            string jointCourseId = (request.TryGetProperty("jointCourseId", out JsonElement _jointCourseId)) ? _jointCourseId.ToString() : string.Empty;
+            if (string.IsNullOrWhiteSpace(jointCourseId))
+            {
+                return BadRequest();
+            }
+            await client.GetContainer(Constant.TEAMModelOS, "Teacher").DeleteItemAsync<JointEventGroupDb>(jointCourseId, new PartitionKey("JointCourse"));
+            return Ok(new { errCode = "", err = "" });
+        }
 
         /// <summary>
         /// 取得統測評量
@@ -502,7 +535,7 @@ namespace TEAMModelOS.Controllers.Common
 #if !DEBUG
         [AuthToken(Roles = "teacher")]
 #endif
-        [HttpPost("exam/find")]
+        [HttpPost("jointexam/find")]
         public async Task<IActionResult> ExamFind(JsonElement request)
         {
             try
@@ -602,12 +635,132 @@ namespace TEAMModelOS.Controllers.Common
             }
             catch (Exception e)
             {
-                await _dingDing.SendBotMsg($"OS,{_option.Location},jointevent/jointexam/find()\n{e.Message}\n{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
+                //await _dingDing.SendBotMsg($"OS,{_option.Location},jointevent/jointexam/find()\n{e.Message}\n{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
                 return BadRequest();
             }
 
         }
 
+        /// <summary>
+        /// 新建變更統測評量
+        /// </summary>
+        /// <param name="request"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [Authorize(Roles = "IES")]
+#if !DEBUG
+        [AuthToken(Roles = "teacher")]
+#endif
+        [HttpPost("jointexam/upsert")]
+        public async Task<IActionResult> upsertJointExam(JsonElement request)
+        {
+            try
+            {
+                var client = _azureCosmos.GetCosmosClient();
+                long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+                string jointEventId = (request.TryGetProperty("jointEventId", out JsonElement _jointEventId)) ? _jointEventId.ToString() : string.Empty;
+                string jointGroupId = (request.TryGetProperty("jointGroupId", out JsonElement _jointGroupId)) ? _jointGroupId.ToString() : string.Empty;
+                string jointScheduleId = (request.TryGetProperty("jointScheduleId", out JsonElement _jointScheduleId)) ? _jointScheduleId.ToString() : string.Empty;
+                string jointExamId = (request.TryGetProperty("jointExamId", out JsonElement _jointExamId)) ? _jointExamId.ToString() : string.Empty;
+                string creatorId = (request.TryGetProperty("creatorId", out JsonElement _creatorId)) ? _creatorId.ToString() : string.Empty;
+                string name = (request.TryGetProperty("creatorId", out JsonElement _name)) ? _name.ToString() : string.Empty;
+                string source = (request.TryGetProperty("source", out JsonElement _source)) ? _source.ToString() : string.Empty;
+                PaperSimple paper = (request.TryGetProperty("paper", out JsonElement _paper)) ? _paper.ToObject<PaperSimple>() : null;
+                List<JointEventGroupBase> stuLists = (request.TryGetProperty("stuLists", out JsonElement _stuLists)) ? _stuLists.ToObject<List<JointEventGroupBase>>() : null;
+                List<JointEventClassBase> classes = (request.TryGetProperty("classes", out JsonElement _classes)) ? _classes.ToObject<List<JointEventClassBase>>() : null;
+
+                if (string.IsNullOrWhiteSpace(jointEventId) || string.IsNullOrWhiteSpace(jointGroupId) || string.IsNullOrWhiteSpace(jointScheduleId))
+                {
+                    return BadRequest();
+                }
+                //取得schedule
+                JointEventGroup jointEventGroup = new JointEventGroup();
+                JointEventSchedule jointEventSchedule = new JointEventSchedule();
+                StringBuilder stringBuilderSchedule = new($"SELECT cg.id as groupId, cg.name as groupName, cg.assistants, cs.id as scheduleId, cs.type as scheduleType, cs.examType, cs.examOverwrite, cs.name as scheduleName, cs.startTime as scheduleStartTime, cs.endTime as scheduleEndTime, cs.progress as scheduleProgress FROM c JOIN cs IN c.schedule JOIN cg IN c.groups WHERE c.id = '{jointEventId}' AND cs.id = '{jointScheduleId}' AND cg.id = '{jointGroupId}' ");
+                await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryStreamIterator(queryText: stringBuilderSchedule.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("JointEvent") }))
+                {
+                    using var json = await JsonDocument.ParseAsync(item.ContentStream);
+                    if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
+                    {
+                        foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
+                        {
+                            jointEventGroup.id = obj.GetProperty("groupId").GetString();
+                            jointEventGroup.name = obj.GetProperty("groupName").GetString();
+                            jointEventGroup.assistants = obj.GetProperty("assistants").ToObject<HashSet<string>>();
+                            jointEventSchedule.id = obj.GetProperty("scheduleId").GetString();
+                            jointEventSchedule.examType = obj.GetProperty("examType").GetString();
+                            jointEventSchedule.examOverwrite = obj.GetProperty("examOverwrite").GetBoolean();
+                            jointEventSchedule.type = obj.GetProperty("scheduleType").GetString();
+                            jointEventSchedule.name = obj.GetProperty("scheduleName").GetString();
+                            jointEventSchedule.startTime = obj.GetProperty("scheduleStartTime").GetInt64();
+                            jointEventSchedule.endTime = obj.GetProperty("scheduleEndTime").GetInt64();
+                            jointEventSchedule.progress = obj.GetProperty("scheduleProgress").GetString();
+                        }
+                    }
+                }
+                if(string.IsNullOrWhiteSpace(jointEventGroup.id) || string.IsNullOrWhiteSpace(jointEventSchedule.id))
+                {
+                    return Ok(new { errCode = "3", err = "Invalid jointEventId." });
+                }
+                JointExam jointExam = new JointExam();
+                if(!string.IsNullOrWhiteSpace(jointExamId))
+                {
+                    try
+                    {
+                        jointExam = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<JointExam>(jointExamId, new PartitionKey("JointExam"));
+                    }
+                    catch (Exception e)
+                    {
+                        return Ok(new { errCode = "6", err = "Invalid jointExamId." });
+                    }
+                    if (!string.IsNullOrWhiteSpace(name)) jointExam.name = name;
+
+                }
+                else
+                {
+                    if(paper == null) return Ok(new { errCode = "7", err = "Invalid paper." });
+                    if(string.IsNullOrWhiteSpace(creatorId)) return Ok(new { errCode = "8", err = "Invalid creatorId." });
+                    if (string.IsNullOrWhiteSpace(name)) return Ok(new { errCode = "9", err = "Invalid name." });
+                    if (string.IsNullOrWhiteSpace(source)) return Ok(new { errCode = "10", err = "Invalid source." });
+                    if (jointEventSchedule.examType.Equals("custom")) //冠軍賽,要填classes或stuLists擇一必須
+                    {
+                        if(classes == null || stuLists == null)
+                        {
+                            return Ok(new { errCode = "8", err = "Invalid classes or stuLists." });
+                        }
+                    }
+                    jointExam.id = Guid.NewGuid().ToString();
+                    jointExam.jointEventId = jointEventId;
+                    jointExam.jointScheduleId = jointScheduleId;
+                    jointExam.jointGroupId = jointGroupId;
+                    jointExam.creatorId = creatorId;
+                    jointExam.name = name;
+                    jointExam.examType = jointEventSchedule.examType;
+                    jointExam.examOverwrite = jointEventSchedule.examOverwrite;
+                    if(jointExam.examType.Equals("custom"))
+                    {
+                        if (classes != null) jointExam.classes = classes;
+                        if (stuLists != null) jointExam.stuLists = stuLists;
+                    }
+                    jointExam.source = source;
+                    jointExam.papers.Add(paper);
+                    jointExam.startTime = jointEventSchedule.startTime;
+                    jointExam.endTime = jointEventSchedule.endTime;
+                    jointExam.progress = (jointExam.startTime > now ) ? "pending" : (jointExam.endTime > now) ? "finish" : "going";
+                    jointExam.createTime = now;
+                }
+
+
+
+                return Ok(new { errCode = "", err = "" });
+            }
+            catch (Exception e)
+            {
+                //await _dingDing.SendBotMsg($"OS,{_option.Location},jointevent/jointexam/find()\n{e.Message}\n{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
+                return BadRequest();
+            }
+        }
+
         //以JointEvent.schedule為資訊新建更新JointExam
         //public async Task<ItemResponse<JointExam>> upsertJointExamBySchedule(string jointEventId, string creatorId, List<JointEventTGroupBase> groupLists, List<PaperSimple> papers, JointEvent.JointEventSchedule scheduleRow)
         //{