TmidController.cs 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872
  1. using Azure.Cosmos;
  2. using DocumentFormat.OpenXml.Office2010.Excel;
  3. using Microsoft.AspNetCore.Mvc;
  4. using Microsoft.Azure.Cosmos.Table;
  5. using Microsoft.Extensions.Configuration;
  6. using Microsoft.Extensions.Options;
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Linq;
  10. using System.Reflection;
  11. using System.Text.Json;
  12. using System.Threading.Tasks;
  13. using TEAMModelOS.Models;
  14. using TEAMModelOS.SDK;
  15. using TEAMModelOS.SDK.DI;
  16. using TEAMModelOS.SDK.Extension;
  17. using TEAMModelOS.SDK.Models;
  18. using TEAMModelOS.SDK.Services;
  19. using static TEAMModelBI.Models.Extension.GeoRegion;
  20. namespace TEAMModelBI.Controllers.BITmid
  21. {
  22. [Route("tmid")]
  23. [ApiController]
  24. public class TmidController : ControllerBase
  25. {
  26. private readonly AzureCosmosFactory _azureCosmos;
  27. private readonly AzureStorageFactory _azureStorage;
  28. private readonly AzureRedisFactory _azureRedis;
  29. private readonly DingDing _dingDing;
  30. private readonly Option _option;
  31. private readonly IConfiguration _configuration;
  32. private readonly HttpTrigger _httpTrigger;
  33. public TmidController(AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis, DingDing dingDing, IOptionsSnapshot<Option> option, IConfiguration configuration, HttpTrigger httpTrigger)
  34. {
  35. _azureCosmos = azureCosmos;
  36. _azureStorage = azureStorage;
  37. _azureRedis = azureRedis;
  38. _dingDing = dingDing;
  39. _option = option?.Value;
  40. _configuration = configuration;
  41. _httpTrigger = httpTrigger;
  42. }
  43. /// <summary>
  44. /// 取得TMID綜合資料
  45. /// </summary>
  46. /// <param name="jsonElement"></param>
  47. /// <returns></returns>
  48. [ProducesDefaultResponseType]
  49. //[AuthToken(Roles = "admin")]
  50. [HttpPost("get-tmidstics")]
  51. public async Task<IActionResult> GetTmidStics(JsonElement jsonElement)
  52. {
  53. try
  54. {
  55. if (!jsonElement.TryGetProperty("tmids", out JsonElement tmidsJobj)) return BadRequest();//TMID(array)
  56. var tmids = tmidsJobj.Deserialize<List<string>>();
  57. if (tmids.Count is 0) return BadRequest();
  58. var datetime = DateTimeOffset.UtcNow.AddDays(-1);
  59. int y = datetime.Year;
  60. int m = datetime.Month;
  61. int d = datetime.Day;
  62. string dateFromStr = (jsonElement.TryGetProperty("dateFrom", out JsonElement dateFromJobj)) ? dateFromJobj.GetString() : string.Empty; //查詢日期:起始(string)[例]2023-03-05
  63. string dateToStr = (jsonElement.TryGetProperty("dateTo", out JsonElement dateToJobj)) ? dateToJobj.GetString() : string.Empty; //查詢日期:結束(string)[例]2023-03-27
  64. string dateUnit = (jsonElement.TryGetProperty("dateUnit", out JsonElement dateUnitJobj)) ? dateUnitJobj.GetString().ToLower() : "month";
  65. string mode = (jsonElement.TryGetProperty("mode", out JsonElement modeJobj)) ? modeJobj.GetString().ToLower() : "default";
  66. //起始終止日期換算
  67. long dateTimeFromSec = 0;
  68. long dateTimeToSec = 0;
  69. if(!string.IsNullOrWhiteSpace(dateFromStr) && !string.IsNullOrWhiteSpace(dateToStr))
  70. {
  71. DateTimeOffset dateTimeFrom;
  72. DateTimeOffset dateTimeTo;
  73. List<string> dateFromList = dateFromStr.Split('-').ToList();
  74. int dateFromYear = Convert.ToInt32(dateFromList[0], 10);
  75. int dateFromMonth = (dateUnit.Equals("day") || dateUnit.Equals("month")) ? Convert.ToInt32(dateFromList[1], 10) : 1;
  76. int dateFromDay = (dateUnit.Equals("day")) ? Convert.ToInt32(dateFromList[2], 10) : 1;
  77. List<string> dateToList = dateToStr.Split('-').ToList();
  78. int dateToYear = Convert.ToInt32(dateToList[0], 10);
  79. int dateToMonth = (dateUnit.Equals("day") || dateUnit.Equals("month")) ? Convert.ToInt32(dateToList[1], 10) : 1;
  80. int dateToDay = (dateUnit.Equals("day")) ? Convert.ToInt32(dateToList[2], 10) : 1;
  81. switch (dateUnit)
  82. {
  83. case "year":
  84. dateTimeFrom = new DateTimeOffset(dateFromYear, 1, 1, 0, 0, 0, TimeSpan.Zero);
  85. dateTimeTo = new DateTimeOffset(dateToYear, 12, 31, 23, 59, 59, TimeSpan.Zero);
  86. break;
  87. case "month":
  88. dateTimeFrom = new DateTimeOffset(dateFromYear, dateFromMonth, 1, 0, 0, 0, TimeSpan.Zero);
  89. dateTimeTo = new DateTimeOffset(dateToYear, dateToMonth, DateTime.DaysInMonth(dateToYear, dateToMonth), 23, 59, 59, TimeSpan.Zero);
  90. break;
  91. case "day":
  92. dateTimeFrom = new DateTimeOffset(dateFromYear, dateFromMonth, dateFromDay, 0, 0, 0, TimeSpan.Zero);
  93. dateTimeTo = new DateTimeOffset(dateToYear, dateToMonth, dateToDay, 23, 59, 59, TimeSpan.Zero);
  94. break;
  95. default:
  96. dateTimeFrom = new DateTimeOffset(y, m, d, 0, 0, 0, TimeSpan.Zero);
  97. dateTimeTo = new DateTimeOffset(y, m, d, 23, 59, 59, TimeSpan.Zero);
  98. break;
  99. }
  100. dateTimeFromSec = dateTimeFrom.ToUnixTimeSeconds();
  101. dateTimeToSec = dateTimeTo.ToUnixTimeSeconds();
  102. y = 0;
  103. m = 0;
  104. d = 0;
  105. }
  106. //取得項目列表
  107. List<string> eventList = new List<string>();
  108. if(mode.Equals("simple"))
  109. {
  110. eventList = new List<string>() { "iot" };
  111. } else
  112. {
  113. eventList = new List<string>() { "coupons", "login", "prod", "points", "iot", "ies5", "benefits", "sokrates" };
  114. }
  115. //服務Client端
  116. var cosmosClientIes5 = _azureCosmos.GetCosmosClient(); //CosmosDB IES5
  117. var cosmosClientCsv2 = _azureCosmos.GetCosmosClient(name: "CoreServiceV2"); //CosmosDB CSV2
  118. var storageClientCsv2 = _azureStorage.GetCloudTableClient(name: "CoreServiceV2"); //Storage CSV2
  119. var tableCouponClient = storageClientCsv2.GetTableReference("Coupon");
  120. var tablePointsClient = storageClientCsv2.GetTableReference("Points");
  121. var redisClient = _azureRedis.GetRedisClient(4);
  122. //取得TMID基本資料
  123. Dictionary<string, TmidStics> tmidDic = new();
  124. QueryDefinition query =
  125. new QueryDefinition(@"SELECT c.id, c.name, c.picture, c.mobile, c.mail, c.lang, c.wechat, c.facebook, c.google, c.ding, c.apple, c.educloudtw, c.ts FROM c WHERE (ARRAY_CONTAINS(@key, c.id) OR ARRAY_CONTAINS(@key, c.mobile))")
  126. .WithParameter("@key", tmids);
  127. await foreach (var item in cosmosClientCsv2
  128. .GetContainer("Core", "ID2")
  129. .GetItemQueryStreamIterator(query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("base") }))
  130. {
  131. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  132. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  133. {
  134. foreach (var doc in json.RootElement.GetProperty("Documents").EnumerateArray())
  135. {
  136. string id = doc.GetProperty("id").GetString();
  137. if(!tmids.Contains(id)) tmids.Add(id);
  138. //基本資料
  139. TmidStics tmidStics = (tmidDic.ContainsKey(id)) ? tmidDic[id] : new() { id = id };
  140. if (eventList.Contains("ies5")) tmidStics.ies5 = new();
  141. if (eventList.Contains("points")) tmidStics.points = new();
  142. if (eventList.Contains("sokrates")) tmidStics.sokrates = new();
  143. if (eventList.Contains("benefits")) tmidStics.benefits = new();
  144. if (eventList.Contains("iot")) tmidStics.iot = new();
  145. tmidStics.name = doc.GetProperty("name").GetString();
  146. tmidStics.picture = doc.GetProperty("picture").GetString();
  147. tmidStics.mobile = GenDataMask(doc.GetProperty("mobile").GetString(), "mobile");
  148. tmidStics.mail = GenDataMask(doc.GetProperty("mail").GetString(), "mail");
  149. tmidStics.lang = (doc.TryGetProperty("lang", out JsonElement lang)) ? lang.GetString() : string.Empty;
  150. tmidStics.wechat = (doc.TryGetProperty("wechat", out JsonElement wechat) && !string.IsNullOrWhiteSpace(wechat.GetString())) ? true : false;
  151. tmidStics.facebook = (doc.TryGetProperty("facebook", out JsonElement facebook) && !string.IsNullOrWhiteSpace(facebook.GetString())) ? true : false;
  152. tmidStics.google = (doc.TryGetProperty("google", out JsonElement google) && !string.IsNullOrWhiteSpace(google.GetString())) ? true : false;
  153. tmidStics.ding = (doc.TryGetProperty("ding", out JsonElement ding) && !string.IsNullOrWhiteSpace(ding.GetString())) ? true : false;
  154. tmidStics.apple = (doc.TryGetProperty("apple", out JsonElement apple) && !string.IsNullOrWhiteSpace(apple.GetString())) ? true : false;
  155. tmidStics.ts = (doc.TryGetProperty("ts", out JsonElement ts)) ? ts.GetInt64() : 0;
  156. tmidDic.Add(id, tmidStics);
  157. }
  158. }
  159. }
  160. //取得TMID進階資料
  161. regiondata regionData = GetRegionData(); //取得國省市區地理資訊架構
  162. query = new QueryDefinition(@"SELECT c.id, c.name, c.mobile, c.mail, c.country, c.province, c.city, c.schoolCode, c.schoolCodeW, c.unitType, c.unitName, c.jobTitle FROM c WHERE (ARRAY_CONTAINS(@key, c.id) OR ARRAY_CONTAINS(@key, c.mobile))")
  163. .WithParameter("@key", tmids);
  164. await foreach (var item in cosmosClientCsv2
  165. .GetContainer("Core", "ID2")
  166. .GetItemQueryStreamIterator(query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("base-ex") }))
  167. {
  168. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  169. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  170. {
  171. foreach (var doc in json.RootElement.GetProperty("Documents").EnumerateArray())
  172. {
  173. string id = doc.GetProperty("id").GetString();
  174. TmidStics tmidStics = (tmidDic.ContainsKey(id)) ? tmidDic[id] : new() { id = id };
  175. if (eventList.Contains("ies5")) tmidStics.ies5 = new();
  176. if (eventList.Contains("points")) tmidStics.points = new();
  177. if (eventList.Contains("sokrates")) tmidStics.sokrates = new();
  178. if (eventList.Contains("benefits")) tmidStics.benefits = new();
  179. if (eventList.Contains("iot")) tmidStics.iot = new();
  180. if (string.IsNullOrWhiteSpace(tmidStics.name)) tmidStics.name = doc.GetProperty("name").GetString();
  181. if (string.IsNullOrWhiteSpace(tmidStics.mobile)) tmidStics.mobile = GenDataMask(doc.GetProperty("mobile").GetString(), "mobile");
  182. if (string.IsNullOrWhiteSpace(tmidStics.mail)) tmidStics.mail = GenDataMask(doc.GetProperty("mail").GetString(), "mail");
  183. string country = doc.GetProperty("country").GetString();
  184. string province = doc.GetProperty("province").GetString();
  185. string city = doc.GetProperty("city").GetString();
  186. string district = string.Empty;
  187. if (!string.IsNullOrWhiteSpace(country) && country.Equals("TW"))
  188. {
  189. district = city;
  190. city = province;
  191. province = string.Empty;
  192. }
  193. tmidStics.country = (!string.IsNullOrWhiteSpace(country) && regionData.country.ContainsKey(country)) ? regionData.country[country].name.Replace("地區", "").Replace("地区", "") : country;
  194. tmidStics.province = (!string.IsNullOrWhiteSpace(country) && regionData.country.ContainsKey(country) && !string.IsNullOrWhiteSpace(province) && regionData.province.ContainsKey(country) && regionData.province[country].ContainsKey(province)) ? regionData.province[country][province].name : province;
  195. if (!string.IsNullOrWhiteSpace(country) && country.Equals("TW"))
  196. tmidStics.city = (regionData.city.ContainsKey(country) && !string.IsNullOrWhiteSpace(city) && regionData.city[country]["tw"].ContainsKey(city)) ? regionData.city[country]["tw"][city].name : city;
  197. else if(!string.IsNullOrWhiteSpace(country) && country.Equals("CN"))
  198. tmidStics.city = (regionData.city.ContainsKey(country) && regionData.city[country].ContainsKey(province) && regionData.city[country][province].ContainsKey(city)) ? regionData.city[country][province][city].name : city;
  199. tmidStics.dist = (!string.IsNullOrWhiteSpace(district) && country.Equals("TW") && regionData.city[country]["tw"].ContainsKey(city) && regionData.dist[country]["tw"][city].ContainsKey(district)) ? regionData.dist[country]["tw"][city][district].name : district;
  200. tmidStics.schoolCode = (doc.TryGetProperty("schoolCode", out JsonElement schCode)) ? schCode.GetString() : string.Empty;
  201. tmidStics.schoolCodeW = (doc.TryGetProperty("schoolCodeW", out JsonElement schCodeW)) ? schCodeW.GetString() : string.Empty;
  202. tmidStics.unitType = (doc.TryGetProperty("unitType", out JsonElement unitType)) ? unitType.GetString() : string.Empty;
  203. tmidStics.unitName = (doc.TryGetProperty("unitName", out JsonElement unitName)) ? unitName.GetString() : string.Empty;
  204. tmidStics.jobTitle = (doc.TryGetProperty("jobTitle", out JsonElement jobTitle)) ? jobTitle.GetString() : string.Empty;
  205. }
  206. }
  207. }
  208. if(tmidDic.Count.Equals(0)) return Ok(new List<object>());
  209. //取得 票券、登入各服務的時間、取得積分、個人服務授權、IOT
  210. foreach (KeyValuePair<string, TmidStics> dicItem in tmidDic)
  211. {
  212. string id = dicItem.Key;
  213. TmidStics tmidStics = dicItem.Value;
  214. //票券
  215. if (eventList.Contains("coupons"))
  216. {
  217. var usersCoupons = tableCouponClient.Get<DynamicTableEntity>(id);
  218. foreach (var coupon in usersCoupons)
  219. {
  220. tmidStics.coupons.Add(
  221. new TmidCoupon()
  222. {
  223. code = coupon.RowKey,
  224. exchange = coupon.Properties["exchangeTime"].DateTimeOffsetValue.Value.ToUnixTimeSeconds(),
  225. });
  226. }
  227. }
  228. //取得登入各服務的時間
  229. if (eventList.Contains("login"))
  230. {
  231. var loginTime = await redisClient.HashGetAllAsync(id);
  232. foreach (var t in loginTime)
  233. {
  234. if (!t.Name.StartsWith("HiTeach") && !_dicClientIds.ContainsKey(t.Name)) continue;
  235. tmidStics.login.Add(
  236. new TmidLoginTime()
  237. {
  238. product = t.Name.StartsWith("HiTeach") ? t.Name.ToString().Split("-")[0] : _dicClientIds[t.Name],
  239. time = (long)t.Value
  240. });
  241. }
  242. }
  243. //積分
  244. if (eventList.Contains("points"))
  245. {
  246. var usersPoints = tablePointsClient.Get("Points", id);
  247. tmidStics.points.points = (usersPoints != null) ? usersPoints.Properties["Points"].Int32Value.Value : 0;
  248. tmidStics.points.level = (usersPoints != null) ? usersPoints.Properties["Level"].Int32Value.Value : 0;
  249. tmidStics.points.balance = (usersPoints != null) ? usersPoints.Properties["Balance"].Int32Value.Value : 0;
  250. }
  251. //個人服務授權
  252. if (eventList.Contains("prod"))
  253. {
  254. tmidStics.prod = await getTMIDAuthService(cosmosClientCsv2, id, "", true);
  255. }
  256. //IOT
  257. if (eventList.Contains("iot"))
  258. {
  259. tmidStics.iot.hiteach.year = null;
  260. tmidStics.iot.hiteach.month = null;
  261. tmidStics.iot.hiteach.day = null;
  262. if (!string.IsNullOrWhiteSpace(dateFromStr) && !string.IsNullOrWhiteSpace(dateToStr) && !string.IsNullOrWhiteSpace(dateUnit))
  263. {
  264. if (dateUnit.ToLower().Equals("year"))
  265. {
  266. tmidStics.iot.hiteach.year = await getTMIDIotData(cosmosClientIes5, id, "HiTeach", "year", y, 0, 0, dateTimeFromSec, dateTimeToSec);
  267. tmidStics.iot.hiteachcc.year = await getTMIDIotData(cosmosClientIes5, id, "HiTeachCC", "year", y, 0, 0, dateTimeFromSec, dateTimeToSec);
  268. }
  269. else if (dateUnit.ToLower().Equals("month"))
  270. {
  271. tmidStics.iot.hiteach.month = await getTMIDIotData(cosmosClientIes5, id, "HiTeach", "month", y, m, 0, dateTimeFromSec, dateTimeToSec);
  272. tmidStics.iot.hiteachcc.month = await getTMIDIotData(cosmosClientIes5, id, "HiTeachCC", "month", y, m, 0, dateTimeFromSec, dateTimeToSec);
  273. }
  274. else if (dateUnit.ToLower().Equals("day"))
  275. {
  276. tmidStics.iot.hiteach.day = await getTMIDIotData(cosmosClientIes5, id, "HiTeach", "day", y, m, d, dateTimeFromSec, dateTimeToSec);
  277. tmidStics.iot.hiteachcc.day = await getTMIDIotData(cosmosClientIes5, id, "HiTeachCC", "day", y, m, d, dateTimeFromSec, dateTimeToSec);
  278. }
  279. }
  280. else
  281. {
  282. tmidStics.iot.hiteach.year = await getTMIDIotData(cosmosClientIes5, id, "HiTeach", "year", y, 0, 0, dateTimeFromSec, dateTimeToSec);
  283. tmidStics.iot.hiteach.month = await getTMIDIotData(cosmosClientIes5, id, "HiTeach", "month", y, m, 0, dateTimeFromSec, dateTimeToSec);
  284. tmidStics.iot.hiteach.day = await getTMIDIotData(cosmosClientIes5, id, "HiTeach", "day", y, m, d, dateTimeFromSec, dateTimeToSec);
  285. tmidStics.iot.hiteachcc.year = await getTMIDIotData(cosmosClientIes5, id, "HiTeachCC", "year", y, 0, 0, dateTimeFromSec, dateTimeToSec);
  286. tmidStics.iot.hiteachcc.month = await getTMIDIotData(cosmosClientIes5, id, "HiTeachCC", "month", y, m, 0, dateTimeFromSec, dateTimeToSec);
  287. tmidStics.iot.hiteachcc.day = await getTMIDIotData(cosmosClientIes5, id, "HiTeachCC", "day", y, m, d, dateTimeFromSec, dateTimeToSec);
  288. }
  289. }
  290. }
  291. //IES5
  292. if (eventList.Contains("ies5"))
  293. {
  294. query = new QueryDefinition(@"SELECT c.id, c.defaultSchool, c.schools FROM c WHERE ARRAY_CONTAINS(@key, c.id)")
  295. .WithParameter("@key", tmidDic.Keys.ToList());
  296. await foreach (var item in cosmosClientIes5
  297. .GetContainer(Constant.TEAMModelOS, "Teacher")
  298. .GetItemQueryStreamIterator(query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base") }))
  299. {
  300. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  301. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  302. {
  303. foreach (var doc in json.RootElement.GetProperty("Documents").EnumerateArray())
  304. {
  305. string id = doc.GetProperty("id").GetString();
  306. TmidStics tmidStics = tmidDic[id];
  307. //IES5學校資訊
  308. string defaultschool = (doc.TryGetProperty("defaultSchool", out JsonElement _defaultSchool)) ? _defaultSchool.ToString() : string.Empty; //預設學校
  309. List<string> schoolIds = new List<string>();
  310. if (doc.TryGetProperty("schools", out JsonElement schoolsJobj))
  311. {
  312. foreach (var obj in schoolsJobj.EnumerateArray())
  313. {
  314. string schoolCodeNow = $"{obj.GetProperty("schoolId")}";
  315. string status = $"{obj.GetProperty("status")}";
  316. if (status.Equals("join"))
  317. {
  318. schoolIds.Add(schoolCodeNow); //放入學校ID列,一次取
  319. }
  320. }
  321. }
  322. if (schoolIds.Count > 0)
  323. {
  324. QueryDefinition querysc = new QueryDefinition(@"SELECT c.id, c.name, c.region, c.province, c.city, c.dist, c.size, c.period FROM c WHERE ARRAY_CONTAINS(@key, c.id)")
  325. .WithParameter("@key", schoolIds);
  326. await foreach (var itemsc in cosmosClientIes5
  327. .GetContainer(Constant.TEAMModelOS, "School")
  328. .GetItemQueryStreamIterator(querysc, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base") }))
  329. {
  330. using var jsonsc = await JsonDocument.ParseAsync(itemsc.ContentStream);
  331. if (jsonsc.RootElement.TryGetProperty("_count", out JsonElement countsc) && countsc.GetUInt16() > 0)
  332. {
  333. foreach (var school in jsonsc.RootElement.GetProperty("Documents").EnumerateArray())
  334. {
  335. string schoolCodeNow = school.GetProperty("id").GetString();
  336. //當前學年 ※若有多學段,取第一個學段來取得學年資訊吧
  337. Period period = school.GetProperty("period").Deserialize<List<Period>>().First();
  338. var info = SchoolService.GetSemester(period, 0, DateTime.Now.ToString());
  339. int studyYear = info.studyYear;
  340. //學校Blob使用狀況
  341. (long usedSize, long teach, long total, long surplus, Dictionary<string, double?> catalog) schoolUsedBlob = await BlobService.GetSurplusSpace(schoolCodeNow, "school", _option.Location, _azureCosmos, _azureRedis, _azureStorage, _dingDing, _httpTrigger);
  342. //老師在此學校的課程數 ※只取當前學年
  343. int courseCnt = 0;
  344. var queryCrs = $"SELECT VALUE COUNT(1) FROM ( SELECT DISTINCT VALUE(c.id) FROM c JOIN schedules IN c.schedules WHERE schedules.teacherId = '{id}' AND c.year = {studyYear} )";
  345. await foreach (int itemCrs in cosmosClientIes5.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<int>(queryText: queryCrs, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"CourseTask-{schoolCodeNow}") }))
  346. {
  347. courseCnt = itemCrs;
  348. }
  349. //IES5學校資料製作
  350. TmidSticsIes5School schoolobj = new TmidSticsIes5School();
  351. long ssize = (school.TryGetProperty("size", out JsonElement ssizeJson)) ? ssizeJson.GetInt32() : 0;
  352. long sused = schoolUsedBlob.usedSize + schoolUsedBlob.teach * 1073741824;
  353. long stotal = ssize * 1073741824;
  354. object schzize = new
  355. {
  356. used = sused,
  357. total = stotal,
  358. avaliable = stotal - sused,
  359. };
  360. schoolobj.schoolId = schoolCodeNow;
  361. schoolobj.name = school.GetProperty("name").GetString();
  362. schoolobj.region = school.GetProperty("region").GetString();
  363. schoolobj.province = school.GetProperty("province").GetString();
  364. schoolobj.city = school.GetProperty("city").GetString();
  365. schoolobj.dist = school.GetProperty("dist").GetString();
  366. schoolobj.size = schzize;
  367. schoolobj.courseCnt = courseCnt;
  368. schoolobj.defaultSchool = (!string.IsNullOrWhiteSpace(defaultschool) && defaultschool.Equals(schoolCodeNow)) ? true : false;
  369. tmidStics.ies5.schools.Add(schoolobj);
  370. }
  371. }
  372. }
  373. }
  374. //IES5個人空間
  375. var (usedSize, teach, total, surplus, catalog) = await BlobService.GetSurplusSpace(id, "private", _option.Location, _azureCosmos, _azureRedis, _azureStorage, _dingDing, _httpTrigger);
  376. tmidStics.ies5.usedSize = usedSize;
  377. tmidStics.ies5.teachSize = teach * 1073741824;
  378. tmidStics.ies5.totalSize = total * 1073741824;
  379. tmidStics.ies5.surplusSize = surplus;
  380. //IES5個人資源數
  381. tmidStics.ies5.resCount = 0; //教材數
  382. tmidStics.ies5.itemCount = 0; //題目數
  383. tmidStics.ies5.paperCount = 0; //試卷數
  384. ///IES5個人題目數
  385. await foreach (int itemC in cosmosClientIes5.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<int>(queryText: $"SELECT VALUE COUNT(1) FROM c WHERE c.pid = null", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{id}") }))
  386. {
  387. tmidStics.ies5.itemCount = itemC;
  388. }
  389. ///IES5個人試卷數
  390. await foreach (int paperC in cosmosClientIes5.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<int>(queryText: $"SELECT VALUE COUNT(1) FROM c WHERE c.scope = 'private'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Paper-{id}") }))
  391. {
  392. tmidStics.ies5.paperCount = paperC;
  393. }
  394. ///IES5個人教材數
  395. List<BlobService.BlobCount> blogCountList = await BlobService.BloblogCount(cosmosClientIes5, "private", id, "", "");
  396. foreach (BlobService.BlobCount blobCountRow in blogCountList)
  397. {
  398. switch (blobCountRow.type)
  399. {
  400. case "doc":
  401. case "image":
  402. case "res":
  403. case "video":
  404. case "audio":
  405. case "other":
  406. tmidStics.ies5.resCount += blobCountRow.count;
  407. break;
  408. }
  409. }
  410. if (!tmidDic.ContainsKey(id)) tmidDic.Add(id, tmidStics);
  411. }
  412. }
  413. }
  414. }
  415. //個人權益
  416. if (eventList.Contains("benefits"))
  417. {
  418. query = new QueryDefinition(@"SELECT * FROM c WHERE (ARRAY_CONTAINS(@key, c.id))")
  419. .WithParameter("@key", tmidDic.Keys.ToList());
  420. await foreach (var item in cosmosClientCsv2
  421. .GetContainer("Core", "ID2")
  422. .GetItemQueryStreamIterator(query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("benefits") }))
  423. {
  424. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  425. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  426. {
  427. foreach (var doc in json.RootElement.GetProperty("Documents").EnumerateArray())
  428. {
  429. string id = doc.GetProperty("id").GetString();
  430. if (doc.TryGetProperty("hiteach", out var elementHiteachData))
  431. {
  432. tmidDic[id].benefits.hiteach = elementHiteachData.ToObject<List<object>>();
  433. }
  434. if (doc.TryGetProperty("hiteachcc", out var elementHiteachCCData))
  435. {
  436. tmidDic[id].benefits.hiteachcc = elementHiteachCCData.ToObject<List<object>>();
  437. }
  438. }
  439. }
  440. }
  441. }
  442. //蘇格拉底資料
  443. if (eventList.Contains("sokrates"))
  444. {
  445. query = new QueryDefinition(@"SELECT * FROM c WHERE (ARRAY_CONTAINS(@key, c.id))")
  446. .WithParameter("@key", tmidDic.Keys.ToList());
  447. await foreach (var item in cosmosClientCsv2
  448. .GetContainer("Core", "ID2")
  449. .GetItemQueryStreamIterator(query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("sokrates") }))
  450. {
  451. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  452. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  453. {
  454. foreach (var doc in json.RootElement.GetProperty("Documents").EnumerateArray())
  455. {
  456. string id = doc.GetProperty("id").GetString();
  457. if (doc.TryGetProperty("hiteach_data", out var elementHiteachData))
  458. {
  459. tmidDic[id].sokrates.hiteach_data = elementHiteachData.ToObject<object>();
  460. }
  461. if (doc.TryGetProperty("user_channels", out var elementUserChannels))
  462. {
  463. tmidDic[id].sokrates.user_channels = elementUserChannels.ToObject<object>();
  464. }
  465. }
  466. }
  467. }
  468. }
  469. //輸出
  470. List<object> data = new();
  471. foreach (KeyValuePair<string, TmidStics> dicItem in tmidDic)
  472. {
  473. data.Add(dicItem.Value);
  474. }
  475. return Ok(data);
  476. }
  477. catch (Exception ex)
  478. {
  479. //await _dingDing.SendBotMsg($"BI,{_option.Location} /tmid/get-tmidstics \n {ex.Message}\n{ex.StackTrace}", GroupNames.台北開發測試群組);
  480. return BadRequest();
  481. }
  482. }
  483. //取得TMID服務授權週期
  484. public async Task<List<object>> getTMIDAuthService(CosmosClient cosmosClientCsv2, string tmid, string prodCode, bool validFlg)
  485. {
  486. long now = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
  487. var qryOption = new QueryRequestOptions() { PartitionKey = new PartitionKey("servicePeriod") };
  488. string whereSql = $"c.saleClient.tmid = '{tmid}'";
  489. if (!string.IsNullOrWhiteSpace(prodCode)) whereSql += $" AND c.prodCode = '{prodCode}'";
  490. if (validFlg) whereSql += $" AND c.startDate <= {now} AND {now} <= c.endDate";
  491. string sql = $"SELECT c.id, c.prodCode, c.type, c.startDate, c.endDate, c.number, c.unit, c.aprule FROM c WHERE {whereSql}";
  492. var client = cosmosClientCsv2.GetContainer("Habb", "Auth");
  493. var result = new List<object>();
  494. await foreach (var item in client.GetItemQueryStreamIterator(queryText: sql, requestOptions: qryOption))
  495. {
  496. var json = await JsonDocument.ParseAsync(item.ContentStream);
  497. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  498. {
  499. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  500. {
  501. result.Add(
  502. new
  503. {
  504. id = obj.GetProperty("id").GetString(),
  505. prodCode = obj.GetProperty("prodCode").GetString(),
  506. type = obj.GetProperty("type").GetInt32(),
  507. startDate = obj.GetProperty("startDate").GetInt64(),
  508. endDate = obj.GetProperty("endDate").GetInt64(),
  509. number = obj.GetProperty("number").GetInt32(),
  510. aprule = obj.GetProperty("aprule")
  511. });
  512. }
  513. }
  514. }
  515. return result;
  516. }
  517. //取得TMID購買紀錄
  518. public async Task<List<Ies5OrderHis>> getTMIDAuthOrder(CosmosClient cosmosClientCsv2, string tmid, string prodCode)
  519. {
  520. SortedDictionary<string, Ies5OrderHis> OrderDic = new SortedDictionary<string, Ies5OrderHis>();
  521. var qryOption = new QueryRequestOptions() { PartitionKey = new PartitionKey("order") };
  522. //服務 ※序號、硬體 不列入購買紀錄
  523. string strQueryV = $"SELECT * FROM c WHERE IS_DEFINED(c.saleClient.tmid) AND c.saleClient.tmid = '{tmid}' AND c.prodType = 'service'";
  524. if (!string.IsNullOrWhiteSpace(prodCode))
  525. {
  526. strQueryV += $" AND c.prodCode = '{prodCode}'";
  527. }
  528. await foreach (OrderHisService orderService in cosmosClientCsv2.GetContainer("Habb", "Auth").GetItemQueryIterator<OrderHisService>(strQueryV, null, qryOption))
  529. {
  530. Ies5OrderHisService ies5OrderVRow = new Ies5OrderHisService();
  531. ies5OrderVRow.prodCode = orderService.prodCode;
  532. ies5OrderVRow.type = (orderService.contract.Equals(1)) ? "C" : (orderService.contract.Equals(2)) ? "G" : "N"; //授權方式 [FROM]contract契約型態 0:新約 1:續約 2:變更 [TO]type N:新約 C:續約 G:變更
  533. ies5OrderVRow.sdate = orderService.startDate;
  534. ies5OrderVRow.edate = orderService.endDate;
  535. ies5OrderVRow.number = orderService.number;
  536. ies5OrderVRow.unit = orderService.unit;
  537. //加入Order字典
  538. string OrderID = orderService.orderinfo.orderid.ToString();
  539. long OrderDate = orderService.orderinfo.createDate;
  540. if (OrderDic.ContainsKey(OrderID))
  541. {
  542. OrderDic[OrderID].service.Add(ies5OrderVRow);
  543. }
  544. else
  545. {
  546. Ies5OrderHis ies5OrderHisNew = new Ies5OrderHis();
  547. ies5OrderHisNew.id = OrderID;
  548. ies5OrderHisNew.date = OrderDate;
  549. ies5OrderHisNew.service.Add(ies5OrderVRow);
  550. OrderDic.Add(OrderID, ies5OrderHisNew);
  551. }
  552. }
  553. //輸出項
  554. List<Ies5OrderHis> Result = new List<Ies5OrderHis>();
  555. foreach (KeyValuePair<string, Ies5OrderHis> item in OrderDic)
  556. {
  557. Result.Add(item.Value);
  558. }
  559. return Result;
  560. }
  561. //Tool
  562. //資料遮罩
  563. ///規則:
  564. ///1.手機、電話:隱藏後4碼
  565. ///2.Mail:隱藏@前資料
  566. ///3.姓名:只顯示第一個字元
  567. ///4.身分證、護照:隱藏後4碼
  568. public string GenDataMask(string data, string type)
  569. {
  570. int length = 0;
  571. string subString = string.Empty;
  572. if (!string.IsNullOrWhiteSpace(data))
  573. {
  574. switch (type)
  575. {
  576. case "mobile":
  577. case "id":
  578. length = 4;
  579. subString = data.Substring(data.Length - length, length);
  580. data = data.Replace(subString, "****");
  581. break;
  582. case "mail":
  583. string[] dataList = data.Split("@");
  584. subString = dataList.First();
  585. data = data.Replace(subString, "****");
  586. break;
  587. case "name":
  588. length = 2;
  589. subString = data.Substring(data.Length - length, length);
  590. data = data.Replace(subString, "〇〇");
  591. break;
  592. }
  593. }
  594. return data;
  595. }
  596. public async Task<TmidAnalysisCal> getTMIDIotData(CosmosClient cosmosClientIes5, string tmid, string toolType, string dateUnit, int year, int month, int day, long from, long to)
  597. {
  598. TmidAnalysisCal result = new TmidAnalysisCal();
  599. List<string> calPropList = new List<string>() { "lessonRecord", "useIES", "useIES5Resource", "useWebIrs", "useDeviceIrs", "useHaboard", "useHita", "lessonLengMin", "lessonLeng0", "stuShow", "stuLessonLengMin", "tGreen", "tLesson", "lTypeCoop", "lTypeIact", "lTypeMis", "lTypeTst", "lTypeDif", "lTypeNone", "lessonCnt928", "lessonCntId", "lessonCntDevice", "lessonCntIdDevice", "mission", "missionFin", "item", "interact", "sendSok" }; //要計算的ProdAnalysis欄位列表
  600. string strQuery = $"SELECT * FROM c WHERE c.tmid = '{tmid}' AND c.toolType = '{toolType}'";
  601. var qryOption = new QueryRequestOptions() { PartitionKey = new PartitionKey("TmidAnalysis") };
  602. if (!string.IsNullOrWhiteSpace(dateUnit)) strQuery += $" AND c.dateUnit = '{dateUnit}'";
  603. if (year > 0) strQuery += $" AND c.year = {year}";
  604. if (month > 0) strQuery += $" AND c.month = {month}";
  605. if (day > 0) strQuery += $" AND c.day = {day}";
  606. if (from > 0) strQuery += $" AND c.dateTime >= {from}";
  607. if (to > 0) strQuery += $" AND c.dateTime <= {to}";
  608. await foreach (TmidAnalysisCosmos tmidAnalysis in cosmosClientIes5.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<TmidAnalysisCosmos>(strQuery, null, qryOption))
  609. {
  610. //一般項
  611. result.tmid = tmidAnalysis.tmid;
  612. result.dateUnit = tmidAnalysis.dateUnit;
  613. result.toolType = tmidAnalysis.toolType;
  614. result.date = tmidAnalysis.date;
  615. if (tmidAnalysis.year > 0) result.year = tmidAnalysis.year;
  616. if (tmidAnalysis.month > 0) result.month = tmidAnalysis.month;
  617. if (tmidAnalysis.day > 0) result.day = tmidAnalysis.day;
  618. if (result.from.Equals(0) || tmidAnalysis.dateTime <= result.from) result.from = tmidAnalysis.dateTime;
  619. if (result.to.Equals(0) || tmidAnalysis.dateTime >= result.to) result.to = tmidAnalysis.dateTime;
  620. result.dateList.Add(tmidAnalysis.date);
  621. //統計項
  622. foreach (PropertyInfo propertyInfo in tmidAnalysis.GetType().GetProperties()) //累加項目
  623. {
  624. if (calPropList.Contains(propertyInfo.Name))
  625. {
  626. var propType = propertyInfo.PropertyType;
  627. var valNow = propertyInfo.GetValue(result);
  628. var valTodo = tmidAnalysis.GetType().GetProperty(propertyInfo.Name).GetValue(tmidAnalysis);
  629. if (propType.Equals(typeof(long))) propertyInfo.SetValue(result, Convert.ToInt64(valNow.ToString(), 10) + Convert.ToInt64(valTodo.ToString(), 10));
  630. else propertyInfo.SetValue(result, Convert.ToInt32(valNow.ToString(), 10) + Convert.ToInt32(valTodo.ToString(), 10));
  631. }
  632. }
  633. result.deviceList = result.deviceList.Union(tmidAnalysis.deviceList).ToList();
  634. result.deviceCnt = result.deviceList.Count;
  635. result.deviceNoAuthList = result.deviceNoAuthList.Union(tmidAnalysis.deviceNoAuthList).ToList();
  636. result.deviceNoAuth = result.deviceNoAuthList.Count;
  637. result.deviceAuthList = result.deviceAuthList.Union(tmidAnalysis.deviceAuthList).ToList();
  638. result.deviceAuth = result.deviceAuthList.Count;
  639. result.tmidList = result.tmidList.Union(tmidAnalysis.tmidList).ToList();
  640. result.tmidCnt = result.tmidList.Count;
  641. result.verList = result.verList.Union(tmidAnalysis.verList).ToList();
  642. }
  643. if (string.IsNullOrWhiteSpace(result.tmid)) result = null;
  644. return result;
  645. }
  646. //Model
  647. //TMID統計 基本資訊
  648. private class TmidStics
  649. {
  650. public string id { get; set; }
  651. public string name { get; set; }
  652. public string picture { get; set; }
  653. public string mobile { get; set; }
  654. public string mail { get; set; }
  655. public string country { get; set; }
  656. public string province { get; set; }
  657. public string city { get; set; }
  658. public string dist { get; set; }
  659. public string schoolCode { get; set; }
  660. public string schoolCodeW { get; set; }
  661. public string lang { get; set; }
  662. public string unitType { get; set; } //1:基礎教育機構(K-小學) 2:中等教育機構(國中、高中/職) 3:高等教育機構 4:政府單位機構 5:NGO機構 6:企業機構 7:其他 8:學前教育 9:特殊教育
  663. public string unitName { get; set; }
  664. public string jobTitle { get; set; }
  665. public TmidSticsIes5 ies5 { get; set; } //IES統計資料
  666. public TmidPoints points { get; set; }
  667. public TmidSokrates sokrates { get; set; }
  668. public TmidBenefits benefits { get; set; }
  669. public List<TmidCoupon> coupons { get; set; } = new();
  670. public List<TmidLoginTime> login { get; set; } = new();
  671. public List<object> prod { get; set; } = new();
  672. public TmidIot iot { get; set; }
  673. public bool wechat { get; set; }
  674. public bool facebook { get; set; }
  675. public bool google { get; set; }
  676. public bool ding { get; set; }
  677. public bool apple { get; set; }
  678. public bool educloudtw { get; set; }
  679. public long ts { get; set; } //資料最終變更時間
  680. }
  681. //TMID統計 IES5資訊
  682. private class TmidSticsIes5
  683. {
  684. public long usedSize { get; set; } //已使用的存儲空間(Byte)
  685. public long teachSize { get; set; } //分配給教師的空間(Byte)
  686. public long totalSize { get; set; } //總空間(Byte)
  687. public long surplusSize { get; set; } //剩余的空間(Byte)
  688. public List<TmidSticsIes5School> schools { get; set; } = new(); //各學校資料
  689. public int resCount { get; set; } //教材數
  690. public int itemCount { get; set; } //題目數
  691. public int paperCount { get; set; } //試卷數
  692. }
  693. private class TmidSticsIes5School
  694. {
  695. public string schoolId { get; set; }
  696. public string name { get; set; }
  697. public string region { get; set; }
  698. public string province { get; set; }
  699. public string city { get; set; }
  700. public string dist { get; set; }
  701. public object size { get; set; } = new();
  702. public int courseCnt { get; set; }
  703. public bool defaultSchool { get; set; }
  704. }
  705. private class TmidPoints
  706. {
  707. public int points { get; set; } = 0; //累積的點數(只加不減)
  708. public int balance { get; set; } = 0; //可用的點數
  709. public int level { get; set; } = 0; //等級
  710. }
  711. private class TmidCoupon
  712. {
  713. public string code { get; set; }
  714. public long exchange { get; set; }
  715. }
  716. private class TmidLoginTime
  717. {
  718. public string product { get; set; }
  719. public long time { get; set; }
  720. }
  721. private class TmidSokrates
  722. {
  723. public object hiteach_data { get; set; }
  724. public object user_channels { get; set; }
  725. }
  726. private class TmidBenefits
  727. {
  728. public List<object> hiteach { get; set; }
  729. public List<object> hiteachcc { get; set; }
  730. }
  731. private class TmidIot
  732. {
  733. public TmidIotYMD hiteach { get; set; } = new();
  734. public TmidIotYMD hiteachcc { get; set; } = new();
  735. }
  736. private class TmidIotYMD
  737. {
  738. public TmidAnalysisCal year { get; set; }
  739. public TmidAnalysisCal month { get; set; }
  740. public TmidAnalysisCal day { get; set; }
  741. }
  742. //[API輸出] 訂單履歷
  743. public class Ies5OrderHis
  744. {
  745. public Ies5OrderHis()
  746. {
  747. service = new List<Ies5OrderHisService>();
  748. }
  749. public string id { get; set; }
  750. public long date { get; set; }
  751. public List<Ies5OrderHisService> service { get; set; } = new ();
  752. }
  753. //[API輸出] 訂單履歷.服務型產品
  754. public class Ies5OrderHisService
  755. {
  756. public string prodCode { get; set; } //產品代碼
  757. public string type { get; set; } //授權方式 N:新約 C:續約
  758. public long sdate { get; set; } //授權起始時間
  759. public long edate { get; set; } //授權終止時間
  760. public int number { get; set; } //購買數量
  761. public string unit { get; set; } //購買單位 無單位者為null
  762. }
  763. //[承接DB] DB: Habb.Auth
  764. //[承接DB] 訂單履歷基本Class
  765. public class OrderHisBase
  766. {
  767. public string id { get; set; } //OPID
  768. public OrderHisOrderInfo orderinfo { get; set; } //訂單資訊
  769. public string prodCode { get; set; } //產品代碼
  770. public SerialSaleClient saleClient { get; set; } = null; //銷售終端
  771. public string prodType { get; set; } //產品類型 serial:序號 service:服務 hard:硬體
  772. public string dataType { get; set; } //資料類型
  773. public long operationTime { get; set; } //最新資料變更時間戳記
  774. public int ttl { get; set; } = -1; //過期刪除秒數
  775. }
  776. //[承接DB] 訂單履歷基本Class.銷售終端
  777. public class SerialSaleClient
  778. {
  779. public string name { get; set; } //[String]銷售終端姓名
  780. public string schoolCode { get; set; } = null; //[String]銷售終端學校代碼
  781. public string clientId { get; set; } = null; //[String]銷售終端客戶ID
  782. public string tmid { get; set; } = null; //[String]TMID
  783. public string type { get; set; } //[String]銷售終端資料類型 school:學校 client:經銷商客戶
  784. public string countryId { get; set; } //[String]國家代碼
  785. public string provinceId { get; set; } //[String]省代碼
  786. public string cityId { get; set; } //[String]市代碼
  787. public string schoolShortCode { get; set; } //[String]學校簡碼
  788. public string districtId { get; set; } //[String]區代碼
  789. public string dataCenter { get; set; } //[String]數據中心
  790. }
  791. //[承接DB] 訂單履歷基本Class.訂單資訊
  792. public class OrderHisOrderInfo
  793. {
  794. public string orderid { get; set; } //[String]訂單編號
  795. public int orderAudit { get; set; } //[Int]訂單審核狀態 0:待審, 1:通過, 2:否決, 3:問題
  796. public int orderProperty { get; set; } //[Int]訂單類型 0:銷售,1:展示申請 2:內部申請
  797. public long createDate { get; set; } //訂單創建時間
  798. }
  799. //[承接DB] 訂單履歷 服務類
  800. public class OrderHisService : OrderHisBase
  801. {
  802. public int type { get; set; } //[Int]授權類型 0:銷售 1:試用
  803. public int contract { get; set; } //[Int]契約型態 0:新約 1:續約
  804. public long startDate { get; set; } //[long]授權起始日期 Timestamp(UTC)
  805. public long endDate { get; set; } //[long]授權終止日期 Timestamp(UTC)
  806. public int number { get; set; } //[Int]數量
  807. public string unit { get; set; } //[String]單位 (無者為空)
  808. }
  809. //雲端服務ClientId列表
  810. private readonly Dictionary<string, string> _dicClientIds = new()
  811. {
  812. { "917d02f2-5b91-404e-a71d-7bdd926ddd81", "HiTeach" },
  813. { "c5328340-b8eb-4489-8650-8c8862d7acfe", "HiTeach" },
  814. { "118d2d4d-32a3-44c0-808a-792ca73d3706", "HiTeachCC" },
  815. { "227082f4-8db0-4517-b281-93dba9428bc7", "HiTeachCC" },
  816. { "371a99aa-7efd-4c3a-90a8-95b7db4f42c0", "HiTA" },
  817. { "0ed38cde-e7fe-4fa6-9eaa-33ad404eb532", "HiTA" },
  818. { "531fecd1-b1a5-469a-93ca-7984e1d392f2", "IES5" },
  819. { "c7317f88-7cea-4e48-ac57-a16071f7b884", "IES5" },
  820. { "c8de822b-3fcf-4831-adba-cdd14653bf7f", "Account" },
  821. { "516148eb-6a38-4657-ba98-a3699061937f", "Account" },
  822. { "d7193896-9b12-4046-ad44-c991dd48cc39", "Sokrates" },
  823. { "59009e38-6e30-4116-814b-7605939edc47", "Sokrates" },
  824. { "626c7285-15aa-4abe-8c0d-2c5ff1381538", "SokAPP" },
  825. { "5bcc16a5-7d20-4cc4-b5c2-8ed0416f32b6", "SokAPP" },
  826. { "044482b5-d024-4f23-9b55-906884243405", "IRS" },
  827. { "5e27b7e3-b36c-4ce9-b838-e94fd0cea080", "IRS" }
  828. };
  829. //TMID IOT date
  830. public class tmidIotDate
  831. {
  832. public string dateUnit { get; set; } //[string]日期單位:年月日 year, month, day
  833. public int year { get; set; } //[Int]年
  834. public int month { get; set; } //[Int]月
  835. public int day { get; set; } //[Int]日
  836. public long from { get; set; } //[long]UTC timestamp 起始日
  837. public long to { get; set; } //[long]UTC timestamp 終止日
  838. }
  839. public class TmidAnalysisCal : TmidAnalysisCosmos
  840. {
  841. public long from { get; set; } //[long]UTC timestamp 起始日
  842. public long to { get; set; } //[long]UTC timestamp 終止日
  843. public List<string> dateList { get; set; } = new();
  844. }
  845. }
  846. }