瀏覽代碼

Merge branch 'develop' of http://52.130.252.100:10000/TEAMMODEL/TEAMModelOS into develop

CrazyIter_Bin 10 月之前
父節點
當前提交
c2b3c3d886

+ 16 - 2
TEAMModelBI/Controllers/RepairApi/SchoolRepController.cs

@@ -576,19 +576,33 @@ namespace TEAMModelBI.Controllers.RepairApi
         /// <returns></returns>
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [ProducesDefaultResponseType]
         [HttpPost("set-allProdAnalysis")]
         [HttpPost("set-allProdAnalysis")]
-        public async Task<IActionResult> SetAllProdAnalysis()
+        public async Task<IActionResult> SetAllProdAnalysis(JsonElement jsonElement)
         {
         {
             var _azureCosmosClient = _azureCosmos.GetCosmosClient();
             var _azureCosmosClient = _azureCosmos.GetCosmosClient();
             var _azureCosmosClientCsv2 = _azureCosmos.GetCosmosClient(name: "CoreServiceV2");
             var _azureCosmosClientCsv2 = _azureCosmos.GetCosmosClient(name: "CoreServiceV2");
             var _azureCosmosClientCsv2Read = _azureCosmos.GetCosmosClient(name: "CoreServiceV2CnRead");
             var _azureCosmosClientCsv2Read = _azureCosmos.GetCosmosClient(name: "CoreServiceV2CnRead");
             var datetime = DateTimeOffset.UtcNow;
             var datetime = DateTimeOffset.UtcNow;
             var y = $"{datetime.Year}";
             var y = $"{datetime.Year}";
+            string month = (jsonElement.TryGetProperty("month", out JsonElement _month)) ? $"{_month}" : string.Empty;
+            string day = (jsonElement.TryGetProperty("day", out JsonElement _day)) ? $"{_day}" : string.Empty;
             var redisClinet2 = _azureRedis.GetRedisClient(2);
             var redisClinet2 = _azureRedis.GetRedisClient(2);
             var keys = new HashSet<RedisKey>();
             var keys = new HashSet<RedisKey>();
             int nextCursor = 0;
             int nextCursor = 0;
             do
             do
             {
             {
-                RedisResult redisResult = redisClinet2.Execute("SCAN", nextCursor.ToString(), "MATCH", "TeachingData:*", "COUNT", "1000");
+                string sql = "TeachingData:*";
+                if (!string.IsNullOrWhiteSpace(month)) {
+                    int _m = 0;
+                    string mString = (Int32.TryParse(month, out _m) && _m > 0 && _m < 10) ? $"0{_m}" : $"{_m}";
+                    sql = $"TeachingData:{mString}*"; //[例]TeachingData:08*
+                    if(!string.IsNullOrWhiteSpace(day))
+                    {
+                        int _d = 0;
+                        string dString = (Int32.TryParse(day, out _d) && _d > 0 && _d < 10) ? $"0{_d}" : $"{_d}";
+                        sql = $"TeachingData:{mString}{dString}"; //[例]TeachingData:0801
+                    }
+                }
+                RedisResult redisResult = redisClinet2.Execute("SCAN", nextCursor.ToString(), "MATCH", $"{sql}", "COUNT", "1000");
                 var innerResult = (RedisResult[])redisResult;
                 var innerResult = (RedisResult[])redisResult;
                 nextCursor = int.Parse((string)innerResult[0]);
                 nextCursor = int.Parse((string)innerResult[0]);
                 List<RedisKey> resultLines = ((RedisKey[])innerResult[1]).ToList();
                 List<RedisKey> resultLines = ((RedisKey[])innerResult[1]).ToList();

+ 118 - 35
TEAMModelOS.Function/IESServiceBusTrigger.cs

@@ -39,6 +39,8 @@ using System.Net;
 using Newtonsoft.Json;
 using Newtonsoft.Json;
 using System.Security.Policy;
 using System.Security.Policy;
 using System.Net.Http.Headers;
 using System.Net.Http.Headers;
+using Microsoft.AspNetCore.Hosting;
+
 namespace TEAMModelOS.Function
 namespace TEAMModelOS.Function
 {
 {
     public class IESServiceBusTrigger
     public class IESServiceBusTrigger
@@ -58,10 +60,11 @@ namespace TEAMModelOS.Function
         private readonly HttpTrigger _httpTrigger;
         private readonly HttpTrigger _httpTrigger;
         private readonly BackgroundWorkerQueue _backgroundWorkerQueue;
         private readonly BackgroundWorkerQueue _backgroundWorkerQueue;
         private readonly IHttpClientFactory _httpClient;
         private readonly IHttpClientFactory _httpClient;
+        private readonly IWebHostEnvironment _environment;
         public IESServiceBusTrigger(ILogger<IESServiceBusTrigger> logger, HttpTrigger httpTrigger, SnowflakeId snowflakeId, CoreAPIHttpService coreAPIHttpService,
         public IESServiceBusTrigger(ILogger<IESServiceBusTrigger> logger, HttpTrigger httpTrigger, SnowflakeId snowflakeId, CoreAPIHttpService coreAPIHttpService,
             AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis,
             AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis,
             AzureServiceBusFactory serviceBus, IOptionsSnapshot<Option> option,
             AzureServiceBusFactory serviceBus, IOptionsSnapshot<Option> option,
-             IConfiguration configuration, BackgroundWorkerQueue backgroundWorkerQueue, IHttpClientFactory httpClient)
+            IConfiguration configuration, BackgroundWorkerQueue backgroundWorkerQueue, IHttpClientFactory httpClient, IWebHostEnvironment hostingEnvironment)
         {
         {
             _logger = logger;
             _logger = logger;
             _azureCosmos = azureCosmos;
             _azureCosmos = azureCosmos;
@@ -77,6 +80,7 @@ namespace TEAMModelOS.Function
             _httpTrigger = httpTrigger;
             _httpTrigger = httpTrigger;
             _backgroundWorkerQueue = backgroundWorkerQueue;
             _backgroundWorkerQueue = backgroundWorkerQueue;
             _httpClient=httpClient;
             _httpClient=httpClient;
+            _environment = hostingEnvironment;
         }
         }
         [Function("GenPDF")]
         [Function("GenPDF")]
         public async Task Run(
         public async Task Run(
@@ -852,19 +856,20 @@ namespace TEAMModelOS.Function
             try
             try
             {
             {
 
 
-                _backgroundWorkerQueue.QueueBackgroundWorkItem(async task => {
+                _backgroundWorkerQueue.QueueBackgroundWorkItem(async task =>
+                {
 
 
                     //await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-名单成员变更-GroupChange\n{msg}", GroupNames.醍摩豆服務運維群組);
                     //await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-名单成员变更-GroupChange\n{msg}", GroupNames.醍摩豆服務運維群組);
                     //await _dingDing.SendBotMsg($"名单变化{msg}", GroupNames.成都开发測試群組);
                     //await _dingDing.SendBotMsg($"名单变化{msg}", GroupNames.成都开发測試群組);
 
 
-                    int add = groupChange.tmdjoin.Count-groupChange.tmdleave.Count+groupChange.stujoin.Count-groupChange.stuleave.Count;
+                    int add = groupChange.tmdjoin.Count - groupChange.tmdleave.Count + groupChange.stujoin.Count - groupChange.stuleave.Count;
                     if (groupChange.scope.Equals("private") && (groupChange.type.Equals("student") || groupChange.type.Equals("class") || groupChange.type.Equals("teach")))
                     if (groupChange.scope.Equals("private") && (groupChange.type.Equals("student") || groupChange.type.Equals("class") || groupChange.type.Equals("teach")))
                     {
                     {
-                        await SystemService.RecordAccumulateData(_azureRedis, _dingDing, new Accumulate { client=groupChange.client, count=add, id= groupChange.listid, scope="teacher", key= "grouplist", name=groupChange.name, target= groupChange.creatorId });
+                        await SystemService.RecordAccumulateData(_azureRedis, _dingDing, new Accumulate { client = groupChange.client, count = add, id = groupChange.listid, scope = "teacher", key = "grouplist", name = groupChange.name, target = groupChange.creatorId });
                     }
                     }
-                    if (groupChange.scope.Equals("school")  && (groupChange.type.Equals("student") || groupChange.type.Equals("class") || groupChange.type.Equals("teach")))
+                    if (groupChange.scope.Equals("school") && (groupChange.type.Equals("student") || groupChange.type.Equals("class") || groupChange.type.Equals("teach")))
                     {
                     {
-                        await SystemService.RecordAccumulateData(_azureRedis, _dingDing, new Accumulate { client=groupChange.client, count=add, id= groupChange.listid, scope="school", key= "grouplist", name=groupChange.name, target=groupChange.school });
+                        await SystemService.RecordAccumulateData(_azureRedis, _dingDing, new Accumulate { client = groupChange.client, count = add, id = groupChange.listid, scope = "school", key = "grouplist", name = groupChange.name, target = groupChange.school });
                     }
                     }
                     //名单变动修改学生课程关联信息
                     //名单变动修改学生课程关联信息
                     //await StuListService.FixStuCourse(client, stuListChange);
                     //await StuListService.FixStuCourse(client, stuListChange);
@@ -900,7 +905,7 @@ namespace TEAMModelOS.Function
                         if (groupChange.stuleave.Count > 0)
                         if (groupChange.stuleave.Count > 0)
                             await BIStats.SetTypeAddStats(client, _dingDing, groupChange.school, "Student", -groupChange.stuleave.Count);//BI统计增/减量
                             await BIStats.SetTypeAddStats(client, _dingDing, groupChange.school, "Student", -groupChange.stuleave.Count);//BI统计增/减量
                     }
                     }
-                    if ((groupChange.type.Equals("class") || groupChange.type.Equals("teach") || groupChange.type.Equals("student"))  && "school".Equals(groupChange.scope) &&  "upsert".Equals(groupChange.status) && !string.IsNullOrWhiteSpace(groupChange.school))
+                    if ((groupChange.type.Equals("class") || groupChange.type.Equals("teach") || groupChange.type.Equals("student")) && "school".Equals(groupChange.scope) && "upsert".Equals(groupChange.status) && !string.IsNullOrWhiteSpace(groupChange.school))
                     {
                     {
 
 
                         var data = await GroupListService.GetMemberByListids(_coreAPIHttpService, client, _dingDing, new List<string> { groupChange.listid }, groupChange.school);
                         var data = await GroupListService.GetMemberByListids(_coreAPIHttpService, client, _dingDing, new List<string> { groupChange.listid }, groupChange.school);
@@ -917,10 +922,10 @@ namespace TEAMModelOS.Function
                                 GroupListSemester groupListSemester = data.groups.First().ToJsonString().ToObject<GroupListSemester>();
                                 GroupListSemester groupListSemester = data.groups.First().ToJsonString().ToObject<GroupListSemester>();
                                 groupListSemester.id = id;
                                 groupListSemester.id = id;
                                 groupListSemester.code = code;
                                 groupListSemester.code = code;
-                                groupListSemester.pk="GroupListSemester";
-                                groupListSemester.semesterId=dataSemester.currSemester.id;
-                                groupListSemester.groupListId=data.groups.First().id;
-                                groupListSemester.studyYear=dataSemester.studyYear;
+                                groupListSemester.pk = "GroupListSemester";
+                                groupListSemester.semesterId = dataSemester.currSemester.id;
+                                groupListSemester.groupListId = data.groups.First().id;
+                                groupListSemester.studyYear = dataSemester.studyYear;
                                 await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).UpsertItemAsync<GroupListSemester>(groupListSemester, new PartitionKey(groupListSemester.code));
                                 await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).UpsertItemAsync<GroupListSemester>(groupListSemester, new PartitionKey(groupListSemester.code));
                             }
                             }
                         }
                         }
@@ -988,9 +993,10 @@ namespace TEAMModelOS.Function
                         List<ItemInfo> items = new List<ItemInfo>();
                         List<ItemInfo> items = new List<ItemInfo>();
                         School school = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>($"{itemCondDto.key}", new PartitionKey("Base"));
                         School school = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>($"{itemCondDto.key}", new PartitionKey("Base"));
                         var period = school.period.Find(z => z.id.Equals(itemCondDto.filed));
                         var period = school.period.Find(z => z.id.Equals(itemCondDto.filed));
-                        string subjectIn =string.Empty;
-                        if (period!=null  && period.subjects.IsNotEmpty()) {
-                              subjectIn =$" and c.subjectId in({string.Join(",", period.subjects.Select(x=>$"'{x.id}'"))})";
+                        string subjectIn = string.Empty;
+                        if (period != null && period.subjects.IsNotEmpty())
+                        {
+                            subjectIn = $" and c.subjectId in({string.Join(",", period.subjects.Select(x => $"'{x.id}'"))})";
                         }
                         }
                         var queryslt = $"SELECT c.gradeIds,c.subjectId,c.periodId,c.type,c.level,c.field ,c.scope FROM c where   c.periodId='{itemCondDto.filed}' and c.pid= null {subjectIn} ";
                         var queryslt = $"SELECT c.gradeIds,c.subjectId,c.periodId,c.type,c.level,c.field ,c.scope FROM c where   c.periodId='{itemCondDto.filed}' and c.pid= null {subjectIn} ";
                         await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIteratorSql<ItemInfo>(queryText: queryslt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{itemCondDto.key}") }))
                         await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIteratorSql<ItemInfo>(queryText: queryslt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{itemCondDto.key}") }))
@@ -1259,7 +1265,8 @@ namespace TEAMModelOS.Function
             List<LessonUpdate> updates = new List<LessonUpdate>();
             List<LessonUpdate> updates = new List<LessonUpdate>();
             try
             try
             {
             {
-                _backgroundWorkerQueue.QueueBackgroundWorkItem(async task => {
+                _backgroundWorkerQueue.QueueBackgroundWorkItem(async task =>
+                {
 
 
                     //更新课堂记录
                     //更新课堂记录
                     if (data.TryGetProperty("lesson_id", out JsonElement _lessonId) && !string.IsNullOrEmpty($"{_lessonId}"))
                     if (data.TryGetProperty("lesson_id", out JsonElement _lessonId) && !string.IsNullOrEmpty($"{_lessonId}"))
@@ -1787,9 +1794,9 @@ namespace TEAMModelOS.Function
 
 
                                             {
                                             {
                                                 await SystemService.RecordAccumulateData(_azureRedis, _dingDing, new SDK.Models.Dtos.Accumulate
                                                 await SystemService.RecordAccumulateData(_azureRedis, _dingDing, new SDK.Models.Dtos.Accumulate
-                                                { client="hiteach", count=1, id=schoolBase.id, key="lesson-create", name=schoolBase.name, scope="school", target=schoolBase.id });
+                                                { client = "hiteach", count = 1, id = schoolBase.id, key = "lesson-create", name = schoolBase.name, scope = "school", target = schoolBase.id });
                                                 await SystemService.RecordAccumulateData(_azureRedis, _dingDing, new SDK.Models.Dtos.Accumulate
                                                 await SystemService.RecordAccumulateData(_azureRedis, _dingDing, new SDK.Models.Dtos.Accumulate
-                                                { client="hiteach", count=1, id=lessonRecord.tmdid, key="lesson-create", name="课例", scope="teacher", target=lessonRecord.tmdid });
+                                                { client = "hiteach", count = 1, id = lessonRecord.tmdid, key = "lesson-create", name = "课例", scope = "teacher", target = lessonRecord.tmdid });
                                             }
                                             }
                                             var space = await BlobService.GetSurplusSpace(school, scope, $"{Environment.GetEnvironmentVariable("Option:Location")}", _azureCosmos, _azureRedis, _azureStorage, _dingDing, _httpTrigger);
                                             var space = await BlobService.GetSurplusSpace(school, scope, $"{Environment.GetEnvironmentVariable("Option:Location")}", _azureCosmos, _azureRedis, _azureStorage, _dingDing, _httpTrigger);
                                             SchoolSetting setting = null;
                                             SchoolSetting setting = null;
@@ -1914,7 +1921,7 @@ namespace TEAMModelOS.Function
                                             var space = await BlobService.GetSurplusSpace(tmdid, scope, $"{Environment.GetEnvironmentVariable("Option:Location")}", _azureCosmos, _azureRedis, _azureStorage, _dingDing, _httpTrigger);
                                             var space = await BlobService.GetSurplusSpace(tmdid, scope, $"{Environment.GetEnvironmentVariable("Option:Location")}", _azureCosmos, _azureRedis, _azureStorage, _dingDing, _httpTrigger);
                                             //20230208调整之前  if (blobTotal * 1073741824 - blobsize > 2147483648)  //剩余空间大于2G 
                                             //20230208调整之前  if (blobTotal * 1073741824 - blobsize > 2147483648)  //剩余空间大于2G 
                                             //剩余空间不足,则开启自动清理机制
                                             //剩余空间不足,则开启自动清理机制
-                                            if (space.surplus> 0)
+                                            if (space.surplus > 0)
                                             {
                                             {
                                                 //大于0则表示空间充足
                                                 //大于0则表示空间充足
                                                 lessonLimit = -1;
                                                 lessonLimit = -1;
@@ -2138,7 +2145,7 @@ namespace TEAMModelOS.Function
                                                 //=-1 则表示不限制上传数量
                                                 //=-1 则表示不限制上传数量
                                             }
                                             }
                                             await SystemService.RecordAccumulateData(_azureRedis, _dingDing, new SDK.Models.Dtos.Accumulate
                                             await SystemService.RecordAccumulateData(_azureRedis, _dingDing, new SDK.Models.Dtos.Accumulate
-                                            { client="hiteach", count=1, id=lessonRecord.tmdid, key="lesson-create", name="课例", scope="teacher", target=lessonRecord.tmdid });
+                                            { client = "hiteach", count = 1, id = lessonRecord.tmdid, key = "lesson-create", name = "课例", scope = "teacher", target = lessonRecord.tmdid });
                                         }
                                         }
                                     }
                                     }
                                     catch (Exception e)
                                     catch (Exception e)
@@ -2260,12 +2267,12 @@ namespace TEAMModelOS.Function
                 await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-ServiceBus,LessonRecordExpire()\n{ex.Message}\n{ex.StackTrace}\n\n{jsonMsg.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
                 await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-ServiceBus,LessonRecordExpire()\n{ex.Message}\n{ex.StackTrace}\n\n{jsonMsg.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
             }
             }
             finally
             finally
-            {  
+            {
                 // Complete the message
                 // Complete the message
                 await messageActions.CompleteMessageAsync(message);
                 await messageActions.CompleteMessageAsync(message);
             }
             }
 
 
-          
+
         }
         }
         /// <summary>
         /// <summary>
         /// UseDevelopmentStorage=true
         /// UseDevelopmentStorage=true
@@ -2286,7 +2293,7 @@ namespace TEAMModelOS.Function
             try
             try
             {
             {
                 //await _dingDing.SendBotMsg($"IES5,{Environment.GetEnvironmentVariable("Option:Location")},Imei AF call\n{msg.ToJsonString()}", GroupNames.成都开发測試群組);
                 //await _dingDing.SendBotMsg($"IES5,{Environment.GetEnvironmentVariable("Option:Location")},Imei AF call\n{msg.ToJsonString()}", GroupNames.成都开发測試群組);
-                
+
                 if (json.RootElement.TryGetProperty("channel", out JsonElement channel) &&
                 if (json.RootElement.TryGetProperty("channel", out JsonElement channel) &&
                 json.RootElement.TryGetProperty("userid", out JsonElement userid) &&
                 json.RootElement.TryGetProperty("userid", out JsonElement userid) &&
                 json.RootElement.TryGetProperty("school", out JsonElement school) &&
                 json.RootElement.TryGetProperty("school", out JsonElement school) &&
@@ -2309,17 +2316,17 @@ namespace TEAMModelOS.Function
                                 imei.userid = userid.GetString();
                                 imei.userid = userid.GetString();
                                 if (!string.IsNullOrWhiteSpace($"{imeiType}"))
                                 if (!string.IsNullOrWhiteSpace($"{imeiType}"))
                                 {
                                 {
-                                    imei.imeiType= $"{imeiType}";
+                                    imei.imeiType = $"{imeiType}";
                                 }
                                 }
                                 else
                                 else
                                 {
                                 {
-                                    if (imei.id.Length==11)
+                                    if (imei.id.Length == 11)
                                     {
                                     {
-                                        imei.imeiType="139zhxy";
+                                        imei.imeiType = "139zhxy";
                                     }
                                     }
-                                    else if (imei.id.Length==15)
+                                    else if (imei.id.Length == 15)
                                     {
                                     {
-                                        imei.imeiType="tianbo";
+                                        imei.imeiType = "tianbo";
                                     }
                                     }
                                 }
                                 }
                                 await db.GetContainer(Constant.TEAMModelOS, Constant.Student).ReplaceItemAsync<Imei>(imei, imei.id);
                                 await db.GetContainer(Constant.TEAMModelOS, Constant.Student).ReplaceItemAsync<Imei>(imei, imei.id);
@@ -2333,12 +2340,12 @@ namespace TEAMModelOS.Function
                 await _dingDing.SendBotMsg($"IES5,{Environment.GetEnvironmentVariable("Option:Location")},Imei AF error\n{ex.Message}\n{ex.StackTrace}{json.RootElement.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
                 await _dingDing.SendBotMsg($"IES5,{Environment.GetEnvironmentVariable("Option:Location")},Imei AF error\n{ex.Message}\n{ex.StackTrace}{json.RootElement.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
             }
             }
             finally
             finally
-            {  
+            {
                 // Complete the message
                 // Complete the message
                 await messageActions.CompleteMessageAsync(message);
                 await messageActions.CompleteMessageAsync(message);
             }
             }
 
 
-           
+
         }
         }
 
 
 
 
@@ -2360,7 +2367,8 @@ namespace TEAMModelOS.Function
             _logger.LogInformation("Message Content-Type: {contentType}", message.ContentType);
             _logger.LogInformation("Message Content-Type: {contentType}", message.ContentType);
             try
             try
             {
             {
-                _backgroundWorkerQueue.QueueBackgroundWorkItem(async task => {
+                _backgroundWorkerQueue.QueueBackgroundWorkItem(async task =>
+                {
                     var jsonMsg = JsonDocument.Parse(message.Body).RootElement.ToObject<BlobRefreshMessage>();
                     var jsonMsg = JsonDocument.Parse(message.Body).RootElement.ToObject<BlobRefreshMessage>();
                     if (!string.IsNullOrWhiteSpace($"{jsonMsg.root}") && !string.IsNullOrWhiteSpace($"{jsonMsg.name}"))
                     if (!string.IsNullOrWhiteSpace($"{jsonMsg.root}") && !string.IsNullOrWhiteSpace($"{jsonMsg.name}"))
                     {
                     {
@@ -2376,12 +2384,14 @@ namespace TEAMModelOS.Function
                         }
                         }
                     }
                     }
                 });
                 });
-            } catch { } finally
-            { 
+            }
+            catch { }
+            finally
+            {
                 // Complete the message
                 // Complete the message
                 await messageActions.CompleteMessageAsync(message);
                 await messageActions.CompleteMessageAsync(message);
             }
             }
-           
+
         }
         }
         /// <summary>
         /// <summary>
         /// 統測評量開始結束
         /// 統測評量開始結束
@@ -2433,7 +2443,8 @@ namespace TEAMModelOS.Function
         public async Task JointEventFunc(
         public async Task JointEventFunc(
             [ServiceBusTrigger("%Azure:ServiceBus:ActiveTask%", "jointevent-schedule", Connection = "Azure:ServiceBus:ConnectionString")]
             [ServiceBusTrigger("%Azure:ServiceBus:ActiveTask%", "jointevent-schedule", Connection = "Azure:ServiceBus:ConnectionString")]
             ServiceBusReceivedMessage message,
             ServiceBusReceivedMessage message,
-            ServiceBusMessageActions messageActions)
+            ServiceBusMessageActions messageActions,
+            ExecutionContext context)
         {
         {
             _logger.LogInformation("Message ID: {id}", message.MessageId);
             _logger.LogInformation("Message ID: {id}", message.MessageId);
             _logger.LogInformation("Message Body: {body}", message.Body);
             _logger.LogInformation("Message Body: {body}", message.Body);
@@ -2441,6 +2452,21 @@ namespace TEAMModelOS.Function
             var jsonMsg = JsonDocument.Parse(message.Body).RootElement;
             var jsonMsg = JsonDocument.Parse(message.Body).RootElement;
             try
             try
             {
             {
+                //多國語字典
+                //string rootPath = _environment.ContentRootPath;
+                //List<string> langList = new List<string>() { "en-us", "zh-cn", "zh-tw" };
+                //Dictionary<string, JObject> langDic = new Dictionary<string, JObject>();
+                //foreach (string langCode in langList)
+                //{
+                //    string path = Path.Combine(rootPath, $"Lang/{langCode}.json");
+                //    if (File.Exists(path))
+                //    {
+                //        string jsonContent = await File.ReadAllTextAsync(path);
+                //        JObject jsonObject = JObject.Parse(jsonContent);
+                //        langDic.Add(langCode, jsonObject);
+                //    }
+                //}
+
                 jsonMsg.TryGetProperty("jointEventId", out JsonElement jointEventId);
                 jsonMsg.TryGetProperty("jointEventId", out JsonElement jointEventId);
                 jsonMsg.TryGetProperty("jointScheduleId", out JsonElement jointScheduleId);
                 jsonMsg.TryGetProperty("jointScheduleId", out JsonElement jointScheduleId);
                 jsonMsg.TryGetProperty("progress", out JsonElement progress);
                 jsonMsg.TryGetProperty("progress", out JsonElement progress);
@@ -2452,7 +2478,7 @@ namespace TEAMModelOS.Function
                 bool updFlg = false;
                 bool updFlg = false;
                 string code = "JointEvent";
                 string code = "JointEvent";
                 var client = _azureCosmos.GetCosmosClient();
                 var client = _azureCosmos.GetCosmosClient();
-                
+
                 JointEvent jointEvent = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<JointEvent>(jointEventId.ToString(), new PartitionKey($"{code}"));
                 JointEvent jointEvent = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<JointEvent>(jointEventId.ToString(), new PartitionKey($"{code}"));
                 if (jointEvent != null)
                 if (jointEvent != null)
                 {
                 {
@@ -2529,6 +2555,57 @@ namespace TEAMModelOS.Function
                                 }
                                 }
                                 //寄發Email
                                 //寄發Email
                                 ///取得收信者Email ※ jointCourse.creatorEmail
                                 ///取得收信者Email ※ jointCourse.creatorEmail
+                                //List<dynamic> users = new List<dynamic>();
+                                //if (jointEventSchedule.type.Equals("exam"))
+                                //{
+                                //    //一般競賽 ※挑戰賽 名單架構確定後再取
+                                //    if (jointEventSchedule.examType.Equals("regular"))
+                                //    {
+                                //        await foreach (var jc in client.GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetItemQueryStreamIteratorSql(queryText: $"SELECT DISTINCT c.creatorId, c.creatorName, c.creatorEmail FROM c WHERE c.jointEventId = '{jointEvent.id}' ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"JointCourse") }))
+                                //        {
+                                //            using var json = await JsonDocument.ParseAsync(jc.Content);
+                                //            if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
+                                //            {
+                                //                foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
+                                //                {
+                                //                    EmailUser user = new EmailUser();
+                                //                    user.tmid = (obj.TryGetProperty("creatorId", out JsonElement _creatorId)) ? _creatorId.GetString() : string.Empty;
+                                //                    user.name = (obj.TryGetProperty("creatorName", out JsonElement _creatorName)) ? _creatorName.GetString() : string.Empty;
+                                //                    user.email = (obj.TryGetProperty("creatorEmail", out JsonElement _creatorEmail)) ? _creatorEmail.GetString() : string.Empty;
+                                //                    if (!string.IsNullOrWhiteSpace(user.tmid) && !string.IsNullOrWhiteSpace(user.email))
+                                //                    {
+                                //                        users.Add(user);
+                                //                    }
+                                //                }
+                                //            }
+                                //        }
+                                //    }
+                                //}
+                                //if (users.Count > 0)
+                                //{
+                                //    //取得模板ID ※國際站就用繁體,大陸站就用簡體 [待定]
+                                //    string location = Environment.GetEnvironmentVariable("Option:Location");
+                                //    string tid = (location.Contains("China")) ? "" : "d-833d40ac6397414b852b91e2fa45850a";
+                                //    string lang = (location.Contains("China")) ? "zh-cn" : "zh-tw";
+                                //    //取得通知內文
+                                //    string mailTitle = string.Empty;
+                                //    string mailBody = string.Empty;
+                                //    JObject jsonObject = langDic[lang];
+                                //    if (jsonObject.TryGetValue("joint-schedule-start", out JToken msgToken))
+                                //    {
+                                //        JArray msgArray = (JArray)msgToken;
+                                //        mailTitle = msgArray[0].ToString();
+                                //        mailBody = $"{msgArray[1].ToString()}";
+                                //    }
+                                //    foreach (dynamic user in users)
+                                //    {
+                                //        if (!string.IsNullOrWhiteSpace(tid)) //※大陸站無模板,暫時不發
+                                //        {
+                                //            mailBody = mailBody.Replace("{tmdname}", user.name).Replace("{event}", jointEventSchedule.name);
+                                //            await _coreAPIHttpService.SendMail(new Dictionary<string, object> { { "to", user.email }, { "tid", tid }, { "vars", new { name = user.name } } }, location, _configuration);
+                                //        }
+                                //    }
+                                //}
                                 break;
                                 break;
                             case "finish":
                             case "finish":
                                 string pk = string.Format("{0}{1}{2}{3}{4}{5}{6}", "JointEvent", "-", $"{jointEventId}", "-", "schedule", "-", "going");
                                 string pk = string.Format("{0}{1}{2}{3}{4}{5}{6}", "JointEvent", "-", $"{jointEventId}", "-", "schedule", "-", "going");
@@ -2584,5 +2661,11 @@ namespace TEAMModelOS.Function
             //await _dingDing.SendBotMsg($"ServiceBus,RefreshBlob:\n容器名:{name}\n文件夹:{u}\n计算时长:{dis}\n文件夹大小:{blobsize}", GroupNames.醍摩豆服務運維群組);
             //await _dingDing.SendBotMsg($"ServiceBus,RefreshBlob:\n容器名:{name}\n文件夹:{u}\n计算时长:{dis}\n文件夹大小:{blobsize}", GroupNames.醍摩豆服務運維群組);
         }
         }
 
 
+        private class EmailUser
+        {
+            public string tmid { get; set; }
+            public string name { get; set; }
+            public string email { get; set; }
+        }
     }
     }
 }
 }

+ 22 - 0
TEAMModelOS.Function/IESTimerTrigger.cs

@@ -6,6 +6,7 @@ using Microsoft.Extensions.Logging;
 using TEAMModelOS.SDK.DI;
 using TEAMModelOS.SDK.DI;
 using TEAMModelOS.SDK;
 using TEAMModelOS.SDK;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Extension;
+using TEAMModelOS.SDK.Models.Service.BI;
 
 
 namespace TEAMModelOS.Function
 namespace TEAMModelOS.Function
 {
 {
@@ -101,5 +102,26 @@ namespace TEAMModelOS.Function
                 _logger.LogInformation($"Next timer schedule at: {myTimer.ScheduleStatus.Next}");
                 _logger.LogInformation($"Next timer schedule at: {myTimer.ScheduleStatus.Next}");
             }
             }
         }
         }
+
+        /// <summary>
+        /// 每天執行 取得IOT TeachingData 並統計昨日每校Redis資料 執行時間:每日凌晨1時1分
+        /// </summary>
+        [Function("BICrtDailyAnal")]
+        //0 1 0 * * * 一天中00的第 1 分钟
+        //0 1 * * * * 一天中每小时的第 1 分钟
+        //0 */10 * * * *  每五分钟一次
+        public async Task BICreatDailyAnalData([TimerTrigger("0 1 1 * * *")] TimerInfo myTimer, ILogger log)
+        {
+            var _azureCosmosClient = _azureCosmos.GetCosmosClient();
+            var _azureCosmosClientCsv2 = _azureCosmos.GetCosmosClient(name: "CoreServiceV2");
+            var _azureCosmosClientCsv2CnRead = _azureCosmos.GetCosmosClient(name: "CoreServiceV2CnRead");
+            var datetime = DateTimeOffset.UtcNow.AddHours(-12); //統計昨天的數據
+            var y = $"{datetime.Year}";
+            var m = datetime.Month >= 10 ? $"{datetime.Month}" : $"0{datetime.Month}";
+            var d = datetime.Day >= 10 ? $"{datetime.Day}" : $"0{datetime.Day}";
+            //生成學校IOT數據
+            await BIProdAnalysis.BICreatDailyAnalData(_azureRedis, _azureCosmosClient, _azureCosmosClientCsv2, _azureCosmosClientCsv2CnRead, _dingDing, y, m, d);
+            //刪除三個月以前的Redis數據 [待做]
+        }
     }
     }
 }
 }

文件差異過大導致無法顯示
+ 3 - 1
TEAMModelOS.Function/Lang/en-us.json


+ 3 - 1
TEAMModelOS.Function/Lang/zh-cn.json

@@ -29,5 +29,7 @@
   "blob-space-school-notify": [ "剩余空间不足", "亲爱的{schoolName}管理员{tmdname}您好,提醒您贵校剩余空间不足{percent}%,请联系官方客服购买空间,详情请登入IES(teammodel.net)查看,如果已经扩容请忽略此通知。" ],
   "blob-space-school-notify": [ "剩余空间不足", "亲爱的{schoolName}管理员{tmdname}您好,提醒您贵校剩余空间不足{percent}%,请联系官方客服购买空间,详情请登入IES(teammodel.net)查看,如果已经扩容请忽略此通知。" ],
   "blob-space-private-notify": [ "剩余空间不足", "亲爱的{tmdname}您好,提醒您的帐号{tmdid}授权的剩余空间不足{percent}%,请联系学校管理员配置或是购买个人空间,如果已经扩容请忽略此通知。" ],
   "blob-space-private-notify": [ "剩余空间不足", "亲爱的{tmdname}您好,提醒您的帐号{tmdid}授权的剩余空间不足{percent}%,请联系学校管理员配置或是购买个人空间,如果已经扩容请忽略此通知。" ],
   "pdf-gen-notify-higher60": [ "PDF报告生成通知", "{tmdname}您好,{taskName}的PDF报告已经生成,总耗时(包含等待和生成时间){totalTime}秒,报告生成平均耗时{avgTime}秒,单个报告生成最长耗时{maxTime}秒,单个报告最短耗时{minTime}秒,生成成功{statusOk}个,生成失败{statusFailed}个" ],
   "pdf-gen-notify-higher60": [ "PDF报告生成通知", "{tmdname}您好,{taskName}的PDF报告已经生成,总耗时(包含等待和生成时间){totalTime}秒,报告生成平均耗时{avgTime}秒,单个报告生成最长耗时{maxTime}秒,单个报告最短耗时{minTime}秒,生成成功{statusOk}个,生成失败{statusFailed}个" ],
-  "pdf-gen-notify-below60": [ "PDF报告生成通知", "{tmdname}您好,{taskName}的PDF报告已经生成,总耗时(包含等待和生成时间){totalTime}秒,报告生成平均耗时{avgTime}秒,生成成功{statusOk}个,生成失败{statusFailed}个。以下是生成报告的详情:", "{studentName}(状态:{status},等待:{wait}秒,耗时:{cost}秒,总耗时:{total}秒)。" ]
+  "pdf-gen-notify-below60": [ "PDF报告生成通知", "{tmdname}您好,{taskName}的PDF报告已经生成,总耗时(包含等待和生成时间){totalTime}秒,报告生成平均耗时{avgTime}秒,生成成功{statusOk}个,生成失败{statusFailed}个。以下是生成报告的详情:", "{studentName}(状态:{status},等待:{wait}秒,耗时:{cost}秒,总耗时:{total}秒)。" ],
+  "joint-schedule-start": [ "活动行程开始通知", "亲爱的{tmdname}老师,提醒您{event}活动已经开始。" ],
+  "joint-schedule-end": [ "活动行程结束通知", "亲爱的{tmdname}老师,提醒您{event}活动已经结束。" ]
 }
 }

+ 3 - 1
TEAMModelOS.Function/Lang/zh-tw.json

@@ -29,5 +29,7 @@
   "blob-space-school-notify": [ "剩餘空間不足", "親愛的{schoolName}管理員{tmdname}您好,提醒您貴校剩餘空間不足{percent}%,請聯繫官方客服購買空間,詳情請登入IES(teammodel.net)查看,如果已經擴容請忽略此通知。" ],
   "blob-space-school-notify": [ "剩餘空間不足", "親愛的{schoolName}管理員{tmdname}您好,提醒您貴校剩餘空間不足{percent}%,請聯繫官方客服購買空間,詳情請登入IES(teammodel.net)查看,如果已經擴容請忽略此通知。" ],
   "blob-space-private-notify": [ "剩餘空間不足", "親愛的{tmdname}您好,提醒您的帳號{tmdid}授權的剩餘空間不足{percent}%,請聯繫學校管理員配置或是購買個人空間,如果已經擴容請忽略此通知。" ],
   "blob-space-private-notify": [ "剩餘空間不足", "親愛的{tmdname}您好,提醒您的帳號{tmdid}授權的剩餘空間不足{percent}%,請聯繫學校管理員配置或是購買個人空間,如果已經擴容請忽略此通知。" ],
   "pdf-gen-notify-higher60": [ "PDF報告生成通知", "{tmdname}您好,{taskName}的PDF報告已經生成,總耗時(包含等待和生成時間){totalTime}秒,報告產生平均耗時{avgTime}秒,單一報告產生最長耗時{maxTime}秒,單一報告最短耗時{minTime}秒,產生成功{statusOk}個,產生失敗{statusFailed}個" ],
   "pdf-gen-notify-higher60": [ "PDF報告生成通知", "{tmdname}您好,{taskName}的PDF報告已經生成,總耗時(包含等待和生成時間){totalTime}秒,報告產生平均耗時{avgTime}秒,單一報告產生最長耗時{maxTime}秒,單一報告最短耗時{minTime}秒,產生成功{statusOk}個,產生失敗{statusFailed}個" ],
-  "pdf-gen-notify-below60": [ "PDF报告生成通知", "{tmdname}您好,{taskName}的PDF报告已经生成,总耗时(包含等待和生成时间){totalTime}秒,报告生成平均耗时{avgTime}秒,生成成功{statusOk}个,生成失败{statusFailed}个。以下是生成报告的详情:", "{studentName}(状态:{status},等待:{wait}秒,耗时:{cost}秒,总耗时:{total}秒)。" ]
+  "pdf-gen-notify-below60": [ "PDF报告生成通知", "{tmdname}您好,{taskName}的PDF报告已经生成,总耗时(包含等待和生成时间){totalTime}秒,报告生成平均耗时{avgTime}秒,生成成功{statusOk}个,生成失败{statusFailed}个。以下是生成报告的详情:", "{studentName}(状态:{status},等待:{wait}秒,耗时:{cost}秒,总耗时:{total}秒)。" ],
+  "joint-schedule-start": [ "活動行程開始通知", "親愛的{tmdname}老師,提醒您{event}活動已經開始。" ],
+  "joint-schedule-end": [ "活動行程結束通知", "親愛的{tmdname}老師,提醒您{event}活動已經結束。" ]
 }
 }

+ 1 - 1
TEAMModelOS/Controllers/Teacher/JointEventController.cs

@@ -399,7 +399,7 @@ namespace TEAMModelOS.Controllers.Common
                         jointEvent.schedule.Add(jointEventSchedule);
                         jointEvent.schedule.Add(jointEventSchedule);
                     }
                     }
                     //製作Schedule progress更新訊息(active-task)
                     //製作Schedule progress更新訊息(active-task)
-                    bool sendScheduleMsg = (!startTimeOld.Equals(jointEventSchedule.startTime) || endTimeOld.Equals(jointEventSchedule.endTime) ) ? true : false; //是否發送變更Schedule.progress訊息
+                    bool sendScheduleMsg = (!startTimeOld.Equals(jointEventSchedule.startTime) || !endTimeOld.Equals(jointEventSchedule.endTime) ) ? true : false; //是否發送變更Schedule.progress訊息
                     if(sendScheduleMsg)
                     if(sendScheduleMsg)
                     {
                     {
                         var msg = new ServiceBusMessage(new { jointEventId = $"{jointEvent.id}", jointScheduleId = $"{jointEventSchedule.id}", progress = jointEventSchedule.progress }.ToJsonString());
                         var msg = new ServiceBusMessage(new { jointEventId = $"{jointEvent.id}", jointScheduleId = $"{jointEventSchedule.id}", progress = jointEventSchedule.progress }.ToJsonString());

+ 14 - 0
TEAMModelOS/Controllers/XTest/TestController.cs

@@ -2558,6 +2558,20 @@ namespace TEAMModelOS.Controllers
             }
             }
         }
         }
 
 
+        //寄送Mail測試
+        [HttpPost("test-sendmail")]
+        public async Task<IActionResult> TestSendMail(JsonElement json)
+        {
+            string mail = "jeff@habook.com.tw";
+                          
+            string tid = "d-833d40ac6397414b852b91e2fa45850a"; //活動報名成功通知模板
+            string name = "Jeff";
+            string location = "Global";
+            await _coreAPIHttpService.SendMail(new Dictionary<string, object> { { "to", mail }, { "tid", tid }, { "vars", new { name = name } } }, location, _configuration);
+
+            return Ok();
+        }
+
         /*
         /*
         //自主學習綱領 資料架構測試
         //自主學習綱領 資料架構測試
         [HttpPost("test-selflearn-structure")]
         [HttpPost("test-selflearn-structure")]