using Azure.Cosmos; using Azure.Messaging.ServiceBus; using Azure.Storage.Blobs.Models; using Azure.Storage.Sas; using Microsoft.Azure.Documents; using System; using System.Collections.Generic; using System.Net.Http; using System.Text; using System.Text.Json; using System.Threading.Tasks; using TEAMModelOS.SDK.DI; using TEAMModelOS.SDK.Extension; using TEAMModelOS.SDK; using TEAMModelOS.SDK.Models; using TEAMModelOS.SDK.Models.Cosmos; using TEAMModelOS.SDK.Models.Cosmos.Common; using TEAMModelOS.SDK.Models.Cosmos.Common.Inner; using TEAMModelOS.SDK.Module.AzureBlob.Configuration; using TEAMModelOS.SDK.Models.Service; using HTEXLib.COMM.Helpers; using Microsoft.Extensions.Configuration; using System.Linq; namespace TEAMModelFunction { public class TriggerSurvey { public static async Task Trigger(AzureServiceBusFactory _serviceBus, AzureStorageFactory _azureStorage, DingDing _dingDing, CosmosClient client, Document input, TriggerData tdata, AzureRedisFactory _azureRedis, IConfiguration _configuration) { try { if ((tdata.status != null && tdata.status.Value == 404) || tdata.ttl > 0) { _azureRedis.GetRedisClient(8).KeyDelete($"Survey:Record:{tdata.id}"); _azureRedis.GetRedisClient(8).KeyDelete($"Survey:Submit:{tdata.id}"); return; } var adid = tdata.id; var adcode = ""; string blobcntr = null; if (tdata.scope.Equals("school")) { adcode = $"Activity-{tdata.school}"; blobcntr = tdata.school; } else { adcode = $"Activity-{tdata.creatorId}"; blobcntr = tdata.creatorId; } Survey survey = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync(input.Id, new Azure.Cosmos.PartitionKey($"{tdata.code}")); if (survey != null) { string PartitionKey = string.Format("{0}{1}{2}", survey.code, "-", survey.progress); List changeRecords = await _azureStorage.FindListByDict(new Dictionary() { { "RowKey", input.Id }, { "PartitionKey", PartitionKey } }); switch (survey.progress) { case "pending": var messageSurvey = new ServiceBusMessage(new { id = input.Id, progress = "going", code = tdata.code }.ToJsonString()); messageSurvey.ApplicationProperties.Add("name", "Survey"); if (changeRecords.Count > 0) { await _serviceBus.GetServiceBusClient().cancelMessage(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), changeRecords[0].sequenceNumber); long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), messageSurvey, DateTimeOffset.FromUnixTimeMilliseconds(tdata.stime)); changeRecords[0].sequenceNumber = start; await _azureStorage.SaveOrUpdate(changeRecords[0]); } else { long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), messageSurvey, DateTimeOffset.FromUnixTimeMilliseconds(tdata.stime)); ChangeRecord changeRecord = new ChangeRecord { RowKey = input.Id, PartitionKey = PartitionKey, sequenceNumber = start, msgId = messageSurvey.MessageId }; await _azureStorage.Save(changeRecord); } break; case "going": List<(string pId, List gid)> ps = new List<(string pId, List gid)>(); if (survey.groupLists.Count > 0) { var group = survey.groupLists; foreach (var gp in group) { foreach (KeyValuePair> pp in gp) { ps.Add((pp.Key, pp.Value)); } } } List classes = ExamService.getClasses(survey.classes, survey.stuLists); (List tmdIds, List classLists) = await GroupListService.GetStutmdidListids(client, _dingDing, classes, survey.school); var addStudentsCls = tmdIds.FindAll(x => x.type == 2); var addTmdidsCls = tmdIds.FindAll(x => x.type == 1); #if DEBUG await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}问卷调查{tdata.id}写入学生表作为活动列表!", GroupNames.成都开发測試群組); #endif List stuActivities = new List(); List tmdActivities = new List(); List tchActivities = new List(); if (addTmdidsCls.IsNotEmpty()) { addTmdidsCls.ForEach(x => { tmdActivities.Add(new StuActivity { pk = "Activity", id = survey.id, code = $"Activity-{x.id}", type = "Survey", name = survey.name, startTime = survey.startTime, endTime = survey.endTime, scode = survey.code, scope = survey.scope, school = survey.school, creatorId = survey.creatorId, subjects = new List { "" }, blob = survey.blob, owner = survey.owner, createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), taskStatus = -1, classIds = classes }); }); } if (addStudentsCls.IsNotEmpty()) { addStudentsCls.ForEach(x => { stuActivities.Add(new StuActivity { pk = "Activity", id = survey.id, code = $"Activity-{x.code.Replace("Base-", "")}-{x.id}", type = "Survey", name = survey.name, startTime = survey.startTime, endTime = survey.endTime, scode = survey.code, scope = survey.scope, school = survey.school, creatorId = survey.creatorId, subjects = new List { "" }, blob = survey.blob, owner = survey.owner, createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), taskStatus = -1, classIds = classes }); }); } (List tchList, List classInfos) = await GroupListService.GetStutmdidListids(client, _dingDing, survey.tchLists, survey.school, ps); (string standard, List tmdids, string school, List update, int statistics) list = (null, null, null, new List { StatisticsService.TeacherSurvey }, 0); if (tchList.IsNotEmpty()) { list.tmdids = tchList.Select(x => x.id).ToList(); School school = null; if (!string.IsNullOrEmpty(survey.school)) { school = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync(survey.school, new Azure.Cosmos.PartitionKey("Base")); list.school = school.id; list.standard = school.standard; } tchList.ForEach(x => { tchActivities.Add(new StuActivity { pk = "Activity", id = survey.id, code = $"Activity-{x.id}", type = "Survey", name = survey.name, startTime = survey.startTime, endTime = survey.endTime, scode = survey.code, scope = survey.scope, school = survey.school, creatorId = survey.creatorId, subjects = new List { "" }, blob = survey.blob, owner = survey.owner, createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), taskStatus = -1, classIds = survey.tchLists }); }); } await ActivityService.SaveStuActivity(client, _dingDing, stuActivities, tmdActivities, tchActivities); await StatisticsService.SendServiceBus(list, _configuration, _serviceBus, client); //向学生或醍摩豆账号发起通知 #region //Notice notice = new Notice() //{ // creation = survey.startTime, // expire = survey.endTime, // creatorId = survey.creatorId, // stuids = students, // tmdids = tmdids, // type = "notice",//问卷参加参加通知 // priority = "normal", // //data = new { }.ToJsonString() // msgId = survey.id, // school = survey.school, // scope = survey.scope, // body = new Body { sid = survey.id, scode = survey.code, spk = survey.pk, biztype = "survey-join" } //}; //var messageBlob = new ServiceBusMessage(notice.ToJsonString()); //messageBlob.ApplicationProperties.Add("name", "Notice"); //await _serviceBus.GetServiceBusClient().SendMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), messageBlob); #endregion #if DEBUG await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}问卷调查{tdata.id}写入完成!", GroupNames.成都开发測試群組); #endif var messageSurveyEnd = new ServiceBusMessage(new { id = input.Id, progress = "finish", code = tdata.code }.ToJsonString()); messageSurveyEnd.ApplicationProperties.Add("name", "Survey"); if (changeRecords.Count > 0) { long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), messageSurveyEnd, DateTimeOffset.FromUnixTimeMilliseconds(tdata.etime)); await _serviceBus.GetServiceBusClient().cancelMessage(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), changeRecords[0].sequenceNumber); changeRecords[0].sequenceNumber = end; await _azureStorage.SaveOrUpdate(changeRecords[0]); } else { long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), messageSurveyEnd, DateTimeOffset.FromUnixTimeMilliseconds(tdata.etime)); ChangeRecord changeRecord = new ChangeRecord { RowKey = input.Id, PartitionKey = PartitionKey, sequenceNumber = end, msgId = messageSurveyEnd.MessageId }; await _azureStorage.Save(changeRecord); } #if DEBUG await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}问卷调查{tdata.id}将于:{tdata.etime}完成并结算!", GroupNames.成都开发測試群組); #endif break; case "finish": #if DEBUG await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}问卷调查{tdata.id}开始结算{tdata.etime}!", GroupNames.成都开发測試群組); #endif var records = await _azureRedis.GetRedisClient(8).HashGetAllAsync($"Survey:Record:{survey.id}"); var submits = await _azureRedis.GetRedisClient(8).SetMembersAsync($"Survey:Submit:{survey.id}"); List recs = new List(); foreach (var rcd in records) { var value = rcd.Value.ToString().ToObject(); recs.Add(new { index = rcd.Name.ToString(), ans = value }); } List userids = new List(); foreach (var submit in submits) { var value = submit.ToString(); userids.Add(value); } List questionRecords = new List(); //结算每道题的答题情况 var ContainerClient = _azureStorage.GetBlobContainerClient(blobcntr); List> tasks = new List>(); //获取 List surveyRecords = new List(); try { List items = await ContainerClient.List($"survey/{survey.id}/urecord"); foreach (string item in items) { var Download = await _azureStorage.GetBlobContainerClient(blobcntr).GetBlobClient(item).DownloadAsync(); var json = await JsonDocument.ParseAsync(Download.Value.Content); var Record = json.RootElement.ToObject(); surveyRecords.Add(Record); } #if DEBUG await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}问卷调查问题结算数据{surveyRecords.ToJsonString()}", GroupNames.成都开发測試群組); #endif for (int index = 0; index < survey.answers.Count; index++) { string url = $"{survey.id}/qrecord/{index}.json"; QuestionRecord question = new QuestionRecord() { index = index }; foreach (SurveyRecord record in surveyRecords) { if (record.ans.Count == survey.answers.Count) { foreach (var an in record.ans[index]) { // if (question.opt.ContainsKey(an)) { if (question.opt[an] != null) { question.opt[an].Add(record.userid); } else { question.opt[an] = new HashSet() { record.userid }; } } else { if (survey.answers[index].Contains(an)) { //如果是客观题code question.opt.Add(an, new HashSet { record.userid }); } else { //如果不是客观code question.other[record.userid] = an; } } } } } questionRecords.Add(question); tasks.Add(_azureStorage.UploadFileByContainer(blobcntr, question.ToJsonString(), "survey", url)); } await Task.WhenAll(tasks); } catch (Exception ex) { await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}问卷调查问题结算异常{ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組); } var cods = new { records = recs, userids, question = questionRecords, urecord = surveyRecords }; //问卷整体情况 await _azureStorage.UploadFileByContainer(blobcntr, cods.ToJsonString(), "survey", $"{survey.id}/record.json"); if (string.IsNullOrEmpty(survey.recordUrl)) { survey.recordUrl = $"/survey/{survey.id}/record.json"; await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(survey, survey.id, new Azure.Cosmos.PartitionKey(survey.code)); } else { _azureRedis.GetRedisClient(8).KeyDelete($"Survey:Record:{survey.id}"); _azureRedis.GetRedisClient(8).KeyDelete($"Survey:Submit:{survey.id}"); break; } //更新结束状态 //data.progress = "finish"; //if (survey.scope .Equals("school")) //{ // await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync(data, data.id, new Azure.Cosmos.PartitionKey(data.code)); //} //else if (survey.scope .Equals("private")) //{ // await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync(data, data.id, new Azure.Cosmos.PartitionKey(data.code)); //} break; } } } catch (CosmosException e) { await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-CosmosDB异常{e.Message}\n{e.Status}", GroupNames.成都开发測試群組); } catch (Exception ex) { await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}问卷调查{ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組); } } } /** * {survey.id}/qrecord/{index}.json { "opt": { "A": [ "userid1", "userid2", "userid3" ], "B": [ "userid1", "userid2", "userid3" ] }, "other": { "userid1": "建议XXXX1", "userid2": "建议XXXX2" } } **/ }