using Azure.Cosmos; using Azure.Messaging.ServiceBus; using Microsoft.Azure.Documents; using System; using System.Collections.Generic; using System.Linq; 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.Models.Service; using HTEXLib.COMM.Helpers; using Microsoft.Extensions.Configuration; using DocumentFormat.OpenXml.Office2013.Excel; using DocumentFormat.OpenXml.Vml; using TEAMModelOS.SDK.Models.Service.BI; namespace TEAMModelOS.FunctionV4 { public static class TriggerVote { public static async Task Trigger(CoreAPIHttpService _coreAPIHttpService, AzureServiceBusFactory _serviceBus, AzureStorageFactory _azureStorage, DingDing _dingDing, CosmosClient client, JsonElement input, TriggerData tdata, AzureRedisFactory _azureRedis, IConfiguration _configuration) { try { if ((tdata.status != null && tdata.status.Value == 404) ) { await client.GetContainer(Constant.TEAMModelOS, "Common").DeleteItemStreamAsync(tdata.id, new PartitionKey(tdata.code)); ActivityList data = input.ToObject(); // await IESActivityService. DeleteActivity(_coreAPIHttpService, client, _dingDing, data); _azureRedis.GetRedisClient(8).KeyDelete($"Vote:Record:{tdata.id}"); _azureRedis.GetRedisClient(8).KeyDelete($"Vote:Count:{tdata.id}"); var table_cancel = _azureStorage.GetCloudTableClient().GetTableReference("ChangeRecord"); List records = await table_cancel.FindListByDict(new Dictionary() { { "RowKey", tdata.id } }); foreach (var record in records) { try { await table_cancel.DeleteSingle(record.PartitionKey, record.RowKey); await _serviceBus.GetServiceBusClient().CancelMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), record.sequenceNumber); } catch (Exception) { continue; } } await BIStats.SetTypeAddStats(client, _dingDing, tdata.school, "Vote", -1, careDate: tdata.startTime);//BI统计增/减量 return; } var table = _azureStorage.GetCloudTableClient().GetTableReference("ChangeRecord"); 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; } // await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}投票活动【{tdata.name}-{tdata.id}-ttl={tdata.ttl}】正在操作", GroupNames.醍摩豆服務運維群組); Vote vote = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync(tdata.id, new Azure.Cosmos.PartitionKey($"{tdata.code}")); if (vote != null) { string PartitionKey = string.Format("{0}{1}{2}", vote.code, "-", vote.progress); List voteRecords = await table.FindListByDict(new Dictionary() { { "RowKey", tdata.id }, { "PartitionKey", PartitionKey } }); switch (vote.progress) { case "pending": var messageVote = new ServiceBusMessage(new { id = tdata.id, progress = "going", code = tdata.code }.ToJsonString()); messageVote.ApplicationProperties.Add("name", "Vote"); if (voteRecords.Count > 0) { long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), messageVote, DateTimeOffset.FromUnixTimeMilliseconds(tdata.startTime)); try { await _serviceBus.GetServiceBusClient().CancelMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), voteRecords[0].sequenceNumber); } catch (Exception) { } voteRecords[0].sequenceNumber = start; await table.SaveOrUpdate(voteRecords[0]); } else { long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), messageVote, DateTimeOffset.FromUnixTimeMilliseconds(tdata.startTime)); ChangeRecord changeRecord = new ChangeRecord { RowKey = tdata.id, PartitionKey = PartitionKey, sequenceNumber = start, msgId = messageVote.MessageId }; await table.Save(changeRecord); } break; case "going": List<(string pId, List gid)> ps = new List<(string pId, List gid)>(); if (vote.groupLists.Count > 0) { var group = vote.groupLists; foreach (var keys in group) { foreach (KeyValuePair> pp in keys) { ps.Add((pp.Key, pp.Value)); } } } List classes = ExamService.getClasses(vote.classes, vote.stuLists); (List tmdIds, List classLists) = await GroupListService.GetMemberByListids(_coreAPIHttpService, client, _dingDing, classes, vote.school, ps); var addStudentsCls = tmdIds.FindAll(x => x.type == 2); var addTmdidsCls = tmdIds.FindAll(x => x.type == 1); //await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}投票活动" + // $"{tmdids.ToJsonString()}\n" + // $"{students.ToJsonString()}\n" + // $"{classLists.ToJsonString()}\n" + // $"{classes.ToJsonString()}\n", GroupNames.醍摩豆服務運維群組); List tmds = new List(); if (addTmdidsCls.IsNotEmpty()) { tmds.AddRange(addTmdidsCls.Select(x => x.id).ToList()); } /* List stuActivities = new List(); List tmdActivities = new List(); List tchActivities = new List(); List sub = new(); if (vote.tchLists.Count == 0) { if (vote.targets.Count > 0) { foreach (var course in vote.targets) { var info = course.ToObject>(); if (info.Count > 1) { sub.Add(info[0]); } } } } if (tmds.IsNotEmpty()) { tmds.ForEach(x => { HashSet classIds = new HashSet(); classLists.ForEach(z => { z.members.ForEach(y => { if (y.id.Equals(x) && y.type == 1) { classIds.Add(z.id); } }); }); tmdActivities.Add(new StuActivity { pk = "Activity", id = vote.id, code = $"Activity-{x}", type = "Vote", name = vote.name, startTime = vote.startTime, endTime = vote.endTime, scode = vote.code, scope = vote.scope, school = vote.school, creatorId = vote.creatorId, subjects = sub, blob = null, owner = vote.owner, createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), taskStatus = -1, classIds = classIds.ToList() }); }); } if (addStudentsCls.IsNotEmpty()) { addStudentsCls.ForEach(x => { HashSet classIds = new HashSet(); classLists.ForEach(z => { z.members.ForEach(y => { if (y.id.Equals(x.id) && y.code.Equals(vote.school) && y.type == 2) { classIds.Add(z.id); } }); }); stuActivities.Add(new StuActivity { pk = "Activity", id = vote.id, code = $"Activity-{x.code.Replace("Base-", "")}-{x.id}", type = "Vote", name = vote.name, startTime = vote.startTime, endTime = vote.endTime, scode = vote.code, scope = vote.scope, school = vote.school, creatorId = vote.creatorId, subjects = sub, blob = null, owner = vote.owner, createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), taskStatus = -1, classIds = classIds.ToList() }); }); } */ (List tchList, List classInfos) = await GroupListService.GetMemberByListids(_coreAPIHttpService, client, _dingDing, vote.tchLists, vote.school, ps); (string standard, List tmdids, string school, List update, int statistics) list = (null, null, null, new List { StatisticsService.TeacherVote }, 0); if (tchList.IsNotEmpty()) { list.tmdids = tchList.Select(x => x.id).ToList(); School school = null; if (!string.IsNullOrEmpty(vote.school)) { school = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync(vote.school, new Azure.Cosmos.PartitionKey("Base")); list.school = school.id; list.standard = school.standard; } /* tchList.ForEach(x => { HashSet classIds = new HashSet(); classInfos.ForEach(z => { z.members.ForEach(y => { if (y.id.Equals(x.id) && y.type == 1) { classIds.Add(z.id); } }); }); tchActivities.Add(new StuActivity { pk = "Activity", id = vote.id, code = $"Activity-{x.id}", type = "Vote", name = vote.name, startTime = vote.startTime, endTime = vote.endTime, scode = vote.code, scope = vote.scope, school = vote.school, creatorId = vote.creatorId, subjects = new List { "" }, blob = null, owner = vote.owner, createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), taskStatus = -1, classIds = classIds.ToList() }); }); */ } // await IESActivityService.SaveStuActivity(client, _dingDing, stuActivities, tmdActivities, tchActivities); await StatisticsService.SendServiceBus(list, _configuration, _serviceBus, client); //向学生或醍摩豆账号发起通知 #region //Notice notice = new Notice() //{ // creation = vote.startTime, // expire = vote.endTime, // creatorId = vote.creatorId, // stuids = students, // tmdids = tmdids, // type = "notice",//问卷参加参加通知 // priority = "normal", // msgId=vote.id, // school = vote.school, // scope = vote.scope, // //data = new { }.ToJsonString() // body = new Body { sid = vote.id, scode = vote.code, spk = vote.pk, biztype = "vote-join" } //}; //var messageBlob = new ServiceBusMessage(notice.ToJsonString()); //messageBlob.ApplicationProperties.Add("name", "Notice"); //await _serviceBus.GetServiceBusClient().SendMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:NoticeTask"), messageBlob); #endregion var messageVoteEnd = new ServiceBusMessage(new { id = tdata.id, progress = "finish", code = tdata.code }.ToJsonString()); messageVoteEnd.ApplicationProperties.Add("name", "Vote"); /* string pk = string.Format("{0}{1}{2}", vote.code, "-", "pending"); await table.DeleteSingle(pk, tdata.id);*/ if (voteRecords.Count > 0) { long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), messageVoteEnd, DateTimeOffset.FromUnixTimeMilliseconds(tdata.endTime)); try { await _serviceBus.GetServiceBusClient().CancelMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), voteRecords[0].sequenceNumber); } catch (Exception) { } voteRecords[0].sequenceNumber = end; await table.SaveOrUpdate(voteRecords[0]); } else { long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), messageVoteEnd, DateTimeOffset.FromUnixTimeMilliseconds(tdata.endTime)); ChangeRecord changeRecord = new() { RowKey = tdata.id, PartitionKey = PartitionKey, sequenceNumber = end, msgId = messageVoteEnd.MessageId }; await table.Save(changeRecord); } #if DEBUG await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}投票活动{tdata.id}将于:{tdata.endTime}完成并结算!", GroupNames.醍摩豆服務運維群組); #endif break; case "finish": #if DEBUG await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}投票活动{tdata.id}开始结算{tdata.endTime}!", GroupNames.醍摩豆服務運維群組); #endif //获取投票活动的所有投票记录 var records = await _azureRedis.GetRedisClient(8).HashGetAllAsync($"Vote:Record:{vote.id}"); //获取投票活动的选项及投票数 var counts = _azureRedis.GetRedisClient(8).SortedSetRangeByScoreWithScores($"Vote:Count:{vote.id}"); List countcds = new List(); if (counts != null && counts.Length > 0) { foreach (var count in counts) { countcds.Add(new { code = count.Element.ToString(), count = (int)count.Score }); } } List> tasks = new(); List recordsBlob = new(); foreach (var rcd in records) { var value = rcd.Value.ToString().ToObject(); recordsBlob.Add(value); } //分组每个人的 var gp = recordsBlob.GroupBy(x => x.userid).Select(x => new { key = x.Key, list = x.ToList() }); foreach (var g in gp) { tasks.Add(_azureStorage.GetBlobContainerClient(blobcntr).UploadFileByContainer(g.list.ToJsonString(), "vote", $"{vote.id}/urecord/{g.key}.json")); } //处理活动方的记录, string url = $"/vote/{vote.id}/record.json"; tasks.Add(_azureStorage.GetBlobContainerClient(blobcntr).UploadFileByContainer(new { options = countcds, records = recordsBlob }.ToJsonString(), "vote", $"{vote.id}/record.json")); //处理投票者的记录 List<(string pId, List gid)> gls = new List<(string pId, List gid)>(); if (vote.groupLists.Count > 0) { var group = vote.groupLists; foreach (var gro in group) { foreach (KeyValuePair> pp in gro) { gls.Add((pp.Key, pp.Value)); } } } //处理投票活动结束统计账户信息 List idsList = await GroupListService.GetFinishMemberInfo(_coreAPIHttpService, client, _dingDing, vote.school, vote.classes, vote.stuLists, vote.tchLists, gls); vote.staffIds = idsList; if (string.IsNullOrEmpty(vote.recordUrl)) { vote.recordUrl = url; await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(vote, vote.id, new Azure.Cosmos.PartitionKey(vote.code)); } else { //异动,且已经有结算记录则不必再继续。 _azureRedis.GetRedisClient(8).KeyDelete($"Vote:Record:{vote.id}"); _azureRedis.GetRedisClient(8).KeyDelete($"Vote:Count:{vote.id}"); break; } await Task.WhenAll(tasks); /* string pkey = string.Format("{0}{1}{2}", vote.code, "-", "going"); await table.DeleteSingle(pkey, tdata.id);*/ break; } } } catch (CosmosException e) { await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-CosmosDB异常{e.Message}\n{e.StackTrace}\n{e.Status}", GroupNames.醍摩豆服務運維群組); } catch (Exception ex) { await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}投票活动异常{ex.Message}\n{ex.StackTrace}\n{input.ToJsonString()}\n{tdata.ToJsonString()}", GroupNames.醍摩豆服務運維群組); } } } }