|
@@ -31,6 +31,9 @@ using Microsoft.AspNetCore.Authorization;
|
|
|
using static TEAMModelBI.Models.Extension.GeoRegion;
|
|
|
using System.Diagnostics.Metrics;
|
|
|
using Microsoft.Azure.Cosmos.Table;
|
|
|
+using System.Net.Http.Json;
|
|
|
+using NotifyData = TEAMModelOS.SDK.CoreAPIHttpService.NotifyData;
|
|
|
+using Microsoft.Azure.Cosmos.Linq;
|
|
|
|
|
|
|
|
|
namespace TEAMModelBI.Controllers.BICommon
|
|
@@ -49,8 +52,9 @@ namespace TEAMModelBI.Controllers.BICommon
|
|
|
private readonly CoreAPIHttpService _coreAPIHttpService;
|
|
|
private readonly IWebHostEnvironment _environment; //读取文件
|
|
|
private readonly HttpClient _httpClient;
|
|
|
+ private readonly SnowflakeId _snowflakeId;
|
|
|
|
|
|
- public BINoticeController(AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage, IOptionsSnapshot<Option> option, IConfiguration configuration, AzureServiceBusFactory serviceBus, IHttpClientFactory http, CoreAPIHttpService coreAPIHttpService, IWebHostEnvironment hostingEnvironment, HttpClient httpClient)
|
|
|
+ public BINoticeController(AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage, IOptionsSnapshot<Option> option, IConfiguration configuration, AzureServiceBusFactory serviceBus, IHttpClientFactory http, CoreAPIHttpService coreAPIHttpService, IWebHostEnvironment hostingEnvironment, HttpClient httpClient, SnowflakeId snowflakeId)
|
|
|
{
|
|
|
_azureCosmos = azureCosmos;
|
|
|
_dingDing = dingDing;
|
|
@@ -62,6 +66,7 @@ namespace TEAMModelBI.Controllers.BICommon
|
|
|
_coreAPIHttpService = coreAPIHttpService;
|
|
|
_environment = hostingEnvironment;
|
|
|
_httpClient = httpClient;
|
|
|
+ _snowflakeId = snowflakeId;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
@@ -242,7 +247,7 @@ namespace TEAMModelBI.Controllers.BICommon
|
|
|
};
|
|
|
|
|
|
bINotice = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Common").CreateItemAsync<BINotice>(bINotice, new PartitionKey("BINotice"));
|
|
|
- if (isOnlySave.GetBoolean())
|
|
|
+ if (isOnlySave.GetBoolean())
|
|
|
{
|
|
|
//BI发送端外通知
|
|
|
_coreAPIHttpService.BIPushNotify(bINotice, new Dictionary<string, object> { { "tmdid", _tmdIds }, { "sendId", bINotice.crowdIds } }, _option.Location, _configuration, _dingDing);
|
|
@@ -305,13 +310,13 @@ namespace TEAMModelBI.Controllers.BICommon
|
|
|
|
|
|
//取得學區
|
|
|
string sqlArea = $"SELECT c.id, c.name FROM c ";
|
|
|
- string whereArea = string.Empty ;
|
|
|
+ string whereArea = string.Empty;
|
|
|
if (!string.IsNullOrWhiteSpace(reqAreaId))
|
|
|
{
|
|
|
- string wherePre = (!string.IsNullOrWhiteSpace(whereArea)) ? " AND " : string.Empty ;
|
|
|
+ string wherePre = (!string.IsNullOrWhiteSpace(whereArea)) ? " AND " : string.Empty;
|
|
|
whereArea += $"{wherePre} c.id = '{reqAreaId}' ";
|
|
|
}
|
|
|
- if(!string.IsNullOrWhiteSpace(whereArea))
|
|
|
+ if (!string.IsNullOrWhiteSpace(whereArea))
|
|
|
{
|
|
|
whereArea = $" WHERE {whereArea}";
|
|
|
sqlArea = sqlArea + whereArea;
|
|
@@ -332,12 +337,12 @@ namespace TEAMModelBI.Controllers.BICommon
|
|
|
string schId = item.GetProperty("id").ToString();
|
|
|
string schName = item.GetProperty("name").ToString();
|
|
|
string areaId = item.GetProperty("areaId").ToString();
|
|
|
- if(!schAreaDic.ContainsKey(schId))
|
|
|
+ if (!schAreaDic.ContainsKey(schId))
|
|
|
{
|
|
|
schAreaDic.Add(schId, areaId);
|
|
|
schNameDic.Add(schId, schName);
|
|
|
}
|
|
|
- if(!teacherCodes.Contains($"Teacher-{schId}"))
|
|
|
+ if (!teacherCodes.Contains($"Teacher-{schId}"))
|
|
|
{
|
|
|
teacherCodes.Add($"Teacher-{schId}");
|
|
|
}
|
|
@@ -351,7 +356,7 @@ namespace TEAMModelBI.Controllers.BICommon
|
|
|
if (!schAreaDic.ContainsKey(schId))
|
|
|
{
|
|
|
schAreaDic.Add(schId, areaId);
|
|
|
- if(!schNameDic.ContainsKey(schId)) schNameDic.Add(schId, schName);
|
|
|
+ if (!schNameDic.ContainsKey(schId)) schNameDic.Add(schId, schName);
|
|
|
}
|
|
|
}
|
|
|
//取得學校教師數
|
|
@@ -370,7 +375,7 @@ namespace TEAMModelBI.Controllers.BICommon
|
|
|
int tchCnt = item.Value;
|
|
|
string areaId = schAreaDic[schId];
|
|
|
AreaInfo areaInfo = areaInfos.Where(a => a.id.Equals(areaId)).FirstOrDefault();
|
|
|
- if(areaInfo != null)
|
|
|
+ if (areaInfo != null)
|
|
|
{
|
|
|
areaInfo.scCnt++;
|
|
|
areaInfo.tchCnt += tchCnt;
|
|
@@ -427,10 +432,10 @@ namespace TEAMModelBI.Controllers.BICommon
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- if(isGlobal)
|
|
|
+ if (isGlobal)
|
|
|
{
|
|
|
provinceId = string.Empty;
|
|
|
- if(countryId.Equals("TW"))
|
|
|
+ if (countryId.Equals("TW"))
|
|
|
{
|
|
|
foreach (KeyValuePair<string, regionbase> item in regionData.city[countryId][countryId.ToLower()])
|
|
|
{
|
|
@@ -446,7 +451,7 @@ namespace TEAMModelBI.Controllers.BICommon
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- if(regionData.province.ContainsKey(countryId) && !string.IsNullOrWhiteSpace(provinceId))
|
|
|
+ if (regionData.province.ContainsKey(countryId) && !string.IsNullOrWhiteSpace(provinceId))
|
|
|
{
|
|
|
provinceName = (regionData.province[countryId].ContainsKey(provinceId)) ? regionData.province[countryId][provinceId].name : string.Empty;
|
|
|
foreach (KeyValuePair<string, regionbase> item in regionData.city[countryId][provinceId])
|
|
@@ -454,13 +459,13 @@ namespace TEAMModelBI.Controllers.BICommon
|
|
|
geoIdNameDic.Add(item.Value.code, item.Value.name);
|
|
|
}
|
|
|
}
|
|
|
- if(isGlobal)
|
|
|
+ if (isGlobal)
|
|
|
{
|
|
|
- if(regionData.city.ContainsKey(countryId))
|
|
|
+ if (regionData.city.ContainsKey(countryId))
|
|
|
{
|
|
|
- if(countryId.ToLower().Equals("tw"))
|
|
|
+ if (countryId.ToLower().Equals("tw"))
|
|
|
{
|
|
|
- if(!string.IsNullOrWhiteSpace(cityId) && regionData.city[countryId][countryId.ToLower()].ContainsKey(cityId))
|
|
|
+ if (!string.IsNullOrWhiteSpace(cityId) && regionData.city[countryId][countryId.ToLower()].ContainsKey(cityId))
|
|
|
{
|
|
|
cityName = regionData.city[countryId][countryId.ToLower()][cityId].name;
|
|
|
}
|
|
@@ -468,7 +473,7 @@ namespace TEAMModelBI.Controllers.BICommon
|
|
|
}
|
|
|
} else
|
|
|
{
|
|
|
- if (regionData.city.ContainsKey(countryId) &&
|
|
|
+ if (regionData.city.ContainsKey(countryId) &&
|
|
|
!string.IsNullOrWhiteSpace(provinceId) && regionData.city[countryId].ContainsKey(provinceId) &&
|
|
|
!string.IsNullOrWhiteSpace(cityId) && regionData.city[countryId][provinceId].ContainsKey(cityId)
|
|
|
)
|
|
@@ -484,20 +489,20 @@ namespace TEAMModelBI.Controllers.BICommon
|
|
|
if (!string.IsNullOrWhiteSpace(sqlWhere)) sqlWhere += $" AND";
|
|
|
comeRemoveStr.ForEach(c => { countryName = countryName.Replace(c, ""); });
|
|
|
sqlWhere += $" CONTAINS(c.region, '{countryName}') ";
|
|
|
- groupKey = (isGlobal) ? "city" : "province";
|
|
|
+ groupKey = (isGlobal) ? "city" : "province";
|
|
|
}
|
|
|
if (!string.IsNullOrWhiteSpace(provinceName))
|
|
|
{
|
|
|
if (!string.IsNullOrWhiteSpace(sqlWhere)) sqlWhere += $" AND";
|
|
|
comeRemoveStr.ForEach(c => { provinceName = provinceName.Replace(c, ""); });
|
|
|
- sqlWhere += $" CONTAINS(c.province, '{provinceName}') ";
|
|
|
+ sqlWhere += $" CONTAINS(c.province, '{provinceName}') ";
|
|
|
groupKey = "city";
|
|
|
}
|
|
|
if (!string.IsNullOrWhiteSpace(cityName))
|
|
|
{
|
|
|
if (!string.IsNullOrWhiteSpace(sqlWhere)) sqlWhere += $" AND";
|
|
|
comeRemoveStr.ForEach(c => { cityName = cityName.Replace(c, ""); });
|
|
|
- sqlWhere += $" CONTAINS(c.city, '{cityName}') ";
|
|
|
+ sqlWhere += $" CONTAINS(c.city, '{cityName}') ";
|
|
|
groupKey = "name";
|
|
|
}
|
|
|
Dictionary<string, string> schGeoDic = new Dictionary<string, string>(); //key: schoolId val:統計的geoName
|
|
@@ -515,6 +520,7 @@ namespace TEAMModelBI.Controllers.BICommon
|
|
|
string schId = item.GetProperty("id").ToString();
|
|
|
string schName = item.GetProperty("name").ToString();
|
|
|
string geoName = item.GetProperty(groupKey).ToString();
|
|
|
+ comeRemoveStr.ForEach(c => { geoName = geoName.Replace(c, ""); });
|
|
|
if (!schGeoDic.ContainsKey(schId))
|
|
|
{
|
|
|
schGeoDic.Add(schId, geoName);
|
|
@@ -555,7 +561,7 @@ namespace TEAMModelBI.Controllers.BICommon
|
|
|
int tchCnt = item.Value;
|
|
|
string geoName = schGeoDic[schId];
|
|
|
AreaInfo geoInfo = geoInfos.Where(g => g.name.Equals(geoName)).FirstOrDefault();
|
|
|
- if(geoInfo == null)
|
|
|
+ if (geoInfo == null)
|
|
|
{
|
|
|
AreaInfo geoInfoCrt = new AreaInfo();
|
|
|
geoInfoCrt.id = (groupKey.Equals("city") || groupKey.Equals("province")) ? geoIdNameDic.FirstOrDefault(x => x.Value.Contains(geoName)).Key : schId;
|
|
@@ -590,7 +596,7 @@ namespace TEAMModelBI.Controllers.BICommon
|
|
|
public async Task<IActionResult> GetUnitTypes(JsonElement jsonElement)
|
|
|
{
|
|
|
var cosmosClient = _azureCosmos.GetCosmosClient();
|
|
|
- var coreCosmosClientCn = _azureCosmos.GetCosmosClient(name:"CoreServiceV2CnRead");
|
|
|
+ var coreCosmosClientCn = _azureCosmos.GetCosmosClient(name: "CoreServiceV2CnRead");
|
|
|
|
|
|
string type = (jsonElement.TryGetProperty("type", out JsonElement _type)) ? _type.GetString() : string.Empty; //教育機構類型 1:基礎教育機構(K-小學) 2:中等教育機構(國中、高中/職) 3:高等教育機構(大學、研究所) 4:其他
|
|
|
bool showSchool = (jsonElement.TryGetProperty("showSchool", out JsonElement _showSchool)) ? _showSchool.GetBoolean() : false; //是否列出學校
|
|
@@ -609,7 +615,7 @@ namespace TEAMModelBI.Controllers.BICommon
|
|
|
{
|
|
|
string schId = item.GetProperty("id").ToString();
|
|
|
string schName = item.GetProperty("name").ToString();
|
|
|
- int schType = item.GetProperty("type").GetInt32();
|
|
|
+ int schType = item.GetProperty("type").GetInt32();
|
|
|
iesSchIds.Add(schId);
|
|
|
if (!schTypeDic.ContainsKey(schId)) schTypeDic.Add(schId, schType.ToString());
|
|
|
if (!schNameDic.ContainsKey(schId)) schNameDic.Add(schId, schName);
|
|
@@ -669,7 +675,7 @@ namespace TEAMModelBI.Controllers.BICommon
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
- else if(!string.IsNullOrWhiteSpace(iesUnitType))
|
|
|
+ else if (!string.IsNullOrWhiteSpace(iesUnitType))
|
|
|
{
|
|
|
switch (iesUnitType) //1 普教,2 高职教
|
|
|
{
|
|
@@ -705,7 +711,7 @@ namespace TEAMModelBI.Controllers.BICommon
|
|
|
unitInfo.schools.Add(sch);
|
|
|
}
|
|
|
}
|
|
|
- if(!string.IsNullOrWhiteSpace(type))
|
|
|
+ if (!string.IsNullOrWhiteSpace(type))
|
|
|
{
|
|
|
unitInfos = unitInfos.Where(u => u.id.Equals(type)).ToList();
|
|
|
}
|
|
@@ -715,9 +721,9 @@ namespace TEAMModelBI.Controllers.BICommon
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
- /// 取得TMID資訊 ※個別挑選用
|
|
|
+ /// (個別挑選)取得TMID資訊後繼送訊息
|
|
|
/// </summary>
|
|
|
- [HttpPost("get-tmidinfo")]
|
|
|
+ [HttpPost("get-tmidinfo-single")]
|
|
|
#if !DEBUG
|
|
|
[Authorize(Roles = "IES")]
|
|
|
[AuthToken(Roles = "admin")]
|
|
@@ -728,10 +734,9 @@ namespace TEAMModelBI.Controllers.BICommon
|
|
|
{
|
|
|
var storageClientCsv2 = _azureStorage.GetCloudTableClient(name: "CoreServiceV2"); //Storage CSV2
|
|
|
var cosmosClientIes = _azureCosmos.GetCosmosClient();
|
|
|
- var cosmosClientCsv2 = _azureCosmos.GetCosmosClient(name:"CoreServiceV2");
|
|
|
+ var cosmosClientCsv2 = _azureCosmos.GetCosmosClient(name: "CoreServiceV2");
|
|
|
var tablePointsClient = storageClientCsv2.GetTableReference("Points");
|
|
|
|
|
|
-
|
|
|
//各項值取聯集或交集
|
|
|
string modeToAll = !string.IsNullOrWhiteSpace(target.mode) ? target.mode : "and";
|
|
|
|
|
@@ -739,7 +744,7 @@ namespace TEAMModelBI.Controllers.BICommon
|
|
|
//生成時間
|
|
|
List<string> passTmidCrt = new List<string>();
|
|
|
List<string> sqlWhereListBase = new List<string>();
|
|
|
- if(target.creatTime != null)
|
|
|
+ if (target.creatTime != null)
|
|
|
{
|
|
|
if (target.creatTime.start > 0) sqlWhereListBase.Add($" {target.creatTime.start} <= StringToNumber(c.id) ");
|
|
|
if (target.creatTime.end > 0) sqlWhereListBase.Add($" StringToNumber(c.id) <= {target.creatTime.end} ");
|
|
@@ -752,7 +757,7 @@ namespace TEAMModelBI.Controllers.BICommon
|
|
|
useCrtFlg = true;
|
|
|
sqlWhereBase += $" AND {w}";
|
|
|
}
|
|
|
- if(!string.IsNullOrWhiteSpace(sqlWhereBase))
|
|
|
+ if (!string.IsNullOrWhiteSpace(sqlWhereBase))
|
|
|
{
|
|
|
string sqlBase = $"{sqlSel}{sqlWhereBase}";
|
|
|
await foreach (var item in cosmosClientCsv2
|
|
@@ -760,7 +765,7 @@ namespace TEAMModelBI.Controllers.BICommon
|
|
|
.GetItemQueryIteratorSql<JsonElement>(queryText: sqlBase, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("base") }))
|
|
|
{
|
|
|
string id = item.GetProperty("id").ToString();
|
|
|
- if(!passTmidCrt.Contains(id)) passTmidCrt.Add(id);
|
|
|
+ if (!passTmidCrt.Contains(id)) passTmidCrt.Add(id);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -797,8 +802,8 @@ namespace TEAMModelBI.Controllers.BICommon
|
|
|
bool usePrdFlg = false;
|
|
|
List<string> passTmidPrd = new List<string>();
|
|
|
var tmidProdDic = new Dictionary<string, List<string>>(); //各ID使用過的的產品List
|
|
|
- List<string> prodWhereList = new List<string>();
|
|
|
- if(target.product != null && target.product.id.Count > 0)
|
|
|
+ List<string> prodWhereList = new List<string>();
|
|
|
+ if (target.product != null && target.product.id.Count > 0)
|
|
|
{
|
|
|
usePrdFlg = true;
|
|
|
foreach (string prodCode in target.product.id)
|
|
@@ -806,7 +811,7 @@ namespace TEAMModelBI.Controllers.BICommon
|
|
|
prodWhereList.Add(prodCode);
|
|
|
}
|
|
|
}
|
|
|
- if(prodWhereList.Count > 0)
|
|
|
+ if (prodWhereList.Count > 0)
|
|
|
{
|
|
|
string sqlSelCross = "SELECT DISTINCT c.id, c.type FROM c ";
|
|
|
string sqlWhereCross = $" WHERE ARRAY_CONTAINS({JsonSerializer.Serialize(prodWhereList)}, c.type)";
|
|
@@ -823,22 +828,22 @@ namespace TEAMModelBI.Controllers.BICommon
|
|
|
///生成符合AndOr條件的TMID製作
|
|
|
if (target.product.mode.Equals("and"))
|
|
|
{
|
|
|
- foreach(var prodItem in tmidProdDic)
|
|
|
+ foreach (var prodItem in tmidProdDic)
|
|
|
{
|
|
|
int hasProdCount = 0;
|
|
|
string tmid = prodItem.Key;
|
|
|
///產品比對
|
|
|
- foreach(string prod in target.product.id)
|
|
|
+ foreach (string prod in target.product.id)
|
|
|
{
|
|
|
- if(prodItem.Value.Contains(prod)) hasProdCount++;
|
|
|
+ if (prodItem.Value.Contains(prod)) hasProdCount++;
|
|
|
}
|
|
|
- if(hasProdCount.Equals(target.product.id.Count))
|
|
|
+ if (hasProdCount.Equals(target.product.id.Count))
|
|
|
{
|
|
|
if (!passTmidPrd.Contains(tmid)) passTmidPrd.Add(tmid);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- else if(target.product.mode.Equals("or"))
|
|
|
+ else if (target.product.mode.Equals("or"))
|
|
|
{
|
|
|
foreach (var prodItem in tmidProdDic)
|
|
|
{
|
|
@@ -854,7 +859,7 @@ namespace TEAMModelBI.Controllers.BICommon
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
//點數
|
|
@@ -862,7 +867,7 @@ namespace TEAMModelBI.Controllers.BICommon
|
|
|
List<string> passTmidPnt = new List<string>();
|
|
|
string filter = TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "Points");
|
|
|
string rkFilterCombine = string.Empty;
|
|
|
- if(target.point != null)
|
|
|
+ if (target.point != null)
|
|
|
{
|
|
|
if (target.point.start > 0 || target.point.end > 0)
|
|
|
{
|
|
@@ -928,12 +933,11 @@ namespace TEAMModelBI.Controllers.BICommon
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-
|
|
|
//所有TMID做聯集交集整合
|
|
|
List<string> passTmid = new List<string>(); //最終條件符合的TMID列表
|
|
|
///初始化
|
|
|
if (passTmidCrt.Count > 0) passTmid = passTmidCrt;
|
|
|
- else if(passTmidGeo.Count > 0) passTmid = passTmidGeo;
|
|
|
+ else if (passTmidGeo.Count > 0) passTmid = passTmidGeo;
|
|
|
else if (passTmidPrd.Count > 0) passTmid = passTmidPrd;
|
|
|
else if (passTmidPnt.Count > 0) passTmid = passTmidPnt;
|
|
|
else if (passTmidSch.Count > 0) passTmid = passTmidSch;
|
|
@@ -983,19 +987,45 @@ namespace TEAMModelBI.Controllers.BICommon
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
- /// 發送訊息核心邏輯
|
|
|
+ /// 寄發訊息API
|
|
|
/// </summary>
|
|
|
+ /// <param name="target"></param>
|
|
|
+ /// <param name="type">發送類型</param>
|
|
|
+ /// <param name="method">挑選方式</param>
|
|
|
+ /// <param name="title">標題</param>
|
|
|
+ /// <param name="body">內文</param>
|
|
|
+ /// <param name="data">傳遞資料</param>
|
|
|
+ /// <param name="action">傳遞動作</param>
|
|
|
[HttpPost("send-message")]
|
|
|
#if !DEBUG
|
|
|
[Authorize(Roles = "IES")]
|
|
|
[AuthToken(Roles = "admin")]
|
|
|
#endif
|
|
|
- public async Task<IActionResult> SendMessage(SendMessageParam target)
|
|
|
+ public async Task<IActionResult> SendMessage(JsonElement jsonElement)
|
|
|
{
|
|
|
+ SendMessageParam target = (jsonElement.TryGetProperty("target", out JsonElement _target)) ? _target.ToObject<SendMessageParam>() : null; //發送對象
|
|
|
+ string type = (jsonElement.TryGetProperty("type", out JsonElement _type)) ? _type.ToString() : string.Empty; //發送類型 mail:郵件、notify:端外、sms:簡訊
|
|
|
+ string method = (jsonElement.TryGetProperty("method", out JsonElement _method)) ? _method.ToString() : string.Empty; //挑選方式 single:個別 multi:批次
|
|
|
+ string title = (jsonElement.TryGetProperty("title", out JsonElement _title)) ? _title.ToString() : string.Empty; //標題
|
|
|
+ string body = (jsonElement.TryGetProperty("body", out JsonElement _body)) ? _body.ToString() : string.Empty; //內文
|
|
|
+ var dataParam = (jsonElement.TryGetProperty("data", out JsonElement _data)) ? _data : new JsonElement { };
|
|
|
+ List<NotifyAction> action = (jsonElement.TryGetProperty("action", out JsonElement _action)) ? _action.ToObject<List<NotifyAction>>() : new List<NotifyAction>();
|
|
|
|
|
|
-
|
|
|
-
|
|
|
- //target 內容例
|
|
|
+ if (target == null || string.IsNullOrWhiteSpace(type) || string.IsNullOrWhiteSpace(method) || string.IsNullOrWhiteSpace(title) || string.IsNullOrWhiteSpace(body)) return BadRequest();
|
|
|
+ string eventKey = "bi-gen-notify";
|
|
|
+ string eventId = $"{eventKey}_{_snowflakeId.NextId()}";
|
|
|
+ string eventName = "BI send notification";
|
|
|
+ var data = new {
|
|
|
+ value = dataParam,
|
|
|
+ action = action
|
|
|
+ };
|
|
|
+ await SendMessageCore(target, type, method, title, body, eventId, eventName, data);
|
|
|
+ return Ok(new { state = RespondCode.Ok });
|
|
|
+ }
|
|
|
+ ///寄發訊息核心邏輯
|
|
|
+ private async Task<IActionResult> SendMessageCore(SendMessageParam target, string type, string method, string title, string body, string eventId = "", string eventName = "", object data = null)
|
|
|
+ {
|
|
|
+ #region target 內容例
|
|
|
//{
|
|
|
// "area":[
|
|
|
// "1234"
|
|
@@ -1024,10 +1054,323 @@ namespace TEAMModelBI.Controllers.BICommon
|
|
|
// "1234"
|
|
|
// ]
|
|
|
//}
|
|
|
+ #endregion
|
|
|
+ var cosmosClientCsv2 = _azureCosmos.GetCosmosClient(name: "CoreServiceV2");
|
|
|
+
|
|
|
+ List<string> tmids_area = await GetTmidByAreaId(target.area);
|
|
|
+ List<string> tmids_geo = await GetTmidByGeo(target.geo);
|
|
|
+ List<string> tmids_unit = await GetTmidByUnitId(target.unit);
|
|
|
+ List<string> tmids_school = await GetTmidBySchoolId(target.school);
|
|
|
+ List<string> tmids_direct = target.tmid;
|
|
|
+
|
|
|
+ List<string> tmids = new List<string>(); //聯集化
|
|
|
+ tmids = tmids.Union(tmids_area).ToList();
|
|
|
+ tmids = tmids.Union(tmids_geo).ToList();
|
|
|
+ tmids = tmids.Union(tmids_unit).ToList();
|
|
|
+ tmids = tmids.Union(tmids_school).ToList();
|
|
|
+ tmids = tmids.Union(tmids_direct).ToList();
|
|
|
+ tmids = tmids.Distinct().ToList(); //唯一化
|
|
|
|
|
|
+ //取得TMID資料
|
|
|
+ List<IdInfo> tmidInfos = new List<IdInfo>();
|
|
|
+ string sqlBaseInfo = $"SELECT c.id, c.name, c.mail, c.mobile FROM c WHERE ARRAY_CONTAINS({JsonSerializer.Serialize(tmids)}, c.id)";
|
|
|
+ await foreach (var item in cosmosClientCsv2
|
|
|
+ .GetContainer("Core", "ID2")
|
|
|
+ .GetItemQueryIteratorSql<JsonElement>(queryText: sqlBaseInfo, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("base") }))
|
|
|
+ {
|
|
|
+ IdInfo idInfo = new IdInfo();
|
|
|
+ idInfo.id = item.GetProperty("id").ToString();
|
|
|
+ idInfo.name = item.GetProperty("name").ToString();
|
|
|
+ idInfo.mail = item.GetProperty("mail").ToString();
|
|
|
+ idInfo.mobile = item.GetProperty("mobile").ToString();
|
|
|
+ tmidInfos.Add(idInfo);
|
|
|
+ }
|
|
|
+
|
|
|
+ //寄發訊息
|
|
|
+ if(type.Equals("notify")) //端內外通知
|
|
|
+ {
|
|
|
+ List<string> tmIds = tmidInfos.Select(i => i.id).ToList();
|
|
|
+ CallPushNotifyApi(tmIds, title, body, eventId, eventName, data);
|
|
|
+ }
|
|
|
+ else if(type.Equals("mail")) //Email
|
|
|
+ {
|
|
|
+ List<string> tmIds = tmidInfos.Where(i => !string.IsNullOrWhiteSpace(i.mail)).Select(i => i.id).ToList();
|
|
|
+ }
|
|
|
+ else if (type.Equals("sms")) //短訊
|
|
|
+ {
|
|
|
+ List<string> tmIds = tmidInfos.Where(i => !string.IsNullOrWhiteSpace(i.mobile)).Select(i => i.id).ToList();
|
|
|
+ }
|
|
|
|
|
|
return Ok(new { state = RespondCode.Ok });
|
|
|
}
|
|
|
+ //取得學區所屬學校教師
|
|
|
+ private async Task<List<string>> GetTmidByAreaId(List<string> areaIds)
|
|
|
+ {
|
|
|
+ var cosmosClientIes = _azureCosmos.GetCosmosClient();
|
|
|
+ //取得學校ID列表
|
|
|
+ List<string> schIds = new List<string>();
|
|
|
+ string sqlSch = $"SELECT c.id FROM c WHERE ARRAY_CONTAINS({JsonSerializer.Serialize(areaIds)}, c.areaId)";
|
|
|
+ ///實體校
|
|
|
+ await foreach (var item in cosmosClientIes.GetContainer(Constant.TEAMModelOS, Constant.School).GetItemQueryIteratorSql<JsonElement>(queryText: sqlSch, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Base") }))
|
|
|
+ {
|
|
|
+ string schId = item.GetProperty("id").ToString();
|
|
|
+ schIds.Add(schId);
|
|
|
+ }
|
|
|
+ List<string> teacherCodes = schIds.Select(s => $"Teacher-{s}").ToList();
|
|
|
+ //取得學校教師ID列表
|
|
|
+ List<string> tmids = new List<string>();
|
|
|
+ string sqlTch = $"SELECT DISTINCT c.id FROM c WHERE c.pk = 'Teacher' AND c.status = 'join' AND ARRAY_CONTAINS({JsonSerializer.Serialize(teacherCodes)}, c.code)";
|
|
|
+ await foreach (var item in cosmosClientIes.GetContainer(Constant.TEAMModelOS, Constant.School).GetItemQueryIteratorSql<JsonElement>(queryText: sqlTch, requestOptions: null))
|
|
|
+ {
|
|
|
+ string tmid = item.GetProperty("id").ToString();
|
|
|
+ tmids.Add(tmid);
|
|
|
+ }
|
|
|
+ return tmids;
|
|
|
+ }
|
|
|
+ //取得地理資訊所屬TMID
|
|
|
+ private async Task<List<string>> GetTmidByGeo(List<Geo> geos)
|
|
|
+ {
|
|
|
+ var cosmosClientCsv2 = _azureCosmos.GetCosmosClient(name: "CoreServiceV2");
|
|
|
+ string sqlWhere = string.Empty;
|
|
|
+ List<string> sqlWhereOrList = new List<string>();
|
|
|
+ foreach (Geo geo in geos)
|
|
|
+ {
|
|
|
+ string sqlWhereRow = String.Empty;
|
|
|
+ if (!string.IsNullOrWhiteSpace(geo.countryId))
|
|
|
+ {
|
|
|
+ if (!string.IsNullOrWhiteSpace(sqlWhereRow)) sqlWhereRow += " AND ";
|
|
|
+ sqlWhereRow += $"c.country = '{geo.countryId}'";
|
|
|
+ }
|
|
|
+ if (!string.IsNullOrWhiteSpace(geo.provinceId))
|
|
|
+ {
|
|
|
+ if (!string.IsNullOrWhiteSpace(sqlWhereRow)) sqlWhereRow += " AND ";
|
|
|
+ sqlWhereRow += $"c.province = '{geo.provinceId}'";
|
|
|
+ }
|
|
|
+ if (!string.IsNullOrWhiteSpace(geo.cityId))
|
|
|
+ {
|
|
|
+ if (!string.IsNullOrWhiteSpace(sqlWhereRow)) sqlWhereRow += " AND ";
|
|
|
+ sqlWhereRow += $"c.city = '{geo.cityId}'";
|
|
|
+ }
|
|
|
+ if (!string.IsNullOrWhiteSpace(sqlWhereRow))
|
|
|
+ {
|
|
|
+ sqlWhereOrList.Add(sqlWhereRow);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (sqlWhereOrList.Count > 0)
|
|
|
+ {
|
|
|
+ foreach (string sqlWhereOrRow in sqlWhereOrList)
|
|
|
+ {
|
|
|
+ if (!string.IsNullOrWhiteSpace(sqlWhere)) sqlWhere += " OR ";
|
|
|
+ sqlWhere += $"({sqlWhereOrRow})";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ List<string> tmids = new List<string>();
|
|
|
+ if (!string.IsNullOrWhiteSpace(sqlWhere))
|
|
|
+ {
|
|
|
+ string sqlEx = $"SELECT DISTINCT c.id FROM c WHERE {sqlWhere}";
|
|
|
+ await foreach (var item in cosmosClientCsv2
|
|
|
+ .GetContainer("Core", "ID2")
|
|
|
+ .GetItemQueryIteratorSql<JsonElement>(sqlEx, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("base-ex") }))
|
|
|
+ {
|
|
|
+ string id = item.GetProperty("id").ToString();
|
|
|
+ tmids.Add(id);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return tmids;
|
|
|
+ }
|
|
|
+ //寄送通知核心程式(途中)
|
|
|
+ private void sendMessageByApi()
|
|
|
+ {
|
|
|
+ //_coreAPIHttpService.PushNotify(idNameCodes, $"{bizcode}_school", Constant.NotifyType_IES5_Task, new Dictionary<string, object> { { "tmdname", name }, { "schoolName", schname }, { "schoolId", $"{school}" }, { "tmdid", userid } }, _option.Location, _configuration, _dingDing, _environment.ContentRootPath);
|
|
|
+ }
|
|
|
+
|
|
|
+ //取得學校機構所屬學校教師
|
|
|
+ private async Task<List<string>> GetTmidByUnitId(List<string> units)
|
|
|
+ {
|
|
|
+ if (units.Count.Equals(0)) return new List<string>();
|
|
|
+
|
|
|
+ var cosmosClientIes = _azureCosmos.GetCosmosClient();
|
|
|
+ var coreCosmosClientCn = _azureCosmos.GetCosmosClient(name: "CoreServiceV2CnRead");
|
|
|
+ //取得IES5學校ID
|
|
|
+ string iesSql = "SELECT c.id, c.type FROM c WHERE 1=1 ";
|
|
|
+ string iesWhere = string.Empty;
|
|
|
+ //IES學校ID取得、學校類型取得
|
|
|
+ List<string> iesSchIds = new List<string>();
|
|
|
+ Dictionary<string, string> schTypeDic = new Dictionary<string, string>(); //IES5學校ID與學校類型對照表
|
|
|
+ List<string> teacherCodes = new List<string>(); //用來取得老師資料的分區鍵
|
|
|
+ string sqlSch = $"{iesSql}{iesWhere}";
|
|
|
+ await foreach (var item in cosmosClientIes.GetContainer(Constant.TEAMModelOS, Constant.School).GetItemQueryIteratorSql<JsonElement>(queryText: sqlSch, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Base") }))
|
|
|
+ {
|
|
|
+ string schId = item.GetProperty("id").ToString();
|
|
|
+ int schType = item.GetProperty("type").GetInt32();
|
|
|
+ iesSchIds.Add(schId);
|
|
|
+ if (!schTypeDic.ContainsKey(schId)) schTypeDic.Add(schId, schType.ToString());
|
|
|
+ }
|
|
|
+ //取得Core學校ID及類型
|
|
|
+ string coreSql = "SELECT c.shortCode, c.unitType FROM c";
|
|
|
+ string coreWhere = $" WHERE ARRAY_CONTAINS({JsonSerializer.Serialize(iesSchIds)}, c.shortCode) ";
|
|
|
+ string coreWhereUnittype = string.Empty;
|
|
|
+ if (units.Contains("1"))
|
|
|
+ {
|
|
|
+ if (!string.IsNullOrWhiteSpace(coreWhereUnittype)) coreWhereUnittype += " OR ";
|
|
|
+ coreWhereUnittype += $" ARRAY_CONTAINS(['1','8'], c.unitType) ";
|
|
|
+ }
|
|
|
+ if (units.Contains("2"))
|
|
|
+ {
|
|
|
+ if (!string.IsNullOrWhiteSpace(coreWhereUnittype)) coreWhereUnittype += " OR ";
|
|
|
+ coreWhereUnittype += $" c.unitType = '2' ";
|
|
|
+ }
|
|
|
+ if (units.Contains("3"))
|
|
|
+ {
|
|
|
+ if (!string.IsNullOrWhiteSpace(coreWhereUnittype)) coreWhereUnittype += " OR ";
|
|
|
+ coreWhereUnittype += $" c.unitType = '3' ";
|
|
|
+ }
|
|
|
+ if (units.Contains("4"))
|
|
|
+ {
|
|
|
+ if (!string.IsNullOrWhiteSpace(coreWhereUnittype)) coreWhereUnittype += " OR ";
|
|
|
+ coreWhereUnittype += $" ARRAY_CONTAINS(['4','5','6','7','9'], c.unitType) ";
|
|
|
+ }
|
|
|
+ if (!string.IsNullOrWhiteSpace(coreWhereUnittype))
|
|
|
+ {
|
|
|
+ coreWhere += $" AND ({coreWhereUnittype})";
|
|
|
+ }
|
|
|
+ Dictionary<string, string> coreSchUnitTypeDic = new Dictionary<string, string>(); //Core學校ID與學校類型對照表
|
|
|
+ string sqlCore = $"{coreSql}{coreWhere}";
|
|
|
+ await foreach (var item in coreCosmosClientCn.GetContainer("Core", "School").GetItemQueryIteratorSql<JsonElement>(queryText: sqlCore, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"base") }))
|
|
|
+ {
|
|
|
+ string shortCode = item.GetProperty("shortCode").ToString();
|
|
|
+ string unitType = item.GetProperty("unitType").ToString();
|
|
|
+ if (!teacherCodes.Contains($"Teacher-{shortCode}")) teacherCodes.Add($"Teacher-{shortCode}");
|
|
|
+ if (!coreSchUnitTypeDic.ContainsKey(shortCode)) coreSchUnitTypeDic.Add(shortCode, unitType);
|
|
|
+ }
|
|
|
+ //學校類型轉換
|
|
|
+ Dictionary<string, string> finalSchUnitTypeDic = new Dictionary<string, string>();
|
|
|
+ foreach (KeyValuePair<string, string> item in coreSchUnitTypeDic)
|
|
|
+ {
|
|
|
+ string schId = item.Key;
|
|
|
+ string coreUnitType = (coreSchUnitTypeDic.ContainsKey(schId)) ? coreSchUnitTypeDic[schId] : string.Empty;
|
|
|
+ string iesUnitType = (schTypeDic.ContainsKey(schId)) ? schTypeDic[schId] : string.Empty;
|
|
|
+ string unitTypeF = string.Empty; //機構類型(最終判斷)
|
|
|
+ if (!string.IsNullOrWhiteSpace(coreUnitType))
|
|
|
+ {
|
|
|
+ switch (coreUnitType)
|
|
|
+ {
|
|
|
+ case "1": //基礎教育機構
|
|
|
+ case "8": //學前教育
|
|
|
+ unitTypeF = "1"; // => 基礎教育機構(K-小學)
|
|
|
+ break;
|
|
|
+ case "2": //中等教育機構
|
|
|
+ unitTypeF = "2"; // => 中等教育機構(國中、高中/職)
|
|
|
+ break;
|
|
|
+
|
|
|
+ case "3": //高等教育機構
|
|
|
+ unitTypeF = "3"; // => 高等教育機構(大學、研究所)
|
|
|
+ break;
|
|
|
+ case "4": //政府單位機構
|
|
|
+ case "5": //NGO機構
|
|
|
+ case "6": //企業機構
|
|
|
+ case "7": //其他
|
|
|
+ case "9": //特殊教育
|
|
|
+ unitTypeF = "4"; // => 其他
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (!string.IsNullOrWhiteSpace(iesUnitType))
|
|
|
+ {
|
|
|
+ switch (iesUnitType) //1 普教,2 高职教
|
|
|
+ {
|
|
|
+ case "1": //國教(K-12)
|
|
|
+ unitTypeF = "1"; // => 基礎教育機構(K-小學)
|
|
|
+ break;
|
|
|
+ case "2": //大專院校
|
|
|
+ unitTypeF = "3"; // => 高等教育機構(大學、研究所)
|
|
|
+ break;
|
|
|
+ default: //未設定
|
|
|
+ unitTypeF = "4"; // => 其他
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ finalSchUnitTypeDic.Add(schId, unitTypeF);
|
|
|
+ }
|
|
|
+ //由類型篩選學校ID [應該不需要,CoreV2的SQL已篩選過]
|
|
|
+ //List<string> schIdsForSql = new List<string>();
|
|
|
+ //foreach (KeyValuePair<string, string> item in finalSchUnitTypeDic)
|
|
|
+ //{
|
|
|
+ // string schId = item.Key;
|
|
|
+ // if (units.Contains(item.Value))
|
|
|
+ // {
|
|
|
+ // schIdsForSql.Add(schId);
|
|
|
+ // }
|
|
|
+ //}
|
|
|
+ //取得學校所屬老師TMID
|
|
|
+ //teacherCodes = schIdsForSql.Select(s => $"Teacher-{s}").ToList();
|
|
|
+ teacherCodes = finalSchUnitTypeDic.Select(s => $"Teacher-{s.Key}").ToList();
|
|
|
+ List<string> tmids = new List<string>();
|
|
|
+ string sqlTch = $"SELECT DISTINCT c.id FROM c WHERE c.pk = 'Teacher' AND c.status = 'join' AND ARRAY_CONTAINS({JsonSerializer.Serialize(teacherCodes)}, c.code)";
|
|
|
+ await foreach (var item in cosmosClientIes.GetContainer(Constant.TEAMModelOS, Constant.School).GetItemQueryIteratorSql<JsonElement>(queryText: sqlTch, requestOptions: null))
|
|
|
+ {
|
|
|
+ string tmid = item.GetProperty("id").ToString();
|
|
|
+ tmids.Add(tmid);
|
|
|
+ }
|
|
|
+ return tmids;
|
|
|
+
|
|
|
+ }
|
|
|
+ //取得學校所屬學校教師
|
|
|
+ private async Task<List<string>> GetTmidBySchoolId(List<string> schIds)
|
|
|
+ {
|
|
|
+ var cosmosClientIes = _azureCosmos.GetCosmosClient();
|
|
|
+ //取得學校ID列表
|
|
|
+ List<string> teacherCodes = schIds.Select(s => $"Teacher-{s}").ToList();
|
|
|
+ //取得學校教師ID列表
|
|
|
+ List<string> tmids = new List<string>();
|
|
|
+ string sqlTch = $"SELECT DISTINCT c.id FROM c WHERE c.pk = 'Teacher' AND c.status = 'join' AND ARRAY_CONTAINS({JsonSerializer.Serialize(teacherCodes)}, c.code)";
|
|
|
+ await foreach (var item in cosmosClientIes.GetContainer(Constant.TEAMModelOS, Constant.School).GetItemQueryIteratorSql<JsonElement>(queryText: sqlTch, requestOptions: null))
|
|
|
+ {
|
|
|
+ string tmid = item.GetProperty("id").ToString();
|
|
|
+ tmids.Add(tmid);
|
|
|
+ }
|
|
|
+ return tmids;
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 寄發端外通知
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="tmIds"></param>
|
|
|
+ /// <param name="title"></param>
|
|
|
+ /// <param name="body"></param>
|
|
|
+ /// <param name="eventId"></param>
|
|
|
+ /// <param name="eventName"></param>
|
|
|
+ /// <param name="data"></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ private HttpResponseMessage CallPushNotifyApi(List<string> tmIds, string title, string body, string eventId = "", string eventName = "", object data = null)
|
|
|
+ {
|
|
|
+ NotifyData notify = new NotifyData();
|
|
|
+ notify.hubName = "hita5";
|
|
|
+ notify.sender = "IES"; //先填IES 若之後有需求要標BI 再修正
|
|
|
+#if DEBUG
|
|
|
+ List<string> filterTmid = new List<string>() { "1522758684", "1595321354" };
|
|
|
+ tmIds = tmIds.Intersect(filterTmid).ToList();
|
|
|
+#endif
|
|
|
+ notify.tags = tmIds.Select(s => $"{s}_BI").ToList();
|
|
|
+ notify.title = title;
|
|
|
+ notify.body = body;
|
|
|
+ notify.eventId = eventId;
|
|
|
+ notify.eventName = eventName;
|
|
|
+ notify.data = (data != null) ? data.ToJsonString() : string.Empty;
|
|
|
+ var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
|
|
|
+ var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
|
|
|
+ var url = _configuration.GetValue<string>("HaBookAuth:CoreAPI");
|
|
|
+ var client = _httpClient;
|
|
|
+ string sendSite = (_option.Location.Contains("China")) ? "China" : "Global";
|
|
|
+ var token = CoreTokenExtensions.CreateAccessToken(clientID, clientSecret, sendSite).Result;
|
|
|
+ if (client.DefaultRequestHeaders.Contains("Authorization"))
|
|
|
+ {
|
|
|
+ client.DefaultRequestHeaders.Remove("Authorization");
|
|
|
+ }
|
|
|
+ client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token.AccessToken}");
|
|
|
+ HttpResponseMessage responseMessage = client.PostAsJsonAsync($"{url}/service/PushNotify", notify).Result;
|
|
|
+ return responseMessage;
|
|
|
+ }
|
|
|
|
|
|
/// <summary>
|
|
|
/// 取得TMID資訊 接收參數class
|
|
@@ -1124,6 +1467,17 @@ namespace TEAMModelBI.Controllers.BICommon
|
|
|
public string id { get; set; }
|
|
|
public string name { get; set; }
|
|
|
}
|
|
|
+ private record IdInfo : IdName
|
|
|
+ {
|
|
|
+ public string mail { get; set; }
|
|
|
+ public string mobile { get; set; }
|
|
|
+ }
|
|
|
+ private record NotifyAction
|
|
|
+ {
|
|
|
+ public string type { get; set; } = "click";
|
|
|
+ public string label { get; set; }
|
|
|
+ public string url { get; set; }
|
|
|
+ }
|
|
|
//地區要去除的特殊字
|
|
|
public List<string> comeRemoveStr = new List<string>() { "省", "市", "区", "州", "县", "旗", "盟", "自治", "地區", "區", "縣" };
|
|
|
}
|