Downloader.cs 71 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736
  1. using Newtonsoft.Json;
  2. using System;
  3. using System.Net.Http;
  4. using System.Net.Http.Headers;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using System.Timers;
  8. using System.Linq;
  9. using Dfs.WayneChina.SpsDataCourier.HostModels;
  10. using Dfs.WayneChina.SpsDataCourier.Guard;
  11. using System.Collections.Generic;
  12. using Dfs.WayneChina.SpsDataCourier.SpsData;
  13. using Microsoft.EntityFrameworkCore;
  14. namespace Dfs.WayneChina.SpsDataCourier
  15. {
  16. public class Downloader
  17. {
  18. #region Fields
  19. private Timer _timer;
  20. private readonly int _interval;
  21. private readonly ConnectionInfo _connectionInfo;
  22. private HttpClient _client = new HttpClient();
  23. private string grantType = "password";
  24. private string tokenAuthPath = "token";
  25. private string authScheme = "bearer";
  26. private AuthToken currentAuthToken;
  27. private string _spsDbConnString;
  28. private long? localVersion = null;
  29. private readonly DbMonitor _dbMonitor;
  30. private readonly string _checkVersionRelativeUrl;
  31. private readonly string _syncDataRelativeUrl;
  32. private bool _excludeCurrentSite = false;
  33. #endregion
  34. #region Logger
  35. static NLog.Logger logger = NLog.LogManager.LoadConfiguration("NLog.config").GetLogger("SpsDataCourier");
  36. #endregion
  37. #region Constructor
  38. public Downloader(ConnectionInfo connectionInfo, DbMonitor dbMonitor, string spsConnString, int interval,
  39. string versionRelativeUrl, string dataRelativeUrl, bool excludeCurrentSite)
  40. {
  41. _connectionInfo = connectionInfo;
  42. _dbMonitor = dbMonitor;
  43. _spsDbConnString = spsConnString;
  44. _interval = interval;
  45. _checkVersionRelativeUrl = versionRelativeUrl;
  46. _syncDataRelativeUrl = dataRelativeUrl;
  47. _excludeCurrentSite = excludeCurrentSite;
  48. }
  49. #endregion
  50. #region Start
  51. public void Start()
  52. {
  53. _timer = new Timer();
  54. _timer.Interval = _interval * 1000;
  55. _timer.Elapsed += DownloadTimerElapsed;
  56. _timer.Start();
  57. }
  58. #endregion
  59. #region Stop
  60. public void Stop()
  61. {
  62. if (_timer != null)
  63. {
  64. _timer.Elapsed -= DownloadTimerElapsed;
  65. _timer.Close();
  66. }
  67. }
  68. #endregion
  69. #region Timer elapsed event
  70. /// <summary>
  71. /// 同步云端定时器
  72. /// </summary>
  73. /// <param name="sender"></param>
  74. /// <param name="e"></param>
  75. private async void DownloadTimerElapsed(object sender, ElapsedEventArgs e)
  76. {
  77. logger.Info("Downloader timer elapsed");
  78. _timer.Stop();
  79. //优先上传
  80. var count = await CheckPendingUpload();
  81. if (count > 0)
  82. {
  83. logger.Info($"There are {count} accounts or cards updated, wait for them to be uploaded first!");
  84. _timer.Start();
  85. return;
  86. }
  87. else
  88. {
  89. await CheckHostDataVersionAsync();
  90. _timer.Start();
  91. }
  92. }
  93. #endregion
  94. #region Check pending account updates
  95. private Task<int> CheckPendingUpload()
  96. {
  97. using (var context = new SpsDbContext(_spsDbConnString))
  98. {
  99. var records = context.TTableaudit
  100. .Where(e => e.AccountUpdated.HasValue && e.AccountUpdated.Value != 0 ||
  101. e.CardInfoUpdated.HasValue && e.CardInfoUpdated.Value != 0)
  102. .ToList();
  103. logger.Info($"Before download, Accounts updated count: " +
  104. $"{records.Count(r => r.AccountUpdated.HasValue && r.AccountUpdated.Value != 0)}");
  105. logger.Info($"Before download, Cards updated count: " +
  106. $"{records.Count(r => r.CardInfoUpdated.HasValue && r.CardInfoUpdated.Value != 0)}");
  107. return Task.FromResult(records.Count);
  108. }
  109. }
  110. #endregion
  111. #region Check host data version
  112. private async Task CheckHostDataVersionAsync()
  113. {
  114. if (currentAuthToken != null && currentAuthToken.IsTokenValid())
  115. {
  116. using (var context = new GuardDbContext())
  117. {
  118. var currentVersion = context.DataVersion
  119. .OrderByDescending(v => v.LastUpdate).FirstOrDefault();
  120. if (currentVersion != null)
  121. {
  122. localVersion = currentVersion.VersionNo;
  123. logger.Info($"Setting local version to {localVersion}");
  124. logger.Info($"Current local version: {currentVersion.VersionNo}");
  125. await CheckVersionStartDownloadAsync(currentVersion.VersionNo);
  126. }
  127. else if(currentVersion == null)
  128. {
  129. logger.Info($"Local version does not exist!");
  130. await CheckVersionStartDownloadAsync(0);
  131. }
  132. }
  133. }
  134. else
  135. {
  136. logger.Info("No valid token now, start to get it.");
  137. await GetTokenAsync(_connectionInfo.UserName, _connectionInfo.Password, _connectionInfo.AuthServiceBaseUrl);
  138. }
  139. }
  140. #endregion
  141. #region Compare version and start download
  142. private async Task CheckVersionStartDownloadAsync(long versionNo)
  143. {
  144. var hostVersionInfo = await GetDataVersionAsync(versionNo);
  145. if (hostVersionInfo != null)
  146. {
  147. logger.Info($"Host data version: {hostVersionInfo.VersionNo}");
  148. long innerDataVersion = 0;
  149. if (hostVersionInfo.VersionNo != versionNo)
  150. {
  151. _dbMonitor.Stop(); // stop for a while
  152. innerDataVersion = await DownloadDataAsync(versionNo);
  153. logger.Info($"Inner data version: {innerDataVersion}");
  154. }
  155. if (innerDataVersion != 0)
  156. {
  157. logger.Info($"Inner data version: {innerDataVersion}, host data version: {hostVersionInfo.VersionNo}");
  158. hostVersionInfo.VersionNo = innerDataVersion;
  159. }
  160. await SaveHostVersion(hostVersionInfo);
  161. _dbMonitor.Start();
  162. localVersion = hostVersionInfo.VersionNo;
  163. }
  164. }
  165. /// <summary>
  166. /// 数据版本同步
  167. /// </summary>
  168. /// <param name="versionNo"></param>
  169. /// <returns></returns>
  170. private async Task<HostVersionInfo> GetDataVersionAsync(long versionNo)
  171. {
  172. string baseUrl = _connectionInfo.AccountServiceBaseUrl;
  173. //string accountingUrl = _connectionInfo.AccountServiceRelativeUrl;
  174. string versionUrl = string.Format(_checkVersionRelativeUrl + "?excludingCurrentBu={0}&versionNo={1}", _excludeCurrentSite, versionNo);
  175. string url = string.Concat(baseUrl, versionUrl);
  176. logger.Info($"Version url: {url}");
  177. _client.DefaultRequestHeaders.Clear();
  178. _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(authScheme, currentAuthToken.AccessToken);
  179. _client.DefaultRequestHeaders.Add("DeviceSN", _connectionInfo.DeviceSN);
  180. try
  181. {
  182. var versionResult = await _client.GetAsync(url).ConfigureAwait(false);
  183. if (versionResult.IsSuccessStatusCode)
  184. {
  185. HostVersionResult hostVersionResult = null;
  186. await versionResult.Content.ReadAsStringAsync().ContinueWith(x =>
  187. {
  188. hostVersionResult = JsonConvert.DeserializeObject<HostVersionResult>(x?.Result);
  189. });
  190. if (hostVersionResult != null && hostVersionResult.Result != null)
  191. {
  192. return hostVersionResult.Result;
  193. }
  194. }
  195. else
  196. {
  197. logger.Warn($"Get host version, status code: {versionResult.StatusCode}");
  198. var content = await versionResult.Content.ReadAsStringAsync();
  199. versionResult.Content?.Dispose();
  200. }
  201. }
  202. catch (Exception ex)
  203. {
  204. logger.Error(ex.ToString());
  205. }
  206. return null;
  207. }
  208. private async Task SaveHostVersion(HostVersionInfo hostVersionInfo)
  209. {
  210. try
  211. {
  212. using (var context = new GuardDbContext())
  213. {
  214. if (!context.DataVersion.Any(v => v.VersionNo == hostVersionInfo.VersionNo))
  215. {
  216. var version = new DataVersion();
  217. version.VersionNo = hostVersionInfo.VersionNo;
  218. version.CommitFlag = 1;
  219. version.LastUpdate = DateTime.Now;
  220. context.DataVersion.Add(version);
  221. await context.SaveChangesAsync();
  222. logger.Info($"Host version no: {hostVersionInfo.VersionNo}, saved into db");
  223. }
  224. }
  225. }
  226. catch (Exception ex)
  227. {
  228. logger.Error($"Exception in saving host version info: {ex.ToString()}");
  229. }
  230. }
  231. #endregion
  232. #region Download
  233. private async Task<long> DownloadDataAsync(long versionNo)
  234. {
  235. logger.Info("==============================");
  236. logger.Info($"Start data synchronizing, from local version: {versionNo}");
  237. string versionSyncRelativeUrl = string.Format(_syncDataRelativeUrl + "?versionNo={0}&excludingCurrentBu={1}", versionNo, _excludeCurrentSite);
  238. var url = string.Concat(_connectionInfo.AuthServiceBaseUrl, versionSyncRelativeUrl);
  239. _client.DefaultRequestHeaders.Clear();
  240. _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(authScheme, currentAuthToken.AccessToken);
  241. _client.DefaultRequestHeaders.Add("DeviceSN", _connectionInfo.DeviceSN);
  242. logger.Info($"sync data url: {url}");
  243. try
  244. {
  245. var response = await _client.GetAsync(url).ConfigureAwait(false);
  246. logger.Info($"Downloading finished, status code: {response.StatusCode}");
  247. HostDataResponse hostDataResponse = null;
  248. if (response.IsSuccessStatusCode)
  249. {
  250. await response.Content.ReadAsStringAsync().ContinueWith(x =>
  251. {
  252. logger.Info($"data response: {x?.Result}");
  253. hostDataResponse = JsonConvert.DeserializeObject<HostDataResponse>(x?.Result);
  254. });
  255. if (hostDataResponse != null && hostDataResponse.Result != null)
  256. {
  257. await SaveOfflineAccounts(hostDataResponse.Result.OfflineAccountInfoList, hostDataResponse.Result.VersionNo);
  258. logger.Info($"Saved account info at: {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}, " +
  259. $"total count: {hostDataResponse.Result.OfflineAccountInfoList?.Count}");
  260. await SaveOfflineCardInfoList(hostDataResponse.Result.OfflineCardInfoList, hostDataResponse.Result.VersionNo);
  261. logger.Info($"Saved card info at: {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}, " +
  262. $"total count: {hostDataResponse.Result.OfflineCardInfoList?.Count}");
  263. await SaveOfflineGrayInfoList(hostDataResponse.Result.OfflineGrayInfoList, hostDataResponse.Result.VersionNo);
  264. logger.Info($"Saved gray info at: {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}, " +
  265. $"total count: {hostDataResponse.Result.OfflineGrayInfoList?.Count}");
  266. await SaveOfflineBlackCardInfoList(hostDataResponse.Result.OfflineBlackCardInfoList, hostDataResponse.Result.VersionNo);
  267. logger.Info($"Saved black card info at: {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}, " +
  268. $"total count: {hostDataResponse.Result.OfflineBlackCardInfoList?.Count}");
  269. await SaveOfflineCardRepLossInfoList(hostDataResponse.Result.OfflineCardRepLossList,
  270. hostDataResponse.Result.VersionNo);
  271. logger.Info($"Saved CardRepLoss info at: {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}, " +
  272. $"total count: {hostDataResponse.Result.OfflineCardRepLossList?.Count}");
  273. var firstAccount = hostDataResponse?.Result?.OfflineAccountInfoList.FirstOrDefault();
  274. var firstCard = hostDataResponse?.Result?.OfflineCardInfoList.FirstOrDefault();
  275. var firstBlackCard = hostDataResponse?.Result?.OfflineBlackCardInfoList.FirstOrDefault();
  276. var firstGrayInfo = hostDataResponse?.Result?.OfflineGrayInfoList.FirstOrDefault();
  277. var firstCardRepLoss = hostDataResponse?.Result?.OfflineBlackCardInfoList.FirstOrDefault();
  278. logger.Info($"size: {hostDataResponse?.Result?.Size}, first account: {firstAccount?.acctID}, " +
  279. $"first card: {firstCard?.cardNo}, first black card: {firstBlackCard?.cardNo}," +
  280. $"first gray info: {firstGrayInfo?.cardNo}, first cardRepLoss info: {firstCardRepLoss?.cardNo}");
  281. return hostDataResponse.Result.VersionNo;
  282. }
  283. }
  284. else
  285. {
  286. var content = await response.Content.ReadAsStringAsync();
  287. response.Content?.Dispose();
  288. }
  289. }
  290. catch (Exception ex)
  291. {
  292. logger.Error(ex.ToString());
  293. }
  294. return versionNo;
  295. }
  296. #endregion
  297. #region Persist Offline AccountInfo
  298. private async Task SaveOfflineAccounts(List<OfflineAccountInfo> offlineAccountInfoList, long versionNo)
  299. {
  300. var accounts = new List<Account>();
  301. foreach (var accountInfo in offlineAccountInfoList)
  302. {
  303. var account = new Account();
  304. account.Gid = Convert.ToUInt64(accountInfo.gid);
  305. account.AccountSNo = accountInfo.acctSNo;
  306. account.SNo = accountInfo.sno;
  307. account.AccountId = accountInfo.acctID;
  308. account.AccountName = accountInfo.belongTo;
  309. account.Address = accountInfo.address;
  310. account.PhoneNo = accountInfo.phoneNo;
  311. account.AccountType = accountInfo.acctType;
  312. account.Amount = Convert.ToInt32(accountInfo.amount);
  313. account.AmountType = 0;
  314. account.FuelNo = accountInfo.fuelNo;
  315. account.Credit = accountInfo.gift;
  316. account.State = accountInfo.acctState;
  317. account.AccountDate = accountInfo.acctDate;
  318. account.CertType = accountInfo.certfType;
  319. account.CertNo = accountInfo.certfNo;
  320. account.RechargeTotal = accountInfo.rechgTotal;
  321. account.TMac = accountInfo.tmac;
  322. account.WaitMalloc = accountInfo.waitMalloc;
  323. account.EnableSms = accountInfo.enableSms;
  324. account.UploadFlag = accountInfo.uploadFlag;
  325. account.VersionNo = versionNo;
  326. account.LastUpdate = DateTime.Now;
  327. accounts.Add(account);
  328. }
  329. try
  330. {
  331. using (var context = new GuardDbContext())
  332. {
  333. context.Account.AddRange(accounts);
  334. await context.SaveChangesAsync();
  335. }
  336. await SaveToSpsDbAcctInfo(accounts);
  337. }
  338. catch (Exception ex)
  339. {
  340. logger.Error(ex.ToString());
  341. }
  342. }
  343. private async Task SaveToSpsDbAcctInfo(IEnumerable<Account> accounts)
  344. {
  345. var spsAccounts = ConvertToSpsAccounts(accounts);
  346. using (var spsDbContext = new SpsDbContext(_spsDbConnString))
  347. {
  348. if (localVersion == null || localVersion.HasValue && localVersion.Value == 0)
  349. {
  350. spsDbContext.TAcctinfo.AddRange(spsAccounts);
  351. await spsDbContext.SaveChangesAsync();
  352. await CleanSyncCreatedAccounts(spsAccounts.Select(a => a.Gid).ToList());
  353. }
  354. else
  355. {
  356. logger.Info("Insert or update acct info...");
  357. var acctIds = spsAccounts.Select(a => a.AcctId).ToList();
  358. var matchedAccounts = spsDbContext.TAcctinfo
  359. .AsEnumerable()
  360. .Where(a => acctIds.Contains(a.AcctId))
  361. .ToList();
  362. var newAccounts = spsAccounts
  363. .Except(matchedAccounts, new GenericComparer<TAcctinfo, string>(a => a.AcctId))
  364. .ToList();
  365. var existingAccounts = spsAccounts
  366. .Except(newAccounts, new GenericComparer<TAcctinfo, string>(a => a.AcctId))
  367. .ToList();
  368. if (existingAccounts != null && existingAccounts.Count > 0)
  369. {
  370. existingAccounts.ForEach(a => logger.Info($" current batch, update, acct id: {a.AcctId}"));
  371. foreach (var account in existingAccounts)
  372. {
  373. var acctinfo = matchedAccounts.FirstOrDefault(x => x.AcctId == account.AcctId);
  374. account.Gid = acctinfo.Gid; //Gid is the key, could not be updated.
  375. spsDbContext.Entry(acctinfo).CurrentValues.SetValues(account);
  376. }
  377. await spsDbContext.SaveChangesAsync();
  378. await CleanSyncUpdatedAccounts(matchedAccounts.Select(a => a.Gid).ToList());
  379. }
  380. if (newAccounts != null && newAccounts.Count > 0)
  381. {
  382. newAccounts.ForEach(a => logger.Info($" current batch, insert, acct id: {a.AcctId}"));
  383. spsDbContext.TAcctinfo.AddRange(newAccounts);
  384. await spsDbContext.SaveChangesAsync();
  385. await CleanSyncCreatedAccounts(newAccounts.Select(a => a.Gid).ToList());
  386. }
  387. }
  388. foreach (var spsAccount in spsAccounts)
  389. {
  390. logger.Info($" acct id: {spsAccount.AcctId}, gid: {spsAccount.Gid}, recharge total: {spsAccount.RechgTotal}, balance: {spsAccount.Amount}");
  391. }
  392. }
  393. }
  394. private async Task CleanSyncCreatedAccounts(List<ulong> accountGids)
  395. {
  396. using (var context = new SpsDbContext(_spsDbConnString))
  397. {
  398. var accountsGeneratedBySync = context.TTableaudit
  399. .AsEnumerable()
  400. .Where(a => accountGids.Contains(Convert.ToUInt64(a.AccountCreated))).ToList();
  401. context.RemoveRange(accountsGeneratedBySync);
  402. await context.SaveChangesAsync();
  403. }
  404. }
  405. private async Task CleanSyncUpdatedAccounts(List<ulong> accountGids)
  406. {
  407. using (var context = new SpsDbContext(_spsDbConnString))
  408. {
  409. var accountsUpdatedBySync = context.TTableaudit
  410. .AsEnumerable()
  411. .Where(a => accountGids.Contains(Convert.ToUInt64(a.AccountUpdated))).ToList();
  412. context.RemoveRange(accountsUpdatedBySync);
  413. await context.SaveChangesAsync();
  414. }
  415. }
  416. private List<TAcctinfo> ConvertToSpsAccounts(IEnumerable<Account> accounts)
  417. {
  418. var spsAccounts = new List<TAcctinfo>();
  419. foreach (var account in accounts)
  420. {
  421. var acctinfo = new TAcctinfo();
  422. acctinfo.AcctSno = Convert.ToByte(account.SNo);
  423. acctinfo.Sno = account.SNo;
  424. acctinfo.AcctId = account.AccountId;
  425. acctinfo.BelongTo = account.AccountName;
  426. acctinfo.Address = account.Address;
  427. acctinfo.PhoneNo = account.PhoneNo;
  428. acctinfo.AcctType = account.AccountType;
  429. acctinfo.Amount = account.Amount;
  430. acctinfo.AmtType = account.AmountType;
  431. acctinfo.FuelNo = account.FuelNo;
  432. acctinfo.Gift = account.Credit;
  433. acctinfo.AcctState = account.State;
  434. acctinfo.AcctDate = account.AccountDate;
  435. acctinfo.CertfType = account.CertType;
  436. acctinfo.CertfNo = account.CertNo;
  437. acctinfo.RechgTotal = account.RechargeTotal;
  438. acctinfo.Tmac = account.TMac;
  439. acctinfo.Waitmalloc = account.WaitMalloc;
  440. acctinfo.EnableSms = account.EnableSms;
  441. acctinfo.UploadFlag = account.UploadFlag;
  442. spsAccounts.Add(acctinfo);
  443. }
  444. return spsAccounts;
  445. }
  446. #endregion
  447. #region Persist Offline Card Info
  448. private async Task SaveOfflineCardInfoList(List<OfflineCardInfo> offlineCardInfoList, long versionNo)
  449. {
  450. var cards = new List<Card>();
  451. foreach (var cardinfo in offlineCardInfoList)
  452. {
  453. var card = new Card();
  454. card.Gid = Convert.ToUInt64(cardinfo.gid);
  455. card.CardSNo = cardinfo.cardSNo;
  456. card.SNo = cardinfo.sno;
  457. card.CardId = cardinfo.cardID;
  458. card.CardNo = cardinfo.cardNo;
  459. card.CTC = cardinfo.ctc;
  460. card.CTCTime = cardinfo.ctctime;
  461. card.AccountGid = 0; // not available
  462. card.AccountId = cardinfo.acctID;
  463. card.UserNo = cardinfo.userNo;
  464. card.Holder = cardinfo.holder;
  465. card.PhoneNo = cardinfo.phoneNo;
  466. card.DMaxPay = cardinfo.dmaxPay;
  467. card.MMaxPay = cardinfo.mmaxPay;
  468. card.YMaxPay = 0; // not available
  469. card.OnceMaxPay = cardinfo.onceMaxPay;
  470. card.LimitCar = cardinfo.bLimitCar;
  471. card.CarNo = cardinfo.carno;
  472. card.Status = cardinfo.cStatus;
  473. card.UserPin = cardinfo.userPIN;
  474. card.OverDate = cardinfo.overDate;
  475. card.KcDate = cardinfo.kcDate;
  476. card.LimitOil = cardinfo.lmtOil;
  477. card.CardType = cardinfo.cardType;
  478. card.AuthStr = ""; // not available
  479. card.TempCheckStr = ""; // not available
  480. card.DiscountNo = cardinfo.discountNo;
  481. card.StartDate = cardinfo.startdate;
  482. card.PreMalloc = cardinfo.pre_malloc;
  483. card.Balance = cardinfo.money;
  484. card.RechargeTotal = cardinfo.rechgTotal;
  485. card.IntegralTotal = Convert.ToUInt32(cardinfo.integralTotal);
  486. card.CardClass = cardinfo.cardClass;
  487. card.TMac = cardinfo.tmac;
  488. card.LimitTimes = cardinfo.limitTimes;
  489. card.UploadFlag = cardinfo.uploadFlag;
  490. card.CTCFlag = cardinfo.ctcflag;
  491. card.EnableSms = cardinfo.enableSms;
  492. card.VersionNo = versionNo;
  493. card.LastUpdate = DateTime.Now;
  494. cards.Add(card);
  495. }
  496. try
  497. {
  498. using (var context = new GuardDbContext())
  499. {
  500. context.Card.AddRange(cards);
  501. await context.SaveChangesAsync();
  502. }
  503. await SaveToSpsDbCardInfo(cards);
  504. }
  505. catch (Exception ex)
  506. {
  507. logger.Error(ex.ToString());
  508. }
  509. }
  510. private async Task SaveToSpsDbCardInfo(IEnumerable<Card> cards)
  511. {
  512. var spsCards = ConvertToSpsCards(cards);
  513. using (var spsDbContext = new SpsDbContext(_spsDbConnString))
  514. {
  515. if (localVersion == null || localVersion.HasValue && localVersion.Value == 0)
  516. {
  517. var validCards = spsCards.Where(c => c.CStatus != 2);
  518. spsDbContext.TCardinfo.AddRange(validCards);
  519. await spsDbContext.SaveChangesAsync();
  520. await CleanSyncCreatedCards(spsCards.Select(c => c.Gid).ToList());
  521. }
  522. else
  523. {
  524. logger.Info("Insert, update or remove card info...");
  525. var cardInfoComparer = new GenericComparer<TCardinfo, string>(c => c.CardNo);
  526. var validCards = spsCards
  527. .Where(c => c.CStatus != 2)
  528. .ToList();
  529. var validCardNos = validCards
  530. .Select(a => a.CardNo)
  531. .ToList();
  532. var closedCardNos = spsCards
  533. .Where(c => c.CStatus == 2)
  534. .Select(x => x.CardNo)
  535. .ToList();
  536. if (closedCardNos.Count > 0)
  537. {
  538. closedCardNos.ForEach(c => logger.Info("Closed/Deactivated card no: " + c));
  539. var closedCards = spsDbContext.TCardinfo
  540. .AsEnumerable()
  541. .Where(c => closedCardNos.Contains(c.CardNo))
  542. .ToList();
  543. spsDbContext.RemoveRange(closedCards);
  544. await spsDbContext.SaveChangesAsync();
  545. await CleanSyncDeletedCards(closedCards.Select(c => c.CardNo).ToList());
  546. }
  547. // These are db records, not host records.
  548. var matchedCards = spsDbContext.TCardinfo
  549. .AsEnumerable()
  550. .Where(c => validCardNos.Contains(c.CardNo))
  551. .ToList();
  552. var newCards = validCards
  553. .Except(matchedCards, cardInfoComparer)
  554. .ToList();
  555. var existingCards = validCards
  556. .Except(newCards, cardInfoComparer)
  557. .ToList();
  558. if (existingCards != null && existingCards.Count > 0)
  559. {
  560. existingCards.ForEach(c => logger.Info($" current batch, update, card no: {c.CardNo}, balance: {c.Money}, PreMalloc: {c.PreMalloc}"));
  561. foreach (var card in existingCards)
  562. {
  563. var cardinfo = matchedCards.FirstOrDefault(x => x.CardNo == card.CardNo);
  564. card.Gid = cardinfo.Gid; //Gid is the key, could not be updated.
  565. spsDbContext.Entry(cardinfo).CurrentValues.SetValues(card);
  566. }
  567. await spsDbContext.SaveChangesAsync();
  568. await CleanSyncUpdatedCards(matchedCards.Select(c => c.Gid).ToList());
  569. }
  570. if (newCards != null && newCards.Count > 0)
  571. {
  572. logger.Info($"new cards count, before : {newCards.Count}");
  573. newCards.ForEach(c => logger.Info($" current batch, insert, card no: {c.CardNo}"));
  574. //
  575. // This is a very strange case, there are two records of card '11000120215000003172'
  576. // one of them contains a blank space ' '.
  577. //
  578. var cardWithSpace = newCards.Where(c => c.CardNo.Contains(' '));
  579. int cnt = cardWithSpace.Count();
  580. logger.Info($"card no w space, count: {cnt}");
  581. if (cardWithSpace.Count() > 0)
  582. {
  583. for (int i = 0; i < cnt; i++)
  584. {
  585. var result = newCards.Remove(cardWithSpace.ToArray()[i]);
  586. logger.Info($"remove result: {result}");
  587. }
  588. }
  589. logger.Info($"new cards count, after: {newCards.Count}");
  590. var distinctNewCards = newCards.Distinct(cardInfoComparer);
  591. logger.Info($"distinct new cards, count: {distinctNewCards.Count()}");
  592. spsDbContext.TCardinfo.AddRange(distinctNewCards);
  593. await spsDbContext.SaveChangesAsync();
  594. await CleanSyncCreatedCards(distinctNewCards.Select(c => c.Gid).ToList());
  595. }
  596. }
  597. foreach (var card in spsCards)
  598. {
  599. logger.Info($" card no: {card.CardNo}, gid: {card.Gid}, balance: {card.Money}");
  600. }
  601. }
  602. }
  603. private async Task CleanSyncCreatedCards(List<ulong> cardGids)
  604. {
  605. using (var context = new SpsDbContext(_spsDbConnString))
  606. {
  607. var cardsGeneratedBySync = context
  608. .TTableaudit
  609. .AsEnumerable()
  610. .Where(a => cardGids.Contains(Convert.ToUInt64(a.CardInfoCreated)))
  611. .ToList();
  612. context.RemoveRange(cardsGeneratedBySync);
  613. await context.SaveChangesAsync();
  614. }
  615. }
  616. private async Task CleanSyncUpdatedCards(List<ulong> cardGids)
  617. {
  618. using (var context = new SpsDbContext(_spsDbConnString))
  619. {
  620. var cardsUpdatedBySync = context
  621. .TTableaudit
  622. .AsEnumerable()
  623. .Where(a => cardGids.Contains(Convert.ToUInt64(a.CardInfoUpdated)))
  624. .ToList();
  625. foreach (var cardGid in cardsUpdatedBySync)
  626. {
  627. logger.Info($" gid for updated card (to be cleaned): {cardGid.CardInfoUpdated}, " +
  628. $"created at: {cardGid.OperationTime.ToString("yyyy-MM-dd HH:mm:ss")}");
  629. }
  630. context.RemoveRange(cardsUpdatedBySync);
  631. await context.SaveChangesAsync();
  632. }
  633. }
  634. private async Task CleanSyncDeletedCards(List<string> cardNos)
  635. {
  636. using (var context = new SpsDbContext(_spsDbConnString))
  637. {
  638. var cardsDeletedBySync = context.TTableaudit
  639. .AsEnumerable()
  640. .Where(a => cardNos.Contains(a.CardInfoDeleted)).ToList();
  641. context.RemoveRange(cardsDeletedBySync);
  642. await context.SaveChangesAsync();
  643. }
  644. }
  645. private List<TCardinfo> ConvertToSpsCards(IEnumerable<Card> cards)
  646. {
  647. var spsCards = new List<TCardinfo>();
  648. foreach (var card in cards)
  649. {
  650. var cardinfo = new TCardinfo();
  651. cardinfo.CardSno = card.CardSNo;
  652. cardinfo.Sno = card.SNo;
  653. cardinfo.CardId = card.CardId;
  654. cardinfo.CardNo = card.CardNo;
  655. cardinfo.Ctc = card.CTC;
  656. cardinfo.Ctctime = card.CTCTime;
  657. cardinfo.AcctGid = card.AccountGid;
  658. cardinfo.AcctId = card.AccountId;
  659. cardinfo.UserNo = card.UserNo;
  660. cardinfo.Holder = card.Holder;
  661. cardinfo.PhoneNo = card.PhoneNo;
  662. cardinfo.DmaxPay = card.DMaxPay;
  663. cardinfo.MmaxPay = card.MMaxPay;
  664. cardinfo.YmaxPay = card.YMaxPay;
  665. cardinfo.OnceMaxPay = card.OnceMaxPay;
  666. cardinfo.BLimitCar = card.LimitCar;
  667. cardinfo.Carno = card.CarNo;
  668. cardinfo.CStatus = card.Status;
  669. cardinfo.UserPin = card.UserPin;
  670. cardinfo.OverDate = card.OverDate;
  671. cardinfo.KcDate = card.KcDate;
  672. cardinfo.OperNo = string.IsNullOrEmpty(card.OperatorNo) ? "0" : card.OperatorNo;
  673. cardinfo.BLmtGood = card.LimitGood;
  674. cardinfo.LmtOil = card.LimitOil;
  675. cardinfo.CardType = card.CardType;
  676. cardinfo.AuthStr = card.AuthStr;
  677. cardinfo.TmpChkStr = card.TempCheckStr;
  678. cardinfo.DiscountNo = card.DiscountNo;
  679. cardinfo.Startdate = card.StartDate;
  680. cardinfo.PreMalloc = card.PreMalloc;
  681. cardinfo.Money = card.Balance;
  682. cardinfo.RechgTotal = card.RechargeTotal;
  683. cardinfo.IntegralTotal = card.IntegralTotal;
  684. cardinfo.CardClass = card.CardClass;
  685. cardinfo.Tmac = card.TMac;
  686. cardinfo.LimitTimes = card.LimitTimes;
  687. cardinfo.UploadFlag = card.UploadFlag;
  688. cardinfo.Ctcflag = Convert.ToInt32(card.CTCFlag);
  689. cardinfo.EnableSms = card.EnableSms;
  690. spsCards.Add(cardinfo);
  691. }
  692. return spsCards;
  693. }
  694. #endregion
  695. #region Persist Offline Gray Info
  696. private List<GrayTrade> ConvertToLocalGrayTrades(IEnumerable<OfflineGrayInfo> offlineGrayInfoList, long versionNo)
  697. {
  698. var grayTrades = new List<GrayTrade>();
  699. foreach (var grayinfo in offlineGrayInfoList)
  700. {
  701. var grayTrade = new GrayTrade();
  702. grayTrade.Gid = Convert.ToUInt64(grayinfo.gid);
  703. grayTrade.SNo = grayinfo.sno;
  704. grayTrade.PumpType = grayinfo.pumpType;
  705. grayTrade.CardNo = grayinfo.cardNo;
  706. grayTrade.PayModeId = grayinfo.paymodeID;
  707. grayTrade.TrdType = grayinfo.trdType;
  708. grayTrade.CommId = grayinfo.commID;
  709. grayTrade.Price = grayinfo.prc;
  710. grayTrade.Volume = grayinfo.vol;
  711. grayTrade.Amount = grayinfo.mon;
  712. grayTrade.PayAmount = grayinfo.realMON;
  713. grayTrade.CardBalance = Convert.ToUInt32(grayinfo.cardBal);
  714. grayTrade.CTC = grayinfo.ctc;
  715. grayTrade.TtcTime = grayinfo.ttctime;
  716. grayTrade.TtcTimeEnd = grayinfo.ttctimeEnd;
  717. grayTrade.TTC = grayinfo.ttc;
  718. grayTrade.SeqNo = grayinfo.seqNo;
  719. grayTrade.NozzleNo = grayinfo.nozNo;
  720. grayTrade.PumpNo = grayinfo.pumpNo;
  721. grayTrade.PayTermId = grayinfo.payTemID;
  722. grayTrade.VolumeTotalizer = Convert.ToUInt32(grayinfo.endPump);
  723. grayTrade.DiscountNo = grayinfo.discountNo;
  724. grayTrade.PsamAsn = grayinfo.psamasn;
  725. grayTrade.PsamTac = grayinfo.psamtac;
  726. grayTrade.PsamTid = grayinfo.psamtid;
  727. grayTrade.PsamTtc = uint.Parse(grayinfo.psamttc);
  728. grayTrade.Tac = grayinfo.tac;
  729. grayTrade.GMac = grayinfo.gmac;
  730. grayTrade.TMac = grayinfo.tmac;
  731. grayTrade.UploadFlag = grayinfo.uploadFlag;
  732. grayTrade.OperationType = grayinfo.operationType;
  733. grayTrade.VersionNo = versionNo;
  734. grayTrade.LastUpdate = DateTime.Now;
  735. grayTrades.Add(grayTrade);
  736. }
  737. return grayTrades;
  738. }
  739. private async Task SaveOfflineGrayInfoList(IEnumerable<OfflineGrayInfo> offlineGrayInfoList, long versionNo)
  740. {
  741. var grayTrades = ConvertToLocalGrayTrades(offlineGrayInfoList, versionNo);
  742. var groupList = grayTrades.GroupBy(x => new { x.CardNo, x.CTC, x.TtcTime },
  743. (key, grp) => new
  744. {
  745. Key1 = key.CardNo,
  746. Key2 = key.CTC,
  747. Key3 = key.TtcTime,
  748. Result = grp.ToList()
  749. });
  750. foreach (var grp in groupList)
  751. {
  752. logger.Info("----------------------------");
  753. foreach (var item in grp.Result)
  754. {
  755. logger.Info($"card no: {item.CardNo}, ctc: {item.CTC}, ttc time: {item.TtcTime.ToString("yyyy-MM-dd HH:mm:ss")}, op typ: {item.OperationType}");
  756. }
  757. }
  758. var validGrayTrades = new List<GrayTrade>();
  759. foreach (var group in groupList)
  760. {
  761. if (group.Result.Count == 2)
  762. {
  763. if (group.Result[0].OperationType != group.Result[1].OperationType)
  764. {
  765. logger.Info($"{group.Key1}, {group.Key2}, {group.Key3}, Gray and Ungray, skip");
  766. }
  767. }
  768. else
  769. {
  770. validGrayTrades.AddRange(group.Result);
  771. }
  772. }
  773. foreach (var vgi in validGrayTrades)
  774. {
  775. logger.Info($"valid gray info, card no: {vgi.CardNo}, ctc: {vgi.CTC}, ttc time: {vgi.TtcTime.ToString("yyyy-MM-dd HH:mm:ss")}, op typ: {vgi.OperationType}");
  776. }
  777. try
  778. {
  779. using (var context = new GuardDbContext())
  780. {
  781. context.GrayTrade.AddRange(grayTrades);
  782. await context.SaveChangesAsync();
  783. }
  784. await SaveToSpsGrayInfo(validGrayTrades);
  785. }
  786. catch (Exception ex)
  787. {
  788. logger.Error(ex.ToString());
  789. }
  790. }
  791. private async Task SaveToSpsGrayInfo(IEnumerable<GrayTrade> grayTrades)
  792. {
  793. var toBeAddedSpsGrayInfos = ConvertToSpsGrayInfo(grayTrades.Where(t => t.OperationType == 0));
  794. var toBeDeletedSpsGrayInfos = ConvertToSpsGrayInfo(grayTrades.Where(t => t.OperationType == 2));
  795. var spsGrayInfos = ConvertToSpsGrayInfo(grayTrades);
  796. using (var spsDbContext = new SpsDbContext(_spsDbConnString))
  797. {
  798. ////// Handle the to be added ///////
  799. if (toBeAddedSpsGrayInfos.Count > 0)
  800. {
  801. logger.Info($"To be added gray info, count: {toBeAddedSpsGrayInfos.Count}");
  802. }
  803. // find out existing gray info, do we need this check?
  804. var matchedGrayInfos = spsDbContext.TGrayinfo
  805. .AsEnumerable()
  806. .Where(g => toBeAddedSpsGrayInfos.Where(gt => gt.CardNo == g.CardNo && gt.Ctc == g.Ctc && gt.Ttctime == g.Ttctime).Count() >= 1)
  807. .ToList();
  808. foreach (var item in matchedGrayInfos)
  809. {
  810. logger.Info($"to be added, match, card no: {item.CardNo}, ctc: {item.Ctc}, ttc time: {item.Ttctime.Value.ToString("yyyy-MM-dd HH:mm:ss")}");
  811. }
  812. // should insert them into sps db.
  813. var newGrayInfos = toBeAddedSpsGrayInfos.Except(matchedGrayInfos,
  814. new GenericComparer<TGrayinfo, string>(g => string.Concat(g.CardNo, g.Ttc.ToString(), g.Ttctime.Value.ToString("yyyy-MM-dd HH:mm:ss"))));
  815. logger.Info($"should insert new gray info, count: {newGrayInfos.Count()}");
  816. spsDbContext.TGrayinfo.AddRange(newGrayInfos);
  817. ////// Handle the to be deleted ///////
  818. if (toBeDeletedSpsGrayInfos.Count > 0)
  819. {
  820. logger.Info($"To be deleted gray info, count: {toBeDeletedSpsGrayInfos.Count}");
  821. }
  822. var matchedToBeRemovedGrayInfos = spsDbContext.TGrayinfo
  823. .AsEnumerable()
  824. .Where(g => toBeDeletedSpsGrayInfos.Where(gt => gt.CardNo == g.CardNo && gt.Ctc == g.Ctc && gt.Ttctime == g.Ttctime).Count() >= 1)
  825. .ToList();
  826. foreach (var item in matchedToBeRemovedGrayInfos)
  827. {
  828. logger.Info($"gray info matched to be deleted, card no: {item.CardNo}, ctc: {item.Ctc}, gid: {item.Gid}");
  829. }
  830. spsDbContext.TGrayinfo.RemoveRange(matchedToBeRemovedGrayInfos);
  831. await spsDbContext.SaveChangesAsync();
  832. foreach (var grayinfo in spsGrayInfos)
  833. {
  834. logger.Info($"gray info, card no: {grayinfo.CardNo}, gid: {grayinfo.Gid}");
  835. }
  836. await CleanSyncGrayInfo(newGrayInfos.Select(g => g.Gid).ToList());
  837. await CleanSyncDeletedGrayInfo(matchedToBeRemovedGrayInfos.Select(g => g.CardNo).ToList());
  838. }
  839. }
  840. private async Task CleanSyncGrayInfo(List<ulong> grayInfoGids)
  841. {
  842. using (var context = new SpsDbContext(_spsDbConnString))
  843. {
  844. var grayInfosGeneratedBySync = context.TTableaudit
  845. .AsEnumerable()
  846. .Where(a => grayInfoGids.Contains(Convert.ToUInt64(a.GrayInfoCreated)))
  847. .ToList();
  848. context.RemoveRange(grayInfosGeneratedBySync);
  849. await context.SaveChangesAsync();
  850. }
  851. }
  852. private async Task CleanSyncDeletedGrayInfo(List<string> grayInfoCardNos)
  853. {
  854. using (var context = new SpsDbContext(_spsDbConnString))
  855. {
  856. var grayInfosRemovedBySync = context.TTableaudit
  857. .AsEnumerable()
  858. .Where(a => grayInfoCardNos.Contains(a.GrayInfoDeleted))
  859. .ToList();
  860. context.RemoveRange(grayInfosRemovedBySync);
  861. await context.SaveChangesAsync();
  862. }
  863. }
  864. private List<TGrayinfo> ConvertToSpsGrayInfo(IEnumerable<GrayTrade> grayTrades)
  865. {
  866. var spsGrayInfoList = new List<TGrayinfo>();
  867. foreach (var grayTrade in grayTrades)
  868. {
  869. var grayinfo = new TGrayinfo();
  870. grayinfo.Sno = grayTrade.SNo;
  871. grayinfo.PumpType = grayTrade.PumpType;
  872. grayinfo.CardNo = grayTrade.CardNo;
  873. grayinfo.PaymodeId = grayTrade.PayModeId;
  874. grayinfo.TrdType = grayTrade.TrdType;
  875. grayinfo.CommId = grayTrade.CommId;
  876. grayinfo.Prc = grayTrade.Price;
  877. grayinfo.Vol = grayTrade.Volume;
  878. grayinfo.Mon = grayTrade.Amount;
  879. grayinfo.RealMon = grayTrade.PayAmount;
  880. grayinfo.CardBal = grayTrade.CardBalance;
  881. grayinfo.Ctc = grayTrade.CTC;
  882. grayinfo.Ttctime = grayTrade.TtcTime;
  883. grayinfo.TtctimeEnd = grayTrade.TtcTimeEnd;
  884. grayinfo.Ttc = grayTrade.TTC;
  885. grayinfo.SeqNo = grayTrade.SeqNo;
  886. grayinfo.NozNo = grayTrade.NozzleNo;
  887. grayinfo.PumpNo = grayTrade.PumpNo;
  888. grayinfo.PayTemId = grayTrade.PayTermId;
  889. grayinfo.EndPumpId = grayTrade.VolumeTotalizer;
  890. grayinfo.DiscountNo = grayTrade.DiscountNo;
  891. grayinfo.Psamasn = grayTrade.PsamAsn;
  892. grayinfo.Psamtac = grayTrade.PsamTac;
  893. grayinfo.Psamtid = grayTrade.PsamTid;
  894. grayinfo.Psamttc = grayTrade.PsamTtc;
  895. grayinfo.Tac = grayTrade.Tac;
  896. grayinfo.Gmac = grayTrade.GMac;
  897. grayinfo.Tmac = grayTrade.TMac;
  898. grayinfo.UploadFlag = grayTrade.UploadFlag;
  899. spsGrayInfoList.Add(grayinfo);
  900. }
  901. return spsGrayInfoList;
  902. }
  903. #endregion
  904. #region Persist Offline Black Card Info
  905. private async Task SaveOfflineBlackCardInfoList(List<OfflineBlackCardInfo> offlineBlackCardInfoList, long versionNo)
  906. {
  907. ////////// add black card
  908. var offlineBaseBlackCardInfoList = offlineBlackCardInfoList.Where(c => c.blackType == 0).ToList();
  909. var baseBlackCards = new List<BaseBlackCard>();
  910. foreach (var baseBlackCardInfo in offlineBaseBlackCardInfoList)
  911. {
  912. var baseBlackCard = new BaseBlackCard();
  913. baseBlackCard.Gid = Convert.ToUInt64(baseBlackCardInfo.gid);
  914. baseBlackCard.CardNo = baseBlackCardInfo.cardNo;
  915. baseBlackCard.DateTime = baseBlackCardInfo.blackDate;
  916. baseBlackCard.AccountGid = Convert.ToUInt64(baseBlackCardInfo.acctGid);
  917. baseBlackCard.AccountId = baseBlackCardInfo.acctId;
  918. baseBlackCard.CardType = baseBlackCardInfo.cardType;
  919. baseBlackCard.DiscountNo = baseBlackCardInfo.discountNo;
  920. baseBlackCard.Reason = baseBlackCardInfo.reason;
  921. baseBlackCard.UploadFlag = baseBlackCardInfo.uploadFlag;
  922. baseBlackCard.OperationType = baseBlackCardInfo.operationType;
  923. baseBlackCard.VersionNo = versionNo;
  924. baseBlackCard.LastUpdate = DateTime.Now;
  925. baseBlackCards.Add(baseBlackCard);
  926. }
  927. logger.Info($"base blackcard record, count: {baseBlackCards.Count}");
  928. await SaveBaseBlackCards(baseBlackCards);
  929. ////////// add black card
  930. var offlineAddBlackCardInfoList = offlineBlackCardInfoList
  931. .Where(c => c.blackType == 1)
  932. .ToList();
  933. var addBlackCards = new List<AddBlackCard>();
  934. foreach (var addBlackCardInfo in offlineAddBlackCardInfoList)
  935. {
  936. var addBlackCard = new AddBlackCard();
  937. addBlackCard.Gid = Convert.ToUInt64(addBlackCardInfo.gid);
  938. addBlackCard.CardNo = addBlackCardInfo.cardNo;
  939. addBlackCard.DateTime = addBlackCardInfo.blackDate;
  940. addBlackCard.AccountGid = Convert.ToUInt64(addBlackCardInfo.acctGid);
  941. addBlackCard.AccountId = addBlackCardInfo.acctId;
  942. addBlackCard.CardType = addBlackCardInfo.cardType;
  943. addBlackCard.DiscountNo = addBlackCardInfo.discountNo;
  944. addBlackCard.Reason = addBlackCardInfo.reason;
  945. addBlackCard.UploadFlag = addBlackCardInfo.uploadFlag;
  946. addBlackCard.OperationType = addBlackCardInfo.operationType;
  947. addBlackCard.VersionNo = versionNo;
  948. addBlackCard.LastUpdate = DateTime.Now;
  949. addBlackCards.Add(addBlackCard);
  950. }
  951. logger.Info($"addblackcard record, count: {addBlackCards.Count}");
  952. await SaveAddBlackCards(addBlackCards);
  953. ////////// delete black card
  954. var offlineDeleteBlackCardInfoList = offlineBlackCardInfoList
  955. .Where(c => c.blackType == 2)
  956. .ToList();
  957. var deleteBlackCards = new List<DeleteBlackCard>();
  958. foreach (var deleteBlackCardInfo in offlineDeleteBlackCardInfoList)
  959. {
  960. var deleteBlackCard = new DeleteBlackCard();
  961. deleteBlackCard.Gid = Convert.ToUInt64(deleteBlackCardInfo.gid);
  962. deleteBlackCard.CardNo = deleteBlackCardInfo.cardNo;
  963. deleteBlackCard.DateTime = deleteBlackCardInfo.blackDate;
  964. deleteBlackCard.AccountGid = Convert.ToUInt64(deleteBlackCardInfo.acctGid);
  965. deleteBlackCard.AccountId = deleteBlackCardInfo.acctId;
  966. deleteBlackCard.CardType = deleteBlackCardInfo.cardType;
  967. deleteBlackCard.DiscountNo = deleteBlackCardInfo.discountNo;
  968. deleteBlackCard.Reason = deleteBlackCardInfo.reason;
  969. deleteBlackCard.UploadFlag = deleteBlackCardInfo.uploadFlag;
  970. deleteBlackCard.OperationType = deleteBlackCardInfo.operationType;
  971. deleteBlackCard.VersionNo = versionNo;
  972. deleteBlackCard.LastUpdate = DateTime.Now;
  973. deleteBlackCards.Add(deleteBlackCard);
  974. }
  975. logger.Info($"deleteblackcard record, count: {deleteBlackCards.Count}");
  976. await SaveDeleteBlackCards(deleteBlackCards);
  977. }
  978. #region Base BlackCard processing
  979. private async Task SaveBaseBlackCards(List<BaseBlackCard> baseBlackCards)
  980. {
  981. try
  982. {
  983. using (var context = new GuardDbContext())
  984. {
  985. context.BaseBlackCard.AddRange(baseBlackCards);
  986. await context.SaveChangesAsync();
  987. }
  988. await SaveToSpsBaseBlackCards(baseBlackCards);
  989. }
  990. catch (Exception ex)
  991. {
  992. logger.Error(ex.ToString());
  993. }
  994. }
  995. private async Task SaveToSpsBaseBlackCards(IEnumerable<BaseBlackCard> baseBlackCards)
  996. {
  997. var comparer = new GenericComparer<TBlackcard, string>(c => c.CardNo);
  998. var spsBaseBlackCards = ConvertToSpsBaseBlackCards(baseBlackCards);
  999. var toBeAddedBaseBlackCards = ConvertToSpsBaseBlackCards(baseBlackCards.Where(c => c.OperationType == 0));
  1000. var toBeUpdatedBaseBlackCards = ConvertToSpsBaseBlackCards(baseBlackCards.Where(c => c.OperationType == 1));
  1001. var toBeRemovedBaseBlackCards = ConvertToSpsBaseBlackCards(baseBlackCards.Where(c => c.OperationType == 2));
  1002. if (toBeUpdatedBaseBlackCards.Count > 0)
  1003. logger.Warn($"Base black cards, there are records to be updated??? count: {toBeUpdatedBaseBlackCards.Count}");
  1004. try
  1005. {
  1006. using (var context = new SpsDbContext(_spsDbConnString))
  1007. {
  1008. // handle `to be added Base BlackCard records`
  1009. var existingToBeAdded = context.TBlackcard
  1010. .AsEnumerable()
  1011. .Where(bc => toBeAddedBaseBlackCards.Any(c => c.CardNo == bc.CardNo))
  1012. .ToList();
  1013. var pendingAdd = toBeAddedBaseBlackCards.Except(existingToBeAdded, comparer).ToList();
  1014. pendingAdd.ForEach(c => logger.Info($" bc, add, card no: {c.CardNo}"));
  1015. context.TBlackcard.AddRange(pendingAdd);
  1016. // handle `to be removed Base BlackCard records`
  1017. var matchedToBeRemoved = context.TBlackcard
  1018. .AsEnumerable()
  1019. .Where(bc => toBeRemovedBaseBlackCards.Any(c => c.CardNo == bc.CardNo))
  1020. .ToList();
  1021. matchedToBeRemoved.ForEach(c => logger.Info($" bc, del, card no: {c.CardNo}"));
  1022. context.TBlackcard.RemoveRange(matchedToBeRemoved);
  1023. await context.SaveChangesAsync();
  1024. await CleanSyncInsertedBaseBlackCards(pendingAdd.Select(a => a.Gid).ToList());
  1025. await CleanSyncRemovedBaseBlackCards(matchedToBeRemoved.Select(c => c.CardNo).ToList());
  1026. spsBaseBlackCards
  1027. .ForEach(c => logger.Info($"base blackcard, card no: {c.CardNo}, gid: {c.Gid}"));
  1028. }
  1029. }
  1030. catch (Exception ex)
  1031. {
  1032. logger.Error(ex.ToString());
  1033. }
  1034. }
  1035. private async Task CleanSyncInsertedBaseBlackCards(List<ulong> baseBlackCardGids)
  1036. {
  1037. using (var context = new SpsDbContext(_spsDbConnString))
  1038. {
  1039. var baseBlackCardsGeneratedBySync = context.TTableaudit
  1040. .AsEnumerable()
  1041. .Where(a => baseBlackCardGids.Contains(Convert.ToUInt64(a.BaseBlackCardCreated)))
  1042. .ToList();
  1043. context.RemoveRange(baseBlackCardsGeneratedBySync);
  1044. await context.SaveChangesAsync();
  1045. }
  1046. }
  1047. private async Task CleanSyncRemovedBaseBlackCards(List<string> baseBlackCardCardNos)
  1048. {
  1049. using (var context = new SpsDbContext(_spsDbConnString))
  1050. {
  1051. var baseBlackCardsDeletedBySync = context.TTableaudit
  1052. .AsEnumerable()
  1053. .Where(a => baseBlackCardCardNos.Contains(a.BaseBlackCardDeleted))
  1054. .ToList();
  1055. context.RemoveRange(baseBlackCardsDeletedBySync);
  1056. await context.SaveChangesAsync();
  1057. }
  1058. }
  1059. private List<TBlackcard> ConvertToSpsBaseBlackCards(IEnumerable<BaseBlackCard> baseBlackCards)
  1060. {
  1061. var spsBaseBlackCards = new List<TBlackcard>();
  1062. foreach (var baseBlackCard in baseBlackCards)
  1063. {
  1064. var baseblackcard = new TBlackcard();
  1065. baseblackcard.CardNo = baseBlackCard.CardNo;
  1066. baseblackcard.BlackDate = baseBlackCard.DateTime;
  1067. baseblackcard.AcctGid = baseBlackCard.AccountGid;
  1068. baseblackcard.AcctId = baseBlackCard.AccountId;
  1069. baseblackcard.CardType = baseBlackCard.CardType;
  1070. baseblackcard.DiscountNo = baseBlackCard.DiscountNo;
  1071. baseblackcard.Reason = baseBlackCard.Reason;
  1072. baseblackcard.UploadFlag = baseBlackCard.UploadFlag;
  1073. spsBaseBlackCards.Add(baseblackcard);
  1074. }
  1075. return spsBaseBlackCards;
  1076. }
  1077. #endregion
  1078. #region AddBlackCard processing
  1079. private async Task SaveAddBlackCards(List<AddBlackCard> addBlackCards)
  1080. {
  1081. try
  1082. {
  1083. using (var context = new GuardDbContext())
  1084. {
  1085. context.AddBlackCard.AddRange(addBlackCards);
  1086. await context.SaveChangesAsync();
  1087. }
  1088. await SaveToSpsAddBlackCards(addBlackCards);
  1089. }
  1090. catch (Exception ex)
  1091. {
  1092. logger.Error(ex.ToString());
  1093. }
  1094. }
  1095. private async Task SaveToSpsAddBlackCards(IEnumerable<AddBlackCard> addBlackCards)
  1096. {
  1097. var comparer = new GenericComparer<TAddblackcard, string>(c => c.CardNo);
  1098. var toBeAddedAddBlackCards = ConvertToSpsAddBlackCards(addBlackCards.Where(c => c.OperationType == 0));
  1099. var toBeUpdatedAddBlackCards = ConvertToSpsAddBlackCards(addBlackCards.Where(c => c.OperationType == 1));
  1100. var toBeRemovedAddBlackCards = ConvertToSpsAddBlackCards(addBlackCards.Where(c => c.OperationType == 2));
  1101. var spsAddBlackCards = ConvertToSpsAddBlackCards(addBlackCards);
  1102. using (var spsDbContext = new SpsDbContext(_spsDbConnString))
  1103. {
  1104. // handle `to be added AddBlackCard records`
  1105. var matchedInToBeAdded = spsDbContext.TAddblackcard
  1106. .AsEnumerable()
  1107. .Where(abc => toBeAddedAddBlackCards.Where(c => c.CardNo == abc.CardNo).Count() >= 1)
  1108. .ToList();
  1109. var pendingAddedAddBlackCard = toBeAddedAddBlackCards.Except(matchedInToBeAdded, comparer).ToList();
  1110. pendingAddedAddBlackCard.ForEach(c => logger.Info($" abc, pending add, card no: {c.CardNo}"));
  1111. spsDbContext.TAddblackcard.AddRange(pendingAddedAddBlackCard);
  1112. // handle `to be updated AddBlackCard records`
  1113. var pendingUpdateAddBlackCard = toBeAddedAddBlackCards.Except(pendingAddedAddBlackCard, comparer).ToList();
  1114. pendingUpdateAddBlackCard.ForEach(c => logger.Info($" abc, pending upd within add, card no: {c.CardNo}"));
  1115. toBeUpdatedAddBlackCards.AddRange(pendingUpdateAddBlackCard);
  1116. var matchedToBeUpdated = spsDbContext.TAddblackcard
  1117. .AsEnumerable()
  1118. .Where(abc => toBeUpdatedAddBlackCards.Where(c => c.CardNo == abc.CardNo).Count() >= 1)
  1119. .ToList();
  1120. var candidatesToBeInserted = toBeUpdatedAddBlackCards
  1121. .Except(matchedToBeUpdated, comparer)
  1122. .ToList();
  1123. if (candidatesToBeInserted.Count > 0)
  1124. logger.Info($" abc, pending upd, some are new??? count: {candidatesToBeInserted.Count}");
  1125. var toBeUpdated = toBeUpdatedAddBlackCards
  1126. .Except(candidatesToBeInserted, comparer)
  1127. .ToList();
  1128. toBeUpdated.ForEach(c => logger.Info($" abc, pending upd, card no: {c.CardNo}"));
  1129. foreach (var card in toBeUpdated)
  1130. {
  1131. var match = matchedToBeUpdated.FirstOrDefault(c => c.CardNo == card.CardNo);
  1132. if (match != null)
  1133. {
  1134. card.Gid = match.Gid;
  1135. spsDbContext.Entry(match).CurrentValues.SetValues(card);
  1136. }
  1137. }
  1138. // handle `to be removed AddBalckCard records`
  1139. var matchedToBeRemoved = spsDbContext.TAddblackcard
  1140. .AsEnumerable()
  1141. .Where(abc => toBeRemovedAddBlackCards.Where(c => c.CardNo == abc.CardNo).Count() >= 1)
  1142. .ToList();
  1143. matchedToBeRemoved.ForEach(c => logger.Info($" abc, pending del, card no: {c.CardNo}"));
  1144. spsDbContext.TAddblackcard.RemoveRange(matchedToBeRemoved);
  1145. await spsDbContext.SaveChangesAsync();
  1146. await CleanSyncInsertedAddBlackCards(pendingAddedAddBlackCard.Select(a => a.Gid).ToList());
  1147. await CleanSyncUpdatedAddBlackCards(toBeUpdated.Select(c => c.Gid).ToList());
  1148. await CleanSyncDeletedAddBlackCards(matchedToBeRemoved.Select(c => c.CardNo).ToList());
  1149. spsAddBlackCards.ForEach(c =>
  1150. logger.Info($"addblackcard, card no: {c.CardNo}, gid: {c.Gid}"));
  1151. }
  1152. }
  1153. private async Task CleanSyncInsertedAddBlackCards(List<ulong> addBlackCardGids)
  1154. {
  1155. using (var context = new SpsDbContext(_spsDbConnString))
  1156. {
  1157. var addBlackCardsGeneratedBySync = context.TTableaudit
  1158. .AsEnumerable()
  1159. .Where(a => addBlackCardGids.Contains(Convert.ToUInt64(a.BlacklistedCardCreated)))
  1160. .ToList();
  1161. context.RemoveRange(addBlackCardsGeneratedBySync);
  1162. await context.SaveChangesAsync();
  1163. }
  1164. }
  1165. private async Task CleanSyncUpdatedAddBlackCards(List<ulong> addBlackCardGids)
  1166. {
  1167. using (var context = new SpsDbContext(_spsDbConnString))
  1168. {
  1169. var addBlackCardsUpdatedBySync = context.TTableaudit
  1170. .AsEnumerable()
  1171. .Where(a => addBlackCardGids.Contains(Convert.ToUInt64(a.BlacklistedCardUpdated)))
  1172. .ToList();
  1173. context.RemoveRange(addBlackCardsUpdatedBySync);
  1174. await context.SaveChangesAsync();
  1175. }
  1176. }
  1177. private async Task CleanSyncDeletedAddBlackCards(List<string> addBlackCardCardNos)
  1178. {
  1179. using (var context = new SpsDbContext(_spsDbConnString))
  1180. {
  1181. var addBlackCardsDeletedBySync = context.TTableaudit
  1182. .AsEnumerable()
  1183. .Where(a => addBlackCardCardNos.Contains(a.BlacklistedCardDeleted))
  1184. .ToList();
  1185. context.RemoveRange(addBlackCardsDeletedBySync);
  1186. await context.SaveChangesAsync();
  1187. }
  1188. }
  1189. private List<TAddblackcard> ConvertToSpsAddBlackCards(IEnumerable<AddBlackCard> addBlackCards)
  1190. {
  1191. var spsAddBlackCards = new List<TAddblackcard>();
  1192. foreach (var addBlackCard in addBlackCards)
  1193. {
  1194. var addblackcard = new TAddblackcard();
  1195. addblackcard.CardNo = addBlackCard.CardNo;
  1196. addblackcard.BlackDate = addBlackCard.DateTime;
  1197. addblackcard.AcctGid = addBlackCard.AccountGid;
  1198. addblackcard.AcctId = addBlackCard.AccountId;
  1199. addblackcard.CardType = addBlackCard.CardType;
  1200. addblackcard.DiscountNo = addBlackCard.DiscountNo;
  1201. addblackcard.Reason = addBlackCard.Reason;
  1202. addblackcard.UploadFlag = addBlackCard.UploadFlag;
  1203. spsAddBlackCards.Add(addblackcard);
  1204. }
  1205. return spsAddBlackCards;
  1206. }
  1207. #endregion
  1208. #region DeleteBlackCard processing
  1209. private async Task SaveDeleteBlackCards(List<DeleteBlackCard> deleteBlackCards)
  1210. {
  1211. try
  1212. {
  1213. using (var context = new GuardDbContext())
  1214. {
  1215. context.DeleteBlackCard.AddRange(deleteBlackCards);
  1216. await context.SaveChangesAsync();
  1217. }
  1218. await SaveToSpsDeleteBlackCards(deleteBlackCards);
  1219. }
  1220. catch (Exception ex)
  1221. {
  1222. logger.Error(ex.ToString());
  1223. }
  1224. }
  1225. private async Task SaveToSpsDeleteBlackCards(IEnumerable<DeleteBlackCard> deleteBlackCards)
  1226. {
  1227. var comparer = new GenericComparer<TDeleteblackcard, string>(c => c.CardNo);
  1228. var toBeAddedDeleteBlackCards = ConvertToSpsDeleteBlackCards(deleteBlackCards.Where(c => c.OperationType == 0));
  1229. var toBeRemovedDeleteBlackCards = ConvertToSpsDeleteBlackCards(deleteBlackCards.Where(c => c.OperationType == 2));
  1230. var spsDeleteBlackCards = ConvertToSpsDeleteBlackCards(deleteBlackCards);
  1231. using (var spsDbContext = new SpsDbContext(_spsDbConnString))
  1232. {
  1233. // handle `to be added DeleteBlackCard records`
  1234. var existingInToBeAdded = spsDbContext.TDeleteblackcard
  1235. .AsEnumerable()
  1236. .Where(dbc => toBeAddedDeleteBlackCards.Where(c => c.CardNo == dbc.CardNo).Count() >= 1)
  1237. .ToList();
  1238. var newDeleteBlackCards = toBeAddedDeleteBlackCards.Except(existingInToBeAdded, comparer).ToList();
  1239. newDeleteBlackCards.ForEach(c => logger.Info($" dbc, add, card no: {c.CardNo}"));
  1240. spsDbContext.TDeleteblackcard.AddRange(newDeleteBlackCards);
  1241. // handle `to be updated DeleteBlackCard records`
  1242. var toBeUpdated = toBeAddedDeleteBlackCards.Except(newDeleteBlackCards, comparer).ToList();
  1243. toBeUpdated.ForEach(c => logger.Info($" dbc, upd, card no: {c.CardNo}, time: {c.BlackDate.Value}"));
  1244. foreach (var card in toBeUpdated)
  1245. {
  1246. var match = existingInToBeAdded.FirstOrDefault(c => c.CardNo == card.CardNo);
  1247. if (match != null)
  1248. {
  1249. card.Gid = match.Gid;
  1250. spsDbContext.Entry(match).CurrentValues.SetValues(card);
  1251. }
  1252. }
  1253. // handle `to be removed DeleteBlackCard records`
  1254. var matchedToBeRemoved = spsDbContext.TDeleteblackcard
  1255. .AsEnumerable()
  1256. .Where(dbc => toBeRemovedDeleteBlackCards.Where(c => c.CardNo == dbc.CardNo).Count() >= 1)
  1257. .ToList();
  1258. matchedToBeRemoved.ForEach(c => logger.Info($" dbc, del, card no: {c.CardNo}"));
  1259. spsDbContext.TDeleteblackcard.RemoveRange(matchedToBeRemoved);
  1260. await spsDbContext.SaveChangesAsync();
  1261. spsDeleteBlackCards
  1262. .ForEach(c => logger.Info($"deleteblackcard, card no: {c.CardNo}, gid: {c.Gid}"));
  1263. await CleanSyncAddedDeleteBlackCards(newDeleteBlackCards.Select(d => d.Gid).ToList());
  1264. await CleanSyncRemovedDeleteBlackCards(matchedToBeRemoved.Select(c => c.CardNo).ToList());
  1265. }
  1266. }
  1267. private async Task CleanSyncAddedDeleteBlackCards(List<ulong> deleteBlackCardGids)
  1268. {
  1269. using (var context = new SpsDbContext(_spsDbConnString))
  1270. {
  1271. var deleteBlackCardsGeneratedBySync = context.TTableaudit
  1272. .AsEnumerable()
  1273. .Where(a => deleteBlackCardGids.Contains(Convert.ToUInt64(a.ReleasedCardCreated)))
  1274. .ToList();
  1275. context.RemoveRange(deleteBlackCardsGeneratedBySync);
  1276. await context.SaveChangesAsync();
  1277. }
  1278. }
  1279. private async Task CleanSyncRemovedDeleteBlackCards(List<string> deleteBlackCardCardNos)
  1280. {
  1281. using (var context = new SpsDbContext(_spsDbConnString))
  1282. {
  1283. var deleteBlackCardsRemovedBySync = context.TTableaudit
  1284. .AsEnumerable()
  1285. .Where(a => deleteBlackCardCardNos.Contains(a.ReleasedCardDeleted))
  1286. .ToList();
  1287. context.RemoveRange(deleteBlackCardsRemovedBySync);
  1288. await context.SaveChangesAsync();
  1289. }
  1290. }
  1291. private List<TDeleteblackcard> ConvertToSpsDeleteBlackCards(IEnumerable<DeleteBlackCard> deleteBlackCards)
  1292. {
  1293. var spsDeleteBlackCards = new List<TDeleteblackcard>();
  1294. foreach (var deleteBlackCard in deleteBlackCards)
  1295. {
  1296. var deleteblackcard = new TDeleteblackcard();
  1297. deleteblackcard.CardNo = deleteBlackCard.CardNo;
  1298. deleteblackcard.BlackDate = deleteBlackCard.DateTime;
  1299. deleteblackcard.AcctGid = deleteBlackCard.AccountGid;
  1300. deleteblackcard.AcctId = deleteBlackCard.AccountId;
  1301. deleteblackcard.CardType = deleteBlackCard.CardType;
  1302. deleteblackcard.DiscountNo = deleteBlackCard.DiscountNo;
  1303. deleteblackcard.Reason = deleteBlackCard.Reason;
  1304. deleteblackcard.UploadFlag = deleteBlackCard.UploadFlag;
  1305. spsDeleteBlackCards.Add(deleteblackcard);
  1306. }
  1307. return spsDeleteBlackCards;
  1308. }
  1309. #endregion
  1310. #endregion
  1311. #region Persist Offline CardRepLoss
  1312. private async Task SaveOfflineCardRepLossInfoList(List<OfflineCardRepLoss> offlineCardRepLossInfoList,
  1313. long versionNo)
  1314. {
  1315. if (offlineCardRepLossInfoList == null || offlineCardRepLossInfoList?.Count == 0)
  1316. {
  1317. return;
  1318. }
  1319. logger.Info($"cardRepLossInfoList, count: {offlineCardRepLossInfoList.Count}");
  1320. var comparer = new GenericComparer<TCardreploss, string>(c => c.CardNo);
  1321. var spsCardRepLoss = ConvertToSpsCardRepLoss(offlineCardRepLossInfoList);
  1322. foreach (var item in spsCardRepLoss)
  1323. {
  1324. logger.Info($"To be added CardRepLoss, card no: {item.CardNo}, operType: {item.OperType}");
  1325. }
  1326. using (var spsDbContext = new SpsDbContext(_spsDbConnString))
  1327. {
  1328. var matches = spsDbContext.TCardreploss
  1329. .AsEnumerable()
  1330. .Where(tc =>
  1331. spsCardRepLoss.Where(s => s.CardNo == tc.CardNo && s.LossTime == tc.LossTime).Count() >= 1)
  1332. .ToList();
  1333. foreach (var c in matches)
  1334. {
  1335. logger.Info($"cardreploss, matched, cardNo: {c.CardNo}, lossTime: {c.LossTime?.ToString("yyyy-MM-dd HH:mm:ss")}");
  1336. }
  1337. var toBeAdded = spsCardRepLoss.Except(matches, comparer).ToList();
  1338. if (toBeAdded.Count == 0)
  1339. {
  1340. logger.Info($"cardreploss, no new records to be added");
  1341. return;
  1342. }
  1343. foreach (var c in toBeAdded)
  1344. {
  1345. logger.Info($"cardreploss, to be added, cardNo: {c.CardNo}, lossTime: {c.LossTime?.ToString("yyyy-MM-dd HH:mm:ss")}");
  1346. }
  1347. await spsDbContext.TCardreploss.AddRangeAsync(toBeAdded);
  1348. int result = 0;
  1349. try
  1350. {
  1351. result = await spsDbContext.SaveChangesAsync();
  1352. logger.Info($"Cardreploss, inserted {result} records");
  1353. }
  1354. catch (Exception ex)
  1355. {
  1356. logger.Error($"Exception raised in saving CardReploss: {ex}");
  1357. }
  1358. var cardRepLossCreated =
  1359. await spsDbContext.TTableaudit.Where(r => r.LostCardCreated != 0).ToListAsync();
  1360. if (cardRepLossCreated.Count == result)
  1361. {
  1362. var toBeCleandGids = spsCardRepLoss.Select(r => r.Gid).ToList();
  1363. foreach (var gid in toBeCleandGids)
  1364. {
  1365. logger.Info($"to be cleand gid: {gid}");
  1366. }
  1367. await CleanSyncCardRepLoss(toBeCleandGids);
  1368. }
  1369. }
  1370. }
  1371. private async Task CleanSyncCardRepLoss(List<ulong> cardRepLosGids)
  1372. {
  1373. using (var context = new SpsDbContext(_spsDbConnString))
  1374. {
  1375. var cardRepLossGeneratedBySync = context.TTableaudit
  1376. .AsEnumerable()
  1377. .Where(a => cardRepLosGids.Contains(Convert.ToUInt64(a.LostCardCreated)))
  1378. .ToList();
  1379. context.RemoveRange(cardRepLossGeneratedBySync);
  1380. await context.SaveChangesAsync();
  1381. }
  1382. }
  1383. private List<TCardreploss> ConvertToSpsCardRepLoss(IEnumerable<OfflineCardRepLoss> cardRepLosses)
  1384. {
  1385. var cardRepLossList = new List<TCardreploss>();
  1386. foreach (var crp in cardRepLosses)
  1387. {
  1388. var cardRepLoss = new TCardreploss();
  1389. cardRepLoss.CardNo = crp.cardNo;
  1390. cardRepLoss.OperNo = crp.operNo;
  1391. cardRepLoss.OperType = crp.operType;
  1392. cardRepLoss.Sno = Convert.ToUInt32(crp.sNo);
  1393. cardRepLoss.LossTime = crp.LossTime;
  1394. cardRepLoss.Reason = crp.reason;
  1395. cardRepLossList.Add(cardRepLoss);
  1396. }
  1397. return cardRepLossList;
  1398. }
  1399. #endregion
  1400. #region Get token
  1401. private async Task<AuthToken> GetTokenAsync(string userName, string password, string baseUrl)
  1402. {
  1403. logger.Info("Downloader starts to get token...");
  1404. _client.DefaultRequestHeaders.Clear();
  1405. string tokenUrl = string.Concat(baseUrl, tokenAuthPath);
  1406. var formParam = new AuthenticationParameter(grantType, userName, password);
  1407. try
  1408. {
  1409. var response = await _client.PostAsync(tokenUrl, new FormUrlEncodedContent(formParam.Params)).ConfigureAwait(false);
  1410. logger.Info($"Token response for downloader, StatusCode = {(int)response.StatusCode}");
  1411. if (response.IsSuccessStatusCode)
  1412. {
  1413. await response.Content.ReadAsStringAsync().ContinueWith(x =>
  1414. {
  1415. currentAuthToken = JsonConvert.DeserializeObject<AuthToken>(x?.Result);
  1416. currentAuthToken.TokenRetrievedTime = DateTime.Now;
  1417. });
  1418. }
  1419. else
  1420. {
  1421. var content = await response.Content.ReadAsStringAsync();
  1422. response.Content?.Dispose();
  1423. }
  1424. return currentAuthToken;
  1425. }
  1426. catch (Exception ex)
  1427. {
  1428. logger.Error(ex.ToString());
  1429. return null;
  1430. }
  1431. }
  1432. #endregion
  1433. }
  1434. }