SpsDataCourierApp.cs 95 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366
  1. using Dfs.WayneChina.SpsDataCourier.Guard;
  2. using Dfs.WayneChina.SpsDataCourier.Models;
  3. using Dfs.WayneChina.SpsDataCourier.SpsData;
  4. using Edge.Core.Processor;
  5. using Edge.Core.Processor.Dispatcher.Attributes;
  6. using Microsoft.EntityFrameworkCore;
  7. using NLog.LayoutRenderers;
  8. using System;
  9. using System.Collections.Generic;
  10. using System.Data;
  11. using System.Linq;
  12. using System.Text;
  13. using System.Threading;
  14. using System.Threading.Tasks;
  15. namespace Dfs.WayneChina.SpsDataCourier
  16. {
  17. /// <summary>
  18. /// Application to upload account/card/transaction/card recharge and reductions.
  19. /// </summary>
  20. [MetaPartsDescriptor(
  21. "lang-zh-cn:Sps传输服务 Applang-en-us:Sps Data Courier",
  22. "lang-zh-cn:用于传输SPS数据库中的数据到远端服务器" +
  23. "lang-en-us:Used for sending SPS data to remote host",
  24. new[] { "lang-zh-cn:数据上传服务lang-en-us:Data Upload Service" })]
  25. public class SpsDataCourierApp : IAppProcessor
  26. {
  27. #region Fields
  28. public string SerialNumber { get; set; }
  29. public string Name { get; set; }
  30. private string username;
  31. private string password;
  32. private string authServiceBaseUrl;
  33. private string accountServiceBaseUrl;
  34. private string accountServiceRelativeUrl;
  35. private string deviceSN;
  36. public int Id { get; }
  37. public object OfflineAccount { get; private set; }
  38. public string MetaConfigName { get; set; }
  39. private DbMonitor dbMonitor;
  40. private DataCourier dataCourier;
  41. private int scanInterval;
  42. private string fuelMapping;
  43. private bool smartFuel05Compatible;
  44. private int retryCount;
  45. private bool enableSync;
  46. private bool excludeCurrentSite;
  47. private int syncInterval;
  48. private string checkVersionRelativeUrl;
  49. private string syncDataRelativeUrl;
  50. private ManualResetEvent mre = new ManualResetEvent(false);
  51. private Dictionary<int, int> fuelMappingDict = new Dictionary<int, int>();
  52. private Downloader downloader;
  53. private readonly ConnectionInfo connectionInfo;
  54. #endregion
  55. #region Logger
  56. static NLog.Logger logger = NLog.LogManager.LoadConfiguration("NLog.config").GetLogger("SpsDataCourier");
  57. #endregion
  58. private string _mySqlConn;
  59. #region Constructor
  60. [ParamsJsonSchemas("appCtorParamsJsonSchema")]
  61. public SpsDataCourierApp(DataCourierAppContructorParameterV1 config)
  62. {
  63. this.Id = config.Id;
  64. this.username = config.Username;
  65. this.password = config.Password;
  66. this.authServiceBaseUrl = config.AuthServiceBaseUrl;
  67. this.accountServiceBaseUrl = config.AccountServiceBaseUrl;
  68. this.accountServiceRelativeUrl = config.AccountServiceRelativeUrl;
  69. this.deviceSN = config.DeviceSN;
  70. this.scanInterval = config.ScanInterval;
  71. this.fuelMapping = string.Join(";", config.FuelMappingArr.Select(m => $"{m.Barcode}:{m.FuelNo}"));
  72. this.retryCount = config.RetryCount;
  73. this.enableSync = config.EnableSync;
  74. this.excludeCurrentSite = config.ExcludeCurrentSite;
  75. this.syncInterval = config.SyncInterval;
  76. this.checkVersionRelativeUrl = config.CheckVersionRelativeUrl;
  77. this.syncDataRelativeUrl = config.SyncDataRelativeUrl;
  78. _mySqlConn = FormatConnectionString(config.ConnectionString);
  79. SetFuelProductMapping();
  80. connectionInfo = new ConnectionInfo
  81. {
  82. AccountServiceBaseUrl = accountServiceBaseUrl,
  83. AccountServiceRelativeUrl = accountServiceRelativeUrl,
  84. AuthServiceBaseUrl = authServiceBaseUrl,
  85. DeviceSN = deviceSN,
  86. UserName = username,
  87. Password = password
  88. };
  89. }
  90. private string FormatConnectionString(SpsDbConnectionSetting spsDbConnectionSetting)
  91. {
  92. return $"server={spsDbConnectionSetting.Server};port={spsDbConnectionSetting.Port};uid={spsDbConnectionSetting.Username};password={spsDbConnectionSetting.Password};database=sps_db;TreatTinyAsBoolean=false;Convert Zero Datetime=true;";
  93. }
  94. public SpsDataCourierApp(int id, string username, string password, string authServiceBaseUrl, string accountServiceBaseUrl,
  95. string accountServiceRelativeUrl, string deviceSN, int scanInterval, string fuelMapping, string smartFuel05Compatible,
  96. int retryCount, int enableSync, int excludeCurrentSite, int syncInterval, string checkVersionRelativeUrl, string syncDataRelativeUrl, string connectionString)
  97. {
  98. Id = id;
  99. this.username = username;
  100. this.password = password;
  101. this.authServiceBaseUrl = authServiceBaseUrl;
  102. this.accountServiceBaseUrl = accountServiceBaseUrl;
  103. this.accountServiceRelativeUrl = accountServiceRelativeUrl;
  104. this.deviceSN = deviceSN;
  105. this.scanInterval = scanInterval;
  106. this.fuelMapping = fuelMapping;
  107. this.smartFuel05Compatible = Convert.ToBoolean(smartFuel05Compatible);
  108. this.retryCount = retryCount;
  109. this.enableSync = enableSync > 0 ? true : false;
  110. this.excludeCurrentSite = excludeCurrentSite > 0 ? true : false;
  111. this.syncInterval = syncInterval;
  112. this.checkVersionRelativeUrl = checkVersionRelativeUrl;
  113. this.syncDataRelativeUrl = syncDataRelativeUrl;
  114. _mySqlConn = connectionString;
  115. SetFuelProductMapping();
  116. connectionInfo = new ConnectionInfo
  117. {
  118. AccountServiceBaseUrl = accountServiceBaseUrl,
  119. AccountServiceRelativeUrl = accountServiceRelativeUrl,
  120. AuthServiceBaseUrl = authServiceBaseUrl,
  121. DeviceSN = deviceSN,
  122. UserName = username,
  123. Password = password
  124. };
  125. }
  126. #endregion
  127. #region Fuel barcode and fuel number
  128. private void SetFuelProductMapping()
  129. {
  130. if (!string.IsNullOrEmpty(fuelMapping))
  131. {
  132. var sequence = fuelMapping.Split(';')
  133. .Select(s => s.Split(':'))
  134. .Select(a => new { Barcode = int.Parse(a[0]), FuelNo = int.Parse(a[1]) });
  135. foreach (var pair in sequence)
  136. {
  137. if (!fuelMappingDict.ContainsKey(pair.Barcode))
  138. {
  139. fuelMappingDict.Add(pair.Barcode, pair.FuelNo);
  140. }
  141. }
  142. }
  143. }
  144. private int GetFuelNo(int barcode)
  145. {
  146. if (fuelMappingDict.ContainsKey(barcode))
  147. return fuelMappingDict[barcode];
  148. return -1;
  149. }
  150. private int GetBarcode(int fuelNo)
  151. {
  152. return fuelMappingDict.FirstOrDefault(x => x.Value == fuelNo).Key;
  153. }
  154. #endregion
  155. #region IApplication implementation, Init
  156. public void Init(IEnumerable<IProcessor> processors)
  157. {
  158. dbMonitor = new DbMonitor(scanInterval, _mySqlConn, smartFuel05Compatible);
  159. dataCourier =
  160. new DataCourier(username, password, authServiceBaseUrl, accountServiceBaseUrl, accountServiceRelativeUrl, deviceSN, retryCount);
  161. if (enableSync)
  162. {
  163. downloader = new Downloader(connectionInfo, dbMonitor, _mySqlConn, syncInterval, checkVersionRelativeUrl,
  164. syncDataRelativeUrl, excludeCurrentSite);
  165. }
  166. }
  167. #endregion
  168. #region Start
  169. public Task<bool> Start()
  170. {
  171. // Hook up the events.
  172. dbMonitor.OnCardTrxCreated += DbMonitor_OnCardTrxCreated;
  173. dbMonitor.OnRechargeCreated += DbMonitor_OnRechargeCreated;
  174. dbMonitor.OnAccountCreated += DbMonitor_OnAccountCreated;
  175. dbMonitor.OnAccountUpdated += DbMonitor_OnAccountUpdated;
  176. dbMonitor.OnCardInfoCreated += DbMonitor_OnCardInfoCreated;
  177. dbMonitor.OnCardInfoUpdated += DbMonitor_OnCardInfoUpdated;
  178. dbMonitor.OnCardInfoDeleted += DbMonitor_OnCardInfoDeleted;
  179. // cardreploss
  180. dbMonitor.OnLostCardCreated += DbMonitor_OnLostCardCreated;
  181. // cardlogout
  182. dbMonitor.OnClosedCardCreated += DbMonitor_OnClosedCardCreated;
  183. // base black card
  184. dbMonitor.OnBaseBlackCardCreated += DbMonitor_OnBaseBlackCardCreated;
  185. dbMonitor.OnBaseBlackCardDeleted += DbMonitor_OnBaseBlackCardDeleted;
  186. // add black card
  187. dbMonitor.OnBlacklistedCardCreated += DbMonitor_OnBlacklistedCardCreated;
  188. dbMonitor.OnBlacklistedCardUpdated += DbMonitor_OnBlacklistedCardUpdated;
  189. dbMonitor.OnBlacklistedCardDeleted += DbMonitor_OnBlacklistedCardDeleted;
  190. // delete black card
  191. dbMonitor.OnReleasedCardCreated += DbMonitor_OnReleasedCardCreated;
  192. dbMonitor.OnReleasedCardDeleted += DbMonitor_OnReleasedCardDeleted;
  193. dbMonitor.OnGrayInfoCreated += DbMonitor_OnGrayInfoCreated;
  194. dbMonitor.OnGrayInfoDeleted += DbMonitor_OnGrayInfoDeleted;
  195. dbMonitor.OnMultipleAccountsCreated += DbMonitor_OnMultipleAccountsCreated;
  196. dbMonitor.OnMultipleAccountsUpdated += DbMonitor_OnMultipleAccountsUpdated;
  197. dbMonitor.OnMultipleCardsCreated += DbMonitor_OnMultipleCardsCreated;
  198. dbMonitor.OnMultipleCardsUpdated += DbMonitor_OnMultipleCardsUpdated;
  199. // Migrate database
  200. using (var context = new GuardDbContext())
  201. {
  202. context.Database.Migrate();
  203. }
  204. ThreadPool.QueueUserWorkItem(arg =>
  205. {
  206. StartDbMonitor();
  207. if (downloader != null)
  208. downloader.Start();
  209. });
  210. ThreadPool.QueueUserWorkItem(arg =>
  211. {
  212. UploadExistingData();
  213. });
  214. return Task.FromResult(true);
  215. }
  216. #endregion
  217. #region Stop
  218. public Task<bool> Stop()
  219. {
  220. if (dbMonitor != null)
  221. {
  222. // Unhook the events.
  223. dbMonitor.OnCardTrxCreated -= DbMonitor_OnCardTrxCreated;
  224. dbMonitor.OnRechargeCreated -= DbMonitor_OnRechargeCreated;
  225. dbMonitor.OnAccountCreated -= DbMonitor_OnAccountCreated;
  226. dbMonitor.OnAccountUpdated -= DbMonitor_OnAccountUpdated;
  227. dbMonitor.OnCardInfoCreated -= DbMonitor_OnCardInfoCreated;
  228. dbMonitor.OnCardInfoUpdated -= DbMonitor_OnCardInfoUpdated;
  229. dbMonitor.OnCardInfoDeleted -= DbMonitor_OnCardInfoDeleted;
  230. // cardreploss
  231. dbMonitor.OnLostCardCreated -= DbMonitor_OnLostCardCreated;
  232. // cardlogout
  233. dbMonitor.OnClosedCardCreated -= DbMonitor_OnClosedCardCreated;
  234. // base black card
  235. dbMonitor.OnBaseBlackCardCreated -= DbMonitor_OnBaseBlackCardCreated;
  236. dbMonitor.OnBaseBlackCardDeleted -= DbMonitor_OnBaseBlackCardDeleted;
  237. // add black card
  238. dbMonitor.OnBlacklistedCardCreated -= DbMonitor_OnBlacklistedCardCreated;
  239. dbMonitor.OnBlacklistedCardUpdated -= DbMonitor_OnBlacklistedCardUpdated;
  240. dbMonitor.OnBlacklistedCardDeleted -= DbMonitor_OnBlacklistedCardDeleted;
  241. // delete black card
  242. dbMonitor.OnReleasedCardCreated -= DbMonitor_OnReleasedCardCreated;
  243. dbMonitor.OnReleasedCardDeleted -= DbMonitor_OnReleasedCardDeleted;
  244. dbMonitor.OnGrayInfoCreated -= DbMonitor_OnGrayInfoCreated;
  245. dbMonitor.OnGrayInfoDeleted -= DbMonitor_OnGrayInfoDeleted;
  246. dbMonitor.OnMultipleAccountsCreated -= DbMonitor_OnMultipleAccountsCreated;
  247. dbMonitor.OnMultipleAccountsUpdated -= DbMonitor_OnMultipleAccountsUpdated;
  248. dbMonitor.OnMultipleCardsCreated -= DbMonitor_OnMultipleCardsCreated;
  249. dbMonitor.OnMultipleCardsUpdated -= DbMonitor_OnMultipleCardsUpdated;
  250. dbMonitor.Stop();
  251. }
  252. return Task.FromResult(true);
  253. }
  254. #endregion
  255. #region Event handlers
  256. #region OnAccountCreated
  257. // New account created
  258. private void DbMonitor_OnAccountCreated(object sender, EntryFoundEventArgs e)
  259. {
  260. if (e.TableAudit.AccountCreated.HasValue && e.TableAudit.AccountCreated.Value != 0)
  261. {
  262. using (var context = new SpsDbContext(_mySqlConn))
  263. {
  264. var record = context.TAcctinfo.FirstOrDefault(a => a.Gid == Convert.ToUInt64(e.TableAudit.AccountCreated.Value));
  265. if (record != null)
  266. {
  267. var result = SubmitAccountRecordAsync(record, HostOperationType.CreateAccount).Result;
  268. logger.Info($"Just try to submit a new Account for AccoutId: {record.AcctId}, GID: {record.Gid}, Success? {result.Success}");
  269. if (result.Success)
  270. {
  271. context.TTableaudit.Remove(e.TableAudit);
  272. var val = context.SaveChanges();
  273. }
  274. else
  275. {
  276. //In case that host returns failure, should retry later on.
  277. logger.Warn("Result not success, don't remove the Created account record");
  278. //context.TTableaudit.Remove(e.TableAudit);
  279. //var val = context.SaveChanges();
  280. }
  281. }
  282. else
  283. {
  284. logger.Error("Stange, could not find the record for created account!");
  285. context.TTableaudit.Remove(e.TableAudit);
  286. context.SaveChanges();
  287. }
  288. }
  289. }
  290. }
  291. #endregion
  292. #region OnAccountUpdated
  293. //Account updated
  294. private async void DbMonitor_OnAccountUpdated(object sender, EntryFoundEventArgs e)
  295. {
  296. if (e.TableAudit.AccountUpdated.HasValue && e.TableAudit.AccountUpdated.Value != 0)
  297. {
  298. using (var context = new SpsDbContext(_mySqlConn))
  299. {
  300. var record = await
  301. context.TAcctinfo.FirstOrDefaultAsync(a => a.Gid == Convert.ToUInt64(e.TableAudit.AccountUpdated.Value));
  302. if (record != null)
  303. {
  304. var result = SubmitAccountRecordAsync(record, HostOperationType.UpdateAccount).Result;
  305. logger.Info($"Update account info, AccountId: {record.AcctId}, Name: {record.BelongTo}, Result: {result.Success}");
  306. if (result.Success)
  307. {
  308. CleanupRecord(context, e.TableAudit);
  309. }
  310. else
  311. {
  312. // Upload failed, should retry later on.
  313. logger.Warn("Result not success, shall retry uploading the Updated Account record");
  314. }
  315. }
  316. else
  317. {
  318. logger.Error("Could not find the Updated Account record");
  319. // Makes no sense to keep it.
  320. CleanupRecord(context, e.TableAudit);
  321. }
  322. }
  323. }
  324. }
  325. #endregion
  326. #region Record cleanup
  327. private int CleanupRecord(SpsDbContext context, TTableaudit entity)
  328. {
  329. logger.Info("Cleaning up...");
  330. try
  331. {
  332. context.TTableaudit.Remove(entity);
  333. return context.SaveChanges();
  334. }
  335. catch (Exception ex)
  336. {
  337. logger.Error(ex.ToString());
  338. }
  339. return 0;
  340. }
  341. #endregion
  342. #region CardInfoCreated
  343. //New card issued (card info created)
  344. private void DbMonitor_OnCardInfoCreated(object sender, EntryFoundEventArgs e)
  345. {
  346. if (e.TableAudit.CardInfoCreated.HasValue && e.TableAudit.CardInfoCreated.Value != 0)
  347. {
  348. using (var context = new SpsDbContext(_mySqlConn))
  349. {
  350. var record = context.TCardinfo.FirstOrDefault(c => c.Gid == Convert.ToUInt64(e.TableAudit.CardInfoCreated.Value));
  351. if (record != null)
  352. {
  353. var result = SubmitCardInfoAsync(record, HostOperationType.CreateCard).Result;
  354. logger.Info($"Submit a new CardInfo for CardNo: {record.CardNo}, AccountId: {record.AcctId} Success? {result.Success}");
  355. if (result.Success)
  356. {
  357. CleanupRecord(context, e.TableAudit);
  358. }
  359. else
  360. {
  361. // Retry later on when host returns failure.
  362. logger.Warn("Result not success, shall retry uploading Created Card Info");
  363. if (result.Code == 4)
  364. {
  365. HandleMissingAccount(context, record.AcctId);
  366. }
  367. }
  368. }
  369. else
  370. {
  371. logger.Error("That's strange, a new CardInfo created, but I can't find it in the table...");
  372. // Makes no sense to keep it here.
  373. CleanupRecord(context, e.TableAudit);
  374. }
  375. }
  376. }
  377. }
  378. #endregion
  379. #region CardInfoUpdated
  380. //Card info updated (could be personal inforation updated)
  381. private async void DbMonitor_OnCardInfoUpdated(object sender, EntryFoundEventArgs e)
  382. {
  383. if (e.TableAudit.CardInfoUpdated.HasValue && e.TableAudit.CardInfoUpdated.Value != 0)
  384. {
  385. using (var context = new SpsDbContext(_mySqlConn))
  386. {
  387. var record = await context.TCardinfo.FirstOrDefaultAsync(c => c.Gid == Convert.ToUInt64(e.TableAudit.CardInfoUpdated.Value));
  388. if (record != null)
  389. {
  390. // Find if there is a closed (deactivated) card.
  391. var closedCard = await context.TCardlogout
  392. .FirstOrDefaultAsync(cl => cl.AcctId == record.AcctId && cl.Holder == record.Holder);
  393. if (closedCard != null)
  394. {
  395. if (closedCard.LgtDate.HasValue && (DateTime.Now - closedCard.LgtDate.Value) < TimeSpan.FromHours(24))
  396. {
  397. //Assume the card was replaced!
  398. var result = SubmitCardInfoAsync(record, HostOperationType.CreateCard).Result;
  399. logger.Info($"A card closed and a new card replacement created, " +
  400. $"CardNo: {record.CardNo}, Balance: {record.Money}, Result: {result.Success}");
  401. if (result.Success)
  402. {
  403. CleanupRecord(context, e.TableAudit);
  404. }
  405. else
  406. {
  407. logger.Warn("Result not success, should try again on Updated Card Info");
  408. }
  409. }
  410. else
  411. {
  412. var result = SubmitCardInfoAsync(record, HostOperationType.UpdateCard).Result;
  413. logger.Info($"Update card info, CardNo: {record.CardNo}, Balance: {record.Money}, PreMalloc: {record.PreMalloc}, Result: {result.Success}");
  414. if (result.Success)
  415. {
  416. CleanupRecord(context, e.TableAudit);
  417. }
  418. else
  419. {
  420. logger.Warn("Result not success, should try again on Updated Card Info");
  421. }
  422. }
  423. }
  424. else
  425. {
  426. var result = SubmitCardInfoAsync(record, HostOperationType.UpdateCard).Result;
  427. logger.Info($"Update card info, CardNo: {record.CardNo}, Balance: {record.Money}, Result: {result.Success}");
  428. if (result.Success)
  429. {
  430. CleanupRecord(context, e.TableAudit);
  431. }
  432. else
  433. {
  434. logger.Warn("Result not success, should try again on Updated Card Info");
  435. }
  436. }
  437. }
  438. else
  439. {
  440. logger.Error("*** Could not find the card info record");
  441. CleanupRecord(context, e.TableAudit);
  442. }
  443. }
  444. }
  445. }
  446. #endregion
  447. #region CardInfoDeleted
  448. //Card info deleted (could be balance updated or card closed)
  449. private async void DbMonitor_OnCardInfoDeleted(object sender, CardChangedEventArgs e)
  450. {
  451. if (!string.IsNullOrEmpty(e.CardNo))
  452. {
  453. using (var context = new SpsDbContext(_mySqlConn))
  454. {
  455. var record = await context.TCardinfo
  456. .OrderBy(r => r.CardNo)
  457. .LastOrDefaultAsync(c => c.CardNo == e.CardNo);
  458. if (record != null)
  459. {
  460. logger.Info("Card info deleted, what can we do about it?");
  461. }
  462. else
  463. {
  464. logger.Info($"*** The card of CardNo: {e.CardNo} must be closed/deactivated.");
  465. }
  466. }
  467. if (e.TableAudit == null)
  468. {
  469. logger.Error("TableAudit is null");
  470. }
  471. using (var context = new SpsDbContext(_mySqlConn))
  472. {
  473. context.Attach(e.TableAudit);
  474. context.TTableaudit.Remove(e.TableAudit);
  475. context.SaveChanges();
  476. }
  477. }
  478. }
  479. #endregion
  480. #region CardTrxCreated
  481. private void DbMonitor_OnCardTrxCreated(object sender, CardTrxEventArgs e)
  482. {
  483. if (e.TableAudit.TransCreated.HasValue)
  484. {
  485. using (var context = new SpsDbContext(_mySqlConn))
  486. {
  487. FuelProductInfo fuelProduct = new FuelProductInfo();
  488. var trans = context.TTrdinfo.FirstOrDefault(t => t.Gid == Convert.ToUInt64(e.TableAudit.TransCreated.Value));
  489. if (trans != null)
  490. {
  491. TTrdinfo grayTrade = null;
  492. //In case it's ungray trade.
  493. if (trans.TrdType == 2)
  494. {
  495. grayTrade = context.TTrdinfo
  496. .FirstOrDefault(t => t.TrdType == 1 && t.Ctc == trans.Ctc && t.Ttctime == trans.Ttctime);
  497. }
  498. var fuel = context.TFuellist.FirstOrDefault(f => f.FuelNo == trans.CommId);
  499. if (fuel != null)
  500. {
  501. fuelProduct.FuelName = fuel.Name;
  502. fuelProduct.Barcode = GetBarcode(Convert.ToInt32(fuel.FuelNo)).ToString();
  503. }
  504. else
  505. {
  506. if (grayTrade != null)
  507. {
  508. fuel = context.TFuellist.FirstOrDefault(f => f.FuelNo == grayTrade.CommId);
  509. if (fuel != null)
  510. {
  511. fuelProduct.FuelName = fuel.Name;
  512. fuelProduct.Barcode = GetBarcode(Convert.ToInt32(fuel.FuelNo)).ToString();
  513. fuelProduct.Price = grayTrade.Prc.Value;
  514. }
  515. }
  516. }
  517. if (trans.TrdType == 10 || trans.TrdType == 11 || trans.TrdType == 8)
  518. {
  519. logger.Error($"Fuel change record or bank card payment record or fuel price download record, trdType: {trans.TrdType}, should be ignored");
  520. CleanupRecord(context, e.TableAudit);
  521. return;
  522. }
  523. var result = SubmitCardTrxRecordAsync(trans, grayTrade, fuelProduct).Result;
  524. logger.Info($"Just submit a new card payment record for " +
  525. $"CardNo {trans.CardNo}, TTCTime: {trans.Ttctime}, GID: {trans.Gid}, Success? {result.Success}");
  526. if (result.Success)
  527. {
  528. dbMonitor.AddToProcessedQueue(Convert.ToInt64(e.TableAudit.TransCreated.Value));
  529. try
  530. {
  531. var val = CleanupRecord(context, e.TableAudit);
  532. var spsDbMonitor = sender as DbMonitor;
  533. if (spsDbMonitor != null)
  534. {
  535. spsDbMonitor.ClearFromQueue(e.TableAudit);
  536. }
  537. logger.Info($"Removing the Trx record from table, result: {val}");
  538. }
  539. catch (Exception ex)
  540. {
  541. logger.Error(ex);
  542. }
  543. }
  544. else
  545. {
  546. var spsDbMonitor = sender as DbMonitor;
  547. if (spsDbMonitor != null)
  548. {
  549. spsDbMonitor.ClearFromQueue(e.TableAudit);
  550. }
  551. logger.Warn("Upload result not success, should try again on New Card Transaction later");
  552. if (result.Code == 3) // missing card
  553. {
  554. HandleMissingCard(context, trans.CardNo);
  555. }
  556. else if (result.Code == 4) // missing account
  557. {
  558. var account = context.TCardinfo.FirstOrDefault(c => c.CardNo == trans.CardNo);
  559. if (account != null)
  560. {
  561. HandleMissingAccount(context, account.AcctId);
  562. }
  563. }
  564. }
  565. }
  566. }
  567. }
  568. }
  569. #endregion
  570. #region Recharge and reduction created
  571. private void DbMonitor_OnRechargeCreated(object sender, EntryFoundEventArgs e)
  572. {
  573. if (e.TableAudit.RechargeCreated.HasValue && e.TableAudit.RechargeCreated.Value != 0)
  574. {
  575. using (var context = new SpsDbContext(_mySqlConn))
  576. {
  577. var record = context.TRechdebitRep.FirstOrDefault(r => r.Gid == Convert.ToUInt64(e.TableAudit.RechargeCreated.Value));
  578. if (record != null)
  579. {
  580. var result = SubmitRechargeReductionRecord(record).Result;
  581. logger.Info($"Just try to submit a new recharge/reduction reocrd for " +
  582. $"CardNo: {record.CardNo}, Amount: {record.Mon}, GID = {record.Gid}, Success? {result.Success}");
  583. if (result.Success)
  584. {
  585. CleanupRecord(context, e.TableAudit);
  586. }
  587. else
  588. {
  589. if (result.Code == 3)
  590. {
  591. logger.Info("Missing card, try to upload it first");
  592. HandleMissingCard(context, record.CardNo);
  593. }
  594. else if (result.Code == 4)
  595. {
  596. logger.Info("Missing account, try to upload it first");
  597. HandleMissingAccount(context, record.AcctId);
  598. }
  599. logger.Warn("Upload result not success, should try again on Recharge/Reduction later");
  600. }
  601. }
  602. }
  603. }
  604. }
  605. #endregion
  606. #region Lost card created
  607. //挂失卡或者解挂卡
  608. private void DbMonitor_OnLostCardCreated(object sender, EntryFoundEventArgs e)
  609. {
  610. logger.Info($"New report of lost card or card released");
  611. if (e.TableAudit.LostCardCreated.HasValue && e.TableAudit.LostCardCreated.Value != 0)
  612. {
  613. using (var context = new SpsDbContext(_mySqlConn))
  614. {
  615. var record = context.TCardreploss.FirstOrDefault(r => r.Gid == Convert.ToUInt64(e.TableAudit.LostCardCreated.Value));
  616. if (record != null)
  617. {
  618. var cardRepLossResult = SubmitCardRepLossAsync(record).Result;
  619. logger.Info($"Just try to submit a new CardRepLoss {record.CardNo}, GID = {record.Gid}, Success? {cardRepLossResult.Success}");
  620. var result = SubmitCardOperationInfoAsync(record, string.Empty).Result;
  621. logger.Info($"Just try to submit a new lost or released card for CardNo: {record.CardNo}, GID = {record.Gid}, Success? {result.Success}");
  622. if (result.Success && cardRepLossResult.Success)
  623. {
  624. CleanupRecord(context, e.TableAudit);
  625. }
  626. else
  627. {
  628. logger.Warn("Upload result not success, should try again on Lost Card later");
  629. }
  630. }
  631. }
  632. }
  633. }
  634. #endregion
  635. #region 注销卡 Closed card created
  636. //注销卡
  637. private void DbMonitor_OnClosedCardCreated(object sender, EntryFoundEventArgs e)
  638. {
  639. logger.Info($"New closed/deactivated card");
  640. if (e.TableAudit.ClosedCardCreated.HasValue && e.TableAudit.ClosedCardCreated.Value != 0)
  641. {
  642. using (var context = new SpsDbContext(_mySqlConn))
  643. {
  644. var record = context.TCardlogout.FirstOrDefault(r => r.Gid == Convert.ToUInt64(e.TableAudit.ClosedCardCreated.Value));
  645. if (record != null)
  646. {
  647. var result = SubmitCardOperationInfoAsync(null, record.CardNo).Result;
  648. logger.Info($"Just try to submit a new closed card for CardNo: {record.CardNo}, GID = {record.Gid}, Success? {result.Success}");
  649. if (result.Success)
  650. {
  651. CleanupRecord(context, e.TableAudit);
  652. }
  653. else
  654. {
  655. logger.Warn("Upload not success, should try again on Closed/Deactivated card later");
  656. }
  657. }
  658. }
  659. }
  660. }
  661. #endregion
  662. #region 基础黑名单 (t_blackcard)
  663. private void DbMonitor_OnBaseBlackCardCreated(object sender, EntryFoundEventArgs e)
  664. {
  665. logger.Info("Handling BlackCard record [Create]");
  666. if (e.TableAudit != null && e.TableAudit.BaseBlackCardCreated.HasValue)
  667. {
  668. using (var context = new SpsDbContext(_mySqlConn))
  669. {
  670. var record = context.TBlackcard
  671. .FirstOrDefault(r => r.Gid == Convert.ToUInt64(e.TableAudit.BaseBlackCardCreated.Value));
  672. if (record != null)
  673. {
  674. var listedCardInfo = new ListedCardInfo();
  675. listedCardInfo.ListedType = ListedType.Base; // base black card
  676. listedCardInfo.Gid = Convert.ToInt64(record.Gid);
  677. listedCardInfo.CardNo = record.CardNo;
  678. listedCardInfo.ListedDate =
  679. record.BlackDate == null ? DateTime.MinValue : record.BlackDate.Value;
  680. listedCardInfo.AccountGid = Convert.ToInt64(record.AcctGid);
  681. listedCardInfo.AccountId = record.AcctId;
  682. listedCardInfo.CardType = Convert.ToByte(record.CardType);
  683. listedCardInfo.DiscountNo =
  684. record.DiscountNo == null ? 0 : record.DiscountNo.Value;
  685. listedCardInfo.Reason = record.Reason;
  686. listedCardInfo.UploadFlag = Convert.ToByte(record.UploadFlag);
  687. listedCardInfo.OperationType = 0; // Create
  688. var result = SendListedCardAsync(listedCardInfo).Result;
  689. if (result.Success)
  690. {
  691. logger.Info($"Upload Base BlackCard record [Create] {record.CardNo}, success");
  692. CleanupRecord(context, e.TableAudit);
  693. }
  694. else
  695. {
  696. logger.Warn("Upload not successful, should try again later on Base BlackCard [CREATE]");
  697. }
  698. }
  699. else
  700. {
  701. logger.Warn($"Base BlackCard [Create], record gid: {e.TableAudit.BaseBlackCardCreated.Value} not found!");
  702. CleanupRecord(context, e.TableAudit);
  703. }
  704. }
  705. }
  706. }
  707. private void DbMonitor_OnBaseBlackCardDeleted(object sender, CardChangedEventArgs e)
  708. {
  709. if (e.TableAudit != null && !string.IsNullOrEmpty(e.TableAudit.BaseBlackCardDeleted))
  710. {
  711. logger.Info($"Handling BlackCard record [Delete], original Card No: {e.TableAudit.BaseBlackCardDeleted}");
  712. var listedCard = new ListedCardInfo();
  713. listedCard.CardNo = e.TableAudit.BaseBlackCardDeleted;
  714. listedCard.ListedType = ListedType.Base; // base black card
  715. listedCard.OperationType = 2; //delete
  716. var result = SendListedCardAsync(listedCard).Result;
  717. if (result.Success)
  718. {
  719. logger.Info($"Upload Base BlackCard [Deleted], Card No: {e.TableAudit.BaseBlackCardDeleted}, success");
  720. using (var context = new SpsDbContext(_mySqlConn))
  721. {
  722. CleanupRecord(context, e.TableAudit);
  723. }
  724. }
  725. else
  726. {
  727. logger.Info($"Upload Base BlackCard [Deleted], Card No: {e.TableAudit.BaseBlackCardDeleted} failed, should try again later");
  728. }
  729. }
  730. }
  731. #endregion
  732. #region 增量黑名单卡 (t_addblackcard)
  733. //增量黑名单卡 - Created
  734. private void DbMonitor_OnBlacklistedCardCreated(object sender, EntryFoundEventArgs e)
  735. {
  736. logger.Info("Handling AddBlackCard record [Create]");
  737. if (e.TableAudit != null && e.TableAudit.BlacklistedCardCreated.HasValue)
  738. {
  739. using (var context = new SpsDbContext(_mySqlConn))
  740. {
  741. var record = context.TAddblackcard
  742. .FirstOrDefault(r => r.Gid == Convert.ToUInt64(e.TableAudit.BlacklistedCardCreated.Value));
  743. if (record != null)
  744. {
  745. var listedCardInfo = new ListedCardInfo();
  746. listedCardInfo.ListedType = ListedType.Add; // add black card
  747. listedCardInfo.Gid = Convert.ToInt64(record.Gid);
  748. listedCardInfo.CardNo = record.CardNo;
  749. listedCardInfo.ListedDate =
  750. record.BlackDate == null ? DateTime.MinValue : record.BlackDate.Value;
  751. listedCardInfo.AccountGid = Convert.ToInt64(record.AcctGid);
  752. listedCardInfo.AccountId = record.AcctId;
  753. listedCardInfo.CardType = Convert.ToByte(record.CardType);
  754. listedCardInfo.DiscountNo =
  755. record.DiscountNo == null ? 0 : record.DiscountNo.Value;
  756. listedCardInfo.Reason = record.Reason;
  757. listedCardInfo.UploadFlag = Convert.ToByte(record.UploadFlag);
  758. listedCardInfo.OperationType = 0; // Create
  759. var result = SendListedCardAsync(listedCardInfo).Result;
  760. if (result.Success)
  761. {
  762. logger.Info($"Upload AddBlackCard record [Create] {record.CardNo}, success");
  763. CleanupRecord(context, e.TableAudit);
  764. }
  765. else
  766. {
  767. logger.Warn("Upload not successful, should try again later on AddBlackCard [CREATE]");
  768. }
  769. }
  770. else
  771. {
  772. logger.Warn($"AddBlackCard [Create], record gid: {e.TableAudit.BlacklistedCardUpdated.Value} not found!");
  773. CleanupRecord(context, e.TableAudit);
  774. }
  775. }
  776. }
  777. }
  778. //增量黑名单卡 - Updated
  779. private void DbMonitor_OnBlacklistedCardUpdated(object sender, EntryFoundEventArgs e)
  780. {
  781. logger.Info($"Handling AddBlackCard record [Update]");
  782. if (e.TableAudit != null && e.TableAudit.BlacklistedCardUpdated.HasValue)
  783. {
  784. using (var context = new SpsDbContext(_mySqlConn))
  785. {
  786. var record = context.TAddblackcard
  787. .FirstOrDefault(r => r.Gid == Convert.ToUInt64(e.TableAudit.BlacklistedCardUpdated.Value));
  788. if (record != null)
  789. {
  790. var listedCardInfo = new ListedCardInfo();
  791. listedCardInfo.ListedType = ListedType.Add; // add black card
  792. listedCardInfo.Gid = Convert.ToInt64(record.Gid);
  793. listedCardInfo.CardNo = record.CardNo;
  794. listedCardInfo.ListedDate =
  795. record.BlackDate == null ? DateTime.MinValue : record.BlackDate.Value;
  796. listedCardInfo.AccountGid = Convert.ToInt64(record.AcctGid);
  797. listedCardInfo.AccountId = record.AcctId;
  798. listedCardInfo.CardType = Convert.ToByte(record.CardType);
  799. listedCardInfo.DiscountNo =
  800. record.DiscountNo == null ? 0 : record.DiscountNo.Value;
  801. listedCardInfo.Reason = record.Reason;
  802. listedCardInfo.UploadFlag = Convert.ToByte(record.UploadFlag);
  803. listedCardInfo.OperationType = 1; // Update
  804. var result = SendListedCardAsync(listedCardInfo).Result;
  805. if (result.Success)
  806. {
  807. logger.Info($"Upload AddBlackCard record [Update] {record.CardNo}, success");
  808. CleanupRecord(context, e.TableAudit);
  809. }
  810. else
  811. {
  812. logger.Warn("Upload not successful, should try again later on AddBlackCard [UPDATE]");
  813. }
  814. }
  815. else
  816. {
  817. logger.Warn($"AddBlackCard [Update], record gid: {e.TableAudit.BlacklistedCardUpdated.Value} not found!");
  818. CleanupRecord(context, e.TableAudit);
  819. }
  820. }
  821. }
  822. }
  823. //增量黑名单卡 - Deleted
  824. private void DbMonitor_OnBlacklistedCardDeleted(object sender, CardChangedEventArgs e)
  825. {
  826. if (e.TableAudit != null && !string.IsNullOrEmpty(e.TableAudit.BlacklistedCardDeleted))
  827. {
  828. logger.Info($"Handling AddBlackCard record [Delete], original Card No: {e.TableAudit.BlacklistedCardDeleted}");
  829. var listedCard = new ListedCardInfo();
  830. listedCard.CardNo = e.TableAudit.BlacklistedCardDeleted;
  831. listedCard.ListedType = ListedType.Add; // add black card
  832. listedCard.OperationType = 2; //delete
  833. var result = SendListedCardAsync(listedCard).Result;
  834. if (result.Success)
  835. {
  836. logger.Info($"Upload AddBlackCard [Deleted], Card No: {e.TableAudit.BlacklistedCardDeleted}, success");
  837. using (var context = new SpsDbContext(_mySqlConn))
  838. {
  839. CleanupRecord(context, e.TableAudit);
  840. }
  841. }
  842. else
  843. {
  844. logger.Info($"Upload AddBlackCard [Deleted], Card No: {e.TableAudit.BlacklistedCardDeleted} failed, should try again later");
  845. }
  846. }
  847. }
  848. #endregion
  849. #region 减量黑名单 (t_deleteBlackCard)
  850. //减量黑名单卡
  851. private void DbMonitor_OnReleasedCardDeleted(object sender, CardChangedEventArgs e)
  852. {
  853. if (e.TableAudit != null && !string.IsNullOrEmpty(e.TableAudit.ReleasedCardDeleted))
  854. {
  855. logger.Info($"Handling DeleteBlackCard record [Delete], Card No: {e.TableAudit.ReleasedCardDeleted}");
  856. var listedCard = new ListedCardInfo();
  857. listedCard.CardNo = e.TableAudit.ReleasedCardDeleted;
  858. listedCard.ListedType = ListedType.Deleted; // Delete black card
  859. listedCard.OperationType = 2; //delete
  860. var result = SendListedCardAsync(listedCard).Result;
  861. if (result.Success)
  862. {
  863. logger.Info($"Upload DeleteBlackCard record [Deleted], Card No: {e.TableAudit.BlacklistedCardDeleted}, success");
  864. using (var context = new SpsDbContext(_mySqlConn))
  865. {
  866. CleanupRecord(context, e.TableAudit);
  867. }
  868. }
  869. else
  870. {
  871. logger.Info($"Upload DeleteBlackCard record [Deleted], Card No: {e.TableAudit.BlacklistedCardDeleted} failed, should try again later");
  872. }
  873. }
  874. }
  875. private void DbMonitor_OnReleasedCardCreated(object sender, EntryFoundEventArgs e)
  876. {
  877. logger.Info("Handling DeleteBlackCard record [Create]");
  878. if (e.TableAudit != null && e.TableAudit.ReleasedCardCreated.HasValue)
  879. {
  880. using (var context = new SpsDbContext(_mySqlConn))
  881. {
  882. var record = context.TDeleteblackcard
  883. .FirstOrDefault(r => r.Gid == Convert.ToUInt64(e.TableAudit.ReleasedCardCreated.Value));
  884. if (record != null)
  885. {
  886. var listedCardInfo = new ListedCardInfo();
  887. listedCardInfo.ListedType = ListedType.Deleted; //delete black card
  888. listedCardInfo.Gid = Convert.ToInt64(record.Gid);
  889. listedCardInfo.CardNo = record.CardNo;
  890. listedCardInfo.ListedDate =
  891. record.BlackDate == null ? DateTime.MinValue : record.BlackDate.Value;
  892. listedCardInfo.AccountGid = Convert.ToInt64(record.AcctGid);
  893. listedCardInfo.AccountId = record.AcctId;
  894. listedCardInfo.CardType = Convert.ToByte(record.CardType);
  895. listedCardInfo.DiscountNo =
  896. record.DiscountNo == null ? 0 : record.DiscountNo.Value;
  897. listedCardInfo.Reason = record.Reason;
  898. listedCardInfo.UploadFlag = Convert.ToByte(record.UploadFlag);
  899. listedCardInfo.OperationType = 0; // Create
  900. var result = SendListedCardAsync(listedCardInfo).Result;
  901. if (result.Success)
  902. {
  903. logger.Info($"Upload DeleteBlackCard record [Create]: {record.CardNo}, success");
  904. CleanupRecord(context, e.TableAudit);
  905. }
  906. else
  907. {
  908. logger.Warn("Upload not successful, should try again later on DeleteBlackCard [Create]");
  909. }
  910. }
  911. else
  912. {
  913. logger.Warn($"DeleteBlackCard record, gid: {e.TableAudit.ReleasedCardCreated.Value} not found!");
  914. CleanupRecord(context, e.TableAudit);
  915. }
  916. }
  917. }
  918. }
  919. #endregion
  920. #region 基础黑名单 (t_blackcard)
  921. // to be implemented...
  922. #endregion
  923. #region 灰名单 (t_grayinfo)
  924. private void DbMonitor_OnGrayInfoCreated(object sender, EntryFoundEventArgs e)
  925. {
  926. if (e.TableAudit.GrayInfoDeleted != null && e.TableAudit.GrayInfoCreated.Value != 0)
  927. {
  928. logger.Info($"Handling GrayInfo record [Create] Gid: {e.TableAudit.GrayInfoCreated.Value}");
  929. using (var context = new SpsDbContext(_mySqlConn))
  930. {
  931. var record = context.TGrayinfo
  932. .FirstOrDefault(g => g.Gid == Convert.ToUInt64(e.TableAudit.GrayInfoCreated.Value));
  933. if (record != null)
  934. {
  935. var grayInfo = CreateGrayInfoFromRecord(record);
  936. var result = SendGrayInfoAsync(grayInfo).Result;
  937. if (result.Success)
  938. {
  939. logger.Info($"Upload GrayInfo record [Create]: {record.CardNo}, success");
  940. CleanupRecord(context, e.TableAudit);
  941. }
  942. else
  943. {
  944. logger.Warn("Upload not successful, should try again later on GrayInfo [Create]");
  945. }
  946. }
  947. else
  948. {
  949. logger.Info($"Gray info, gid={e.TableAudit.GrayInfoCreated.Value} could not be found.");
  950. CleanupRecord(context, e.TableAudit);
  951. }
  952. }
  953. }
  954. }
  955. private GrayInfo CreateGrayInfoFromRecord(TGrayinfo record)
  956. {
  957. if (record == null)
  958. return null;
  959. var grayInfo = new GrayInfo();
  960. grayInfo.Gid = record.Gid;
  961. grayInfo.SNo = (int)record.Sno;
  962. grayInfo.PumpType = (byte)record.PumpType;
  963. grayInfo.CardNo = record.CardNo;
  964. grayInfo.PaymodeId = (byte)record.PaymodeId;
  965. grayInfo.TrdType = (byte)record.TrdType;
  966. grayInfo.CommId = record.CommId;
  967. grayInfo.Price = (uint)record.Prc;
  968. grayInfo.Volume = (uint)record.Vol;
  969. grayInfo.Money = (uint)record.Mon;
  970. grayInfo.RealMon = (uint)record.RealMon;
  971. grayInfo.CardBalance = (uint)record.CardBal;
  972. grayInfo.Ctc = (uint)record.Ctc;
  973. grayInfo.TtcTime =
  974. record.Ttctime.HasValue ? record.Ttctime.Value.ToString("yyyy-MM-dd HH:mm:ss") : "0001-01-01 00:00:00";
  975. grayInfo.TtcTimeEnd =
  976. record.TtctimeEnd.HasValue ? record.TtctimeEnd.Value.ToString("yyyy-MM-dd HH:mm:ss") : "0001-01-01 00:00:00";
  977. grayInfo.Ttc = (uint)record.Ttc;
  978. grayInfo.SeqNo = Convert.ToUInt16(record.SeqNo);
  979. grayInfo.NozNo = (byte)record.NozNo;
  980. grayInfo.PumpNo = (byte)record.PumpNo;
  981. grayInfo.PayTermId = (ulong)record.PayTemId;
  982. grayInfo.EndPumpId = (ulong)record.EndPumpId;
  983. grayInfo.DiscountNo = (uint)record.DiscountNo;
  984. grayInfo.PsamAsn = record.Psamasn;
  985. grayInfo.PsamTac = (uint)record.Psamtac;
  986. grayInfo.PsamTid = record.Psamtid;
  987. grayInfo.PsamTtc = (uint)record.Psamttc;
  988. grayInfo.Tac = (uint)record.Tac;
  989. grayInfo.Gmac = (uint)record.Gmac;
  990. grayInfo.Tmac = (uint)record.Tmac;
  991. grayInfo.UploadFlag = (byte)record.UploadFlag;
  992. grayInfo.OperationType = 0; // Record creation
  993. return grayInfo;
  994. }
  995. private void DbMonitor_OnGrayInfoDeleted(object sender, EntryFoundEventArgs e)
  996. {
  997. logger.Info($"Handling GrayInfo record [Delete], Card No: {e.TableAudit.GrayInfoDeleted}");
  998. var grayInfo = new GrayInfo();
  999. grayInfo.CardNo = e.TableAudit.GrayInfoDeleted;
  1000. grayInfo.OperationType = 2; // Record Deletion
  1001. var result = SendGrayInfoAsync(grayInfo).Result;
  1002. if (result.Success)
  1003. {
  1004. logger.Info($"Upload GrayInfo record [Delete], Card No: {e.TableAudit.GrayInfoDeleted}, success");
  1005. using (var context = new SpsDbContext(_mySqlConn))
  1006. {
  1007. logger.Info($"Removing GrayInfo [Delete] audit entry");
  1008. CleanupRecord(context, e.TableAudit);
  1009. }
  1010. }
  1011. else
  1012. {
  1013. logger.Warn("Upload not successful, should try again later on GrayInfo [Delete]");
  1014. }
  1015. }
  1016. private async Task<SendResult> SendGrayInfoAsync(GrayInfo grayInfo)
  1017. {
  1018. var offlineRequest = new OfflineRequest();
  1019. offlineRequest.GrayInfoList = new List<GrayInfo>();
  1020. offlineRequest.GrayInfoList.Add(grayInfo);
  1021. var result = await dataCourier.SendRequest(offlineRequest, HostOperationType.GrayInfo);
  1022. return result;
  1023. }
  1024. #endregion
  1025. #region Multiple records handling
  1026. // Multiple `CREATED` acctinfo
  1027. private void DbMonitor_OnMultipleAccountsCreated(object sender, MultipleAccountRecordsEventArgs e)
  1028. {
  1029. var auditCount = e.AuditRecords.Count();
  1030. var accountInfoCount = e.AccountInfoRecords.Count();
  1031. if (accountInfoCount > 0)
  1032. logger.Info($"Multiple created account, count: {auditCount}, to be submitted count: {accountInfoCount}");
  1033. try
  1034. {
  1035. using (var context = new SpsDbContext(_mySqlConn))
  1036. {
  1037. var result = SubmitMultipleAccountRecordsAsync(e.AccountInfoRecords, HostOperationType.CreateAccount).GetAwaiter().GetResult();
  1038. if (result.Success)
  1039. {
  1040. context.RemoveRange(e.AuditRecords);
  1041. var affectedRowCount = context.SaveChanges();
  1042. logger.Info($"Cleaning up multiple created account info, affected row count: {affectedRowCount}");
  1043. }
  1044. }
  1045. }
  1046. catch (Exception ex)
  1047. {
  1048. logger.Error(ex.ToString());
  1049. }
  1050. }
  1051. // Multiple `UPDATED` acctinfo
  1052. private void DbMonitor_OnMultipleAccountsUpdated(object sender, MultipleAccountRecordsEventArgs e)
  1053. {
  1054. var auditCount = e.AuditRecords.Count();
  1055. var accountInfoCount = e.AccountInfoRecords.Count();
  1056. if (accountInfoCount > 0)
  1057. logger.Info($"Multiple updated account, count: {auditCount}, to be submitted count: {accountInfoCount}");
  1058. try
  1059. {
  1060. using (var context = new SpsDbContext(_mySqlConn))
  1061. {
  1062. var result = SubmitMultipleAccountRecordsAsync(e.AccountInfoRecords, HostOperationType.UpdateAccount).GetAwaiter().GetResult();
  1063. if (result.Success)
  1064. {
  1065. context.RemoveRange(e.AuditRecords);
  1066. var affectedRowCount = context.SaveChanges();
  1067. logger.Info($"Cleaning up multiple updated account info, affected row count: {affectedRowCount}");
  1068. }
  1069. }
  1070. }
  1071. catch (Exception ex)
  1072. {
  1073. logger.Error(ex.ToString());
  1074. }
  1075. }
  1076. // Multiple `CREATED` cardinfo
  1077. private void DbMonitor_OnMultipleCardsCreated(object sender, MultipleCardRecordsEventArgs e)
  1078. {
  1079. var auditCount = e.AuditRecords.Count();
  1080. var cardInfoCount = e.CardInfoRecords.Count();
  1081. if (cardInfoCount > 0)
  1082. logger.Info($"Multiple created cards, count: {auditCount}, to be submitted count: {cardInfoCount}");
  1083. try
  1084. {
  1085. using (var context = new SpsDbContext(_mySqlConn))
  1086. {
  1087. var result = SubmitMultipleCardInfoAsync(e.CardInfoRecords, HostOperationType.CreateCard).GetAwaiter().GetResult();
  1088. if (result.Success)
  1089. {
  1090. context.RemoveRange(e.AuditRecords);
  1091. var affectedRowCount = context.SaveChanges();
  1092. logger.Info($"Cleaning up multiple created cards, affected row count: {affectedRowCount}");
  1093. }
  1094. }
  1095. }
  1096. catch (Exception ex)
  1097. {
  1098. logger.Error(ex.ToString());
  1099. }
  1100. }
  1101. // Multiple `UPDATED` cardinfo
  1102. private void DbMonitor_OnMultipleCardsUpdated(object sender, MultipleCardRecordsEventArgs e)
  1103. {
  1104. var auditCount = e.AuditRecords.Count();
  1105. var cardInfoCount = e.CardInfoRecords.Count();
  1106. if (cardInfoCount > 0)
  1107. logger.Info($"Multiple updated cards, count: {auditCount}, to be submitted count: {cardInfoCount}");
  1108. try
  1109. {
  1110. using (var context = new SpsDbContext(_mySqlConn))
  1111. {
  1112. var result = SubmitMultipleCardInfoAsync(e.CardInfoRecords, HostOperationType.UpdateCard).GetAwaiter().GetResult();
  1113. if (result.Success)
  1114. {
  1115. context.RemoveRange(e.AuditRecords);
  1116. var affectedRowCount = context.SaveChanges();
  1117. logger.Info($"Cleaning up multiple updated cards, affected row count: {affectedRowCount}");
  1118. }
  1119. }
  1120. }
  1121. catch (Exception ex)
  1122. {
  1123. logger.Error(ex.ToString());
  1124. }
  1125. }
  1126. #endregion
  1127. #endregion
  1128. #region Force upload transaction
  1129. public async Task ForceTransactionUploadAsync(long gid)
  1130. {
  1131. logger.Info("Force uploading a transaction record...");
  1132. if (dbMonitor.IsTransAlreadyUploaded(gid))
  1133. {
  1134. logger.Warn($"The transaction of GID: {gid} was uploaded, do nothing about it!");
  1135. return;
  1136. }
  1137. var addResult = dbMonitor.AddToQueue(gid);
  1138. if (!addResult)
  1139. {
  1140. logger.Info("No need to handle it now, since db monitor already found it");
  1141. return;
  1142. }
  1143. logger.Info($"Ready to go ahead to upload transaction of GID: {gid}");
  1144. using (var context = new SpsDbContext(_mySqlConn))
  1145. {
  1146. FuelProductInfo fuelProduct = new FuelProductInfo();
  1147. var trans = await context.TTrdinfo.FirstOrDefaultAsync(t => t.Gid == Convert.ToUInt64(gid));
  1148. if (trans != null)
  1149. {
  1150. logger.Info($" The transaction information of GID: {gid} is retrieved");
  1151. TTrdinfo grayTrade = null;
  1152. //In case it's ungray trade.
  1153. if (trans.TrdType == 2)
  1154. {
  1155. grayTrade = context.TTrdinfo
  1156. .FirstOrDefault(t => t.TrdType == 1 && t.CardNo == trans.CardNo
  1157. && t.Ctc == trans.Ctc && t.Ttctime == trans.Ttctime);
  1158. }
  1159. var fuel = context.TFuellist.FirstOrDefault(f => f.FuelNo == trans.CommId);
  1160. if (fuel != null)
  1161. {
  1162. logger.Info("fuel is not null");
  1163. fuelProduct.FuelName = fuel.Name;
  1164. fuelProduct.Barcode = GetBarcode(Convert.ToInt32(fuel.FuelNo)).ToString();
  1165. }
  1166. else
  1167. {
  1168. logger.Info("Fuel is null");
  1169. if (grayTrade != null)
  1170. {
  1171. logger.Info("get fuel from gray trans");
  1172. fuel = context.TFuellist.FirstOrDefault(f => f.FuelNo == grayTrade.CommId);
  1173. if (fuel != null)
  1174. {
  1175. fuelProduct.FuelName = fuel.Name;
  1176. fuelProduct.Barcode = GetBarcode(Convert.ToInt32(fuel.FuelNo)).ToString();
  1177. fuelProduct.Price = grayTrade.Prc.Value;
  1178. }
  1179. }
  1180. }
  1181. //var result = SubmitCardTrxRecordAsync(trans, fuelProduct).Result;
  1182. var result = await SubmitCardTrxRecordAsync(trans, grayTrade, fuelProduct);
  1183. logger.Info($"Force submit a new card payment record for " +
  1184. $"CardNo {trans.CardNo}, TTCTime: {trans.Ttctime}, GID: {trans.Gid}, Success? {result.Success}");
  1185. if (result.Success)
  1186. {
  1187. dbMonitor.AddToProcessedQueue(gid);
  1188. try
  1189. {
  1190. var currentTableAudit = await context.TTableaudit.FirstOrDefaultAsync(t => t.TransCreated == gid);
  1191. if (currentTableAudit != null)
  1192. {
  1193. var val = CleanupRecord(context, currentTableAudit);
  1194. logger.Info($"Cleaning up the Trx record from table, result: {val}");
  1195. }
  1196. dbMonitor.ClearFromQueue(gid);
  1197. }
  1198. catch (Exception ex)
  1199. {
  1200. logger.Error(ex);
  1201. }
  1202. }
  1203. else
  1204. {
  1205. dbMonitor.ClearFromQueue(gid);
  1206. logger.Warn($"Force upload result not success, should try again on New Card Transaction later, clear {gid} from queue");
  1207. }
  1208. }
  1209. else
  1210. {
  1211. logger.Info($"This won't look good, the record of GID: {gid} could not be found! Clear it!");
  1212. dbMonitor.ClearFromQueue(gid);
  1213. }
  1214. }
  1215. }
  1216. #endregion
  1217. private async Task<SendResult> SubmitAccountUpdate(TAcctinfo info)
  1218. {
  1219. var accountInfo = CreateAccountInfo(info);
  1220. var result = await dataCourier.SendRequest(new OfflineRequest { AccountInfo = accountInfo }, HostOperationType.UpdateAccount);
  1221. return result;
  1222. }
  1223. #region CreateAccountInfo - convert TAcctinfo to host account
  1224. private AccountInfo CreateAccountInfo(TAcctinfo info)
  1225. {
  1226. AccountInfo accountInfo = new AccountInfo();
  1227. accountInfo.Gid = Convert.ToInt64(info.Gid);
  1228. accountInfo.SNo = Convert.ToInt16(info.Sno);
  1229. accountInfo.AcctDate =
  1230. info.AcctDate.HasValue ? info.AcctDate.Value.ToString("yyyy-MM-dd HH:mm:ss") /*.Replace(' ', 'T')*/ : "0001-01-01";
  1231. accountInfo.AcctId = info.AcctId;
  1232. accountInfo.AcctSNo = Convert.ToInt16(info.AcctSno);
  1233. accountInfo.AcctState = Convert.ToByte(info.AcctState);
  1234. accountInfo.AcctType = Convert.ToByte(info.AcctType);
  1235. accountInfo.Address = info.Address;
  1236. accountInfo.Amount = Convert.ToInt64(info.Amount);
  1237. accountInfo.BelongTo = info.BelongTo;
  1238. accountInfo.CertfType = info.CertfType;
  1239. accountInfo.CertfNo = info.CertfNo;
  1240. accountInfo.EnableSms = Convert.ToByte(info.EnableSms);
  1241. accountInfo.FuelNo = info.FuelNo;
  1242. accountInfo.Gift = Convert.ToInt32(info.Gift);
  1243. accountInfo.PhoneNo = info.PhoneNo;
  1244. accountInfo.RechgTotal = Convert.ToInt64(info.RechgTotal);
  1245. accountInfo.TMac = Convert.ToInt64(info.Tmac);
  1246. accountInfo.UploadFlag = Convert.ToByte(info.UploadFlag);
  1247. accountInfo.WaitMalloc = info.Waitmalloc.Value > int.MaxValue ? 0 : Convert.ToUInt32(info.Waitmalloc);
  1248. return accountInfo;
  1249. }
  1250. #endregion
  1251. #region SUBMIT newly created Card Transaction
  1252. private async Task<SendResult> SubmitCardTrxRecordAsync(TTrdinfo trx, TTrdinfo grayTrd, FuelProductInfo fuel = null)
  1253. {
  1254. OfflineTransactionInfo transInfo = new OfflineTransactionInfo();
  1255. transInfo.Gid = Convert.ToInt64(trx.Gid);
  1256. transInfo.SNo = Convert.ToInt16(trx.Sno);
  1257. transInfo.ShiftNo = Convert.ToInt32(trx.ShiftNo);
  1258. transInfo.PosId = Convert.ToByte(trx.Posid);
  1259. transInfo.PumpType = Convert.ToByte(trx.PumpType);
  1260. transInfo.Operator = trx.Operator;
  1261. transInfo.CardNo = trx.CardNo;
  1262. transInfo.OperCardNo = trx.OperCardNo;
  1263. transInfo.PayModeId = trx.PaymodeId.HasValue ? (byte)trx.PaymodeId.Value : Convert.ToByte(0);
  1264. transInfo.PayModeNo = trx.PaymodeNo;
  1265. transInfo.TrdType = trx.TrdType;
  1266. transInfo.CommId = trx.CommId;
  1267. transInfo.Barcode = fuel == null ? "" : fuel.Barcode;
  1268. transInfo.FuelName = fuel == null ? "" : fuel.FuelName;
  1269. transInfo.Prc = trx.Prc == 0 ? Convert.ToInt32(fuel.Price) : Convert.ToInt32(trx.Prc);
  1270. transInfo.Vol = Convert.ToInt32(trx.Vol);
  1271. transInfo.Mon = Convert.ToInt32(trx.Mon);
  1272. transInfo.RealMon = Convert.ToInt32(trx.RealMon);
  1273. transInfo.CardBal = Convert.ToInt32(trx.CardBal);
  1274. transInfo.CardType = Convert.ToByte(trx.CardType);
  1275. transInfo.CTC = Convert.ToInt32(trx.Ctc);
  1276. transInfo.TTCTime =
  1277. trx.Ttctime.ToString("yyyy-MM-dd HH:mm:ss") /*.Replace(' ', 'T')*/;
  1278. transInfo.TTCTimeEnd =
  1279. trx.TtctimeEnd.HasValue ? trx.TtctimeEnd.Value.ToString("yyyy-MM-dd HH:mm:ss") /*.Replace(' ', 'T')*/ : "0001-01-01 00:00:00";
  1280. if (transInfo.Mon == 0 && transInfo.RealMon == 0)
  1281. {
  1282. if (grayTrd != null)
  1283. {
  1284. transInfo.CardBal += Convert.ToInt32(grayTrd.Mon - grayTrd.RealMon);
  1285. transInfo.TTCTimeEnd = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
  1286. }
  1287. }
  1288. transInfo.TTC = Convert.ToInt32(trx.Ttc);
  1289. transInfo.SeqNo = Convert.ToInt32(trx.SeqNo);
  1290. transInfo.BillNo = Convert.ToInt32(trx.BillNo);
  1291. transInfo.NozNo = Convert.ToByte(trx.NozNo);
  1292. transInfo.PumpNo = trx.PumpNo;
  1293. transInfo.PayTermId = Convert.ToInt32(trx.PayTemId);
  1294. transInfo.EndPump = Convert.ToInt64(trx.EndPumpId);
  1295. transInfo.DiscountNo = Convert.ToInt32(trx.DiscountNo);
  1296. transInfo.PsamAsn = trx.Psamasn;
  1297. transInfo.PsamTac = Convert.ToInt64(trx.Psamtac);
  1298. transInfo.PsamTid = trx.Psamtid;
  1299. transInfo.PsamTTC = Convert.ToInt32(trx.Psamttc);
  1300. transInfo.Tac = Convert.ToInt64(trx.Tac);
  1301. transInfo.GMac = Convert.ToInt64(trx.Gmac);
  1302. transInfo.Integral = Convert.ToInt32(trx.Integral);
  1303. transInfo.UploadFlag = Convert.ToByte(trx.UploadFlag);
  1304. transInfo.CarId = trx.CarId;
  1305. transInfo.CarLicsNo = trx.CarLicsNo;
  1306. transInfo.LineNo = trx.LineNo;
  1307. transInfo.BillType = Convert.ToByte(trx.BillType);
  1308. transInfo.BillFlag = Convert.ToByte(trx.BillFlag);
  1309. var result = await
  1310. dataCourier.SendRequest(new OfflineRequest { OfflineTrxInfo = transInfo }, HostOperationType.CreatePayRecord);
  1311. return result;
  1312. }
  1313. private async Task<SendResult> SubmitCardTrxRecordAsync(TCardtrx trx)
  1314. {
  1315. OfflineTransactionInfo transInfo = new OfflineTransactionInfo();
  1316. transInfo.Gid = Convert.ToInt64(trx.Gid);
  1317. transInfo.SNo = Convert.ToInt16(trx.Sno);
  1318. transInfo.ShiftNo = Convert.ToInt32(trx.ShiftNo);
  1319. transInfo.PosId = Convert.ToByte(trx.Posid);
  1320. transInfo.PumpType = Convert.ToByte(trx.PumpType);
  1321. transInfo.Operator = trx.Operator;
  1322. transInfo.CardNo = trx.CardNo;
  1323. trx.PaymodeId = trx.PaymodeId;
  1324. trx.PaymodeNo = trx.PaymodeNo;
  1325. trx.TrdType = trx.TrdType;
  1326. transInfo.CommId = trx.CommId;
  1327. transInfo.Prc = Convert.ToInt32(trx.Prc);
  1328. transInfo.Vol = Convert.ToInt32(trx.Vol);
  1329. transInfo.Mon = Convert.ToInt32(trx.Mon);
  1330. transInfo.RealMon = Convert.ToInt32(trx.RealMon);
  1331. transInfo.CardBal = Convert.ToInt32(trx.CardBal);
  1332. transInfo.CardType = Convert.ToByte(trx.CardType);
  1333. transInfo.CTC = Convert.ToInt32(trx.Ctc);
  1334. transInfo.TTCTime =
  1335. trx.Ttctime.ToString("yyyy-MM-dd HH:mm:ss") /*.Replace(' ', 'T')*/;
  1336. transInfo.TTCTimeEnd =
  1337. trx.TtctimeEnd.HasValue ? trx.TtctimeEnd.Value.ToString("yyyy-MM-dd HH:mm:ss") /*.Replace(' ', 'T')*/ : "0001-01-01 00:00:00";
  1338. transInfo.TTC = Convert.ToInt32(trx.Ttc);
  1339. transInfo.SeqNo = Convert.ToInt32(trx.SeqNo);
  1340. transInfo.BillNo = Convert.ToInt32(trx.BillNo);
  1341. transInfo.NozNo = Convert.ToByte(trx.NozNo);
  1342. transInfo.PumpNo = trx.PumpNo;
  1343. transInfo.PayTermId = Convert.ToInt32(trx.PayTemId);
  1344. transInfo.EndPump = Convert.ToInt64(trx.EndPumpId);
  1345. transInfo.DiscountNo = Convert.ToInt32(trx.DiscountNo);
  1346. transInfo.PsamAsn = trx.Psamasn;
  1347. transInfo.PsamTac = Convert.ToInt64(trx.Psamtac);
  1348. transInfo.PsamTid = trx.Psamtid;
  1349. transInfo.PsamTTC = Convert.ToInt32(trx.Psamttc);
  1350. transInfo.Tac = Convert.ToInt64(trx.Tac);
  1351. transInfo.GMac = Convert.ToInt64(trx.Gmac);
  1352. transInfo.Integral = Convert.ToInt32(trx.Integral);
  1353. transInfo.UploadFlag = Convert.ToByte(trx.UploadFlag);
  1354. transInfo.CarId = trx.CarId;
  1355. transInfo.CarLicsNo = trx.CarLicsNo;
  1356. transInfo.LineNo = trx.LineNo;
  1357. transInfo.BillType = Convert.ToByte(trx.BillType);
  1358. transInfo.BillFlag = Convert.ToByte(trx.BillFlag);
  1359. var result = await
  1360. dataCourier.SendRequest(new OfflineRequest { OfflineTrxInfo = transInfo }, HostOperationType.CreatePayRecord);
  1361. return result;
  1362. }
  1363. #endregion
  1364. #region Single and multiple accounts
  1365. private async Task<SendResult> SubmitAccountRecordAsync(TAcctinfo info, HostOperationType operationType)
  1366. {
  1367. var accountInfo = CreateAccountInfo(info);
  1368. var result = await dataCourier.SendRequest(new OfflineRequest { AccountInfo = accountInfo }, operationType);
  1369. return result;
  1370. }
  1371. private async Task<SendResult> SubmitMultipleAccountRecordsAsync(IEnumerable<TAcctinfo> accountRecords, HostOperationType operationType)
  1372. {
  1373. List<AccountInfo> accountList = new List<AccountInfo>();
  1374. foreach (var item in accountRecords)
  1375. {
  1376. var acct = CreateAccountInfo(item);
  1377. accountList.Add(acct);
  1378. }
  1379. var result = await dataCourier.SendRequest(new OfflineRequest { AccountInfoList = accountList }, operationType);
  1380. return result;
  1381. }
  1382. #endregion
  1383. #region Single and multiple card info
  1384. private async Task<SendResult> SubmitCardInfoAsync(TCardinfo info, HostOperationType operationType)
  1385. {
  1386. var cardInfo = ConvertDbCardInfoToHostCardInfo(info);
  1387. var result = await dataCourier.SendRequest(new OfflineRequest { CardInfo = cardInfo }, operationType);
  1388. return result;
  1389. }
  1390. private async Task<SendResult> SubmitMultipleCardInfoAsync(IEnumerable<TCardinfo> cardInfoRecords, HostOperationType operationType)
  1391. {
  1392. var cardInfoList = new List<CardInfo>();
  1393. foreach (var item in cardInfoRecords)
  1394. {
  1395. var cardInfo = ConvertDbCardInfoToHostCardInfo(item);
  1396. cardInfoList.Add(cardInfo);
  1397. }
  1398. var result = await dataCourier.SendRequest(new OfflineRequest { CardInfoList = cardInfoList }, operationType);
  1399. return result;
  1400. }
  1401. #endregion
  1402. #region Convert db cardinfo to host cardinfo
  1403. private CardInfo ConvertDbCardInfoToHostCardInfo(TCardinfo info)
  1404. {
  1405. CardInfo cardInfo = new CardInfo();
  1406. cardInfo.Gid = Convert.ToInt64(info.Gid);
  1407. cardInfo.AcctId = info.AcctId;
  1408. cardInfo.BLimitCar = Convert.ToByte(info.BLimitCar);
  1409. cardInfo.BLmtGood = info.BLmtGood.HasValue ? Convert.ToBoolean(info.BLmtGood.Value) : false; //0=No restriction, 1=Restricted.
  1410. cardInfo.CStatus = Convert.ToByte(info.CStatus);
  1411. cardInfo.CardClass = Convert.ToByte(info.CardClass);
  1412. cardInfo.CardId = Convert.ToInt64(info.CardId);
  1413. cardInfo.CardNo = info.CardNo;
  1414. cardInfo.CardSNo = Convert.ToInt16(info.CardSno);
  1415. cardInfo.CardType = Convert.ToByte(info.CardType);
  1416. cardInfo.CarNo = info.Carno;
  1417. cardInfo.CTC = Convert.ToInt32(info.Ctc);
  1418. cardInfo.CtcFlag = Convert.ToByte(info.Ctcflag);
  1419. cardInfo.CtcTime = info.Ctctime;
  1420. cardInfo.DiscountNo = Convert.ToInt32(info.DiscountNo);
  1421. cardInfo.DMaxPay = Convert.ToInt32(info.DmaxPay);
  1422. cardInfo.EnableSms = Convert.ToByte(info.EnableSms);
  1423. cardInfo.Holder = info.Holder;
  1424. cardInfo.IntegralTotal = Convert.ToInt32(info.IntegralTotal);
  1425. cardInfo.KcDate =
  1426. info.KcDate.HasValue ? info.KcDate.Value.ToString("yyyy-MM-dd HH:mm:ss") /*.Replace(' ', 'T')*/ : "0001-01-01 00:00:00";
  1427. cardInfo.LimitTimes = Convert.ToByte(info.LimitTimes);
  1428. cardInfo.LmtOil = info.LmtOil;
  1429. cardInfo.MMaxPay = Convert.ToInt32(info.MmaxPay);
  1430. cardInfo.Money = Convert.ToInt32(info.Money);
  1431. cardInfo.OnceMaxPay = Convert.ToInt32(info.OnceMaxPay);
  1432. cardInfo.OperNo = info.OperNo;
  1433. cardInfo.OverDate =
  1434. info.OverDate.HasValue ? info.OverDate.Value.ToString("yyyy-MM-dd HH:mm:ss") /*.Replace(' ', 'T')*/ : "9999-12-12 00:00:00";
  1435. cardInfo.PhoneNo = info.PhoneNo;
  1436. cardInfo.Pre_Malloc = Convert.ToInt32(info.PreMalloc);
  1437. cardInfo.RechgTotal = Convert.ToUInt64(info.RechgTotal);
  1438. cardInfo.SNo = Convert.ToInt16(info.Sno);
  1439. cardInfo.StartDate =
  1440. info.Startdate.HasValue ? info.Startdate.Value.ToString("yyyy-MM-dd HH:mm:ss") /*.Replace(' ', 'T')*/ : "0001-01-01 00:00:00";
  1441. cardInfo.TMac = Convert.ToInt64(info.Tmac);
  1442. cardInfo.UploadFlag = Convert.ToByte(info.UploadFlag);
  1443. cardInfo.UserNo = info.UserNo;
  1444. cardInfo.UserPin = info.UserPin;
  1445. return cardInfo;
  1446. }
  1447. #endregion
  1448. #region submit recharge/debit record
  1449. private async Task<SendResult> SubmitRechargeReductionRecord(TRechdebitRep rep)
  1450. {
  1451. RechargeDebitInfo rdInfo = new RechargeDebitInfo();
  1452. rdInfo.AcctId = rep.AcctId;
  1453. rdInfo.Bal = Convert.ToInt32(rep.Bal);
  1454. rdInfo.BillFlag = Convert.ToByte(rep.BillFlag);
  1455. rdInfo.BillType = Convert.ToByte(rep.BillType);
  1456. rdInfo.CardNo = rep.CardNo;
  1457. rdInfo.CTC = Convert.ToInt32(rep.Ctc);
  1458. rdInfo.DisIntegral = Convert.ToInt32(rep.DisIntegral);
  1459. rdInfo.DisMoney = Convert.ToInt32(rep.DisMoney);
  1460. rdInfo.DiscountNo = Convert.ToInt32(rep.DiscountNo);
  1461. rdInfo.Gid = Convert.ToInt64(rep.Gid);
  1462. rdInfo.Mon = Convert.ToInt32(rep.Mon);
  1463. rdInfo.OperNo = rep.OperNo;
  1464. rdInfo.RechgType = Convert.ToByte(rep.RechgType);
  1465. rdInfo.SNo = Convert.ToInt16(rep.Sno);
  1466. rdInfo.TMac = Convert.ToInt64(rep.Tmac);
  1467. rdInfo.TrdType = Convert.ToByte(rep.TrdType);
  1468. rdInfo.TTC = Convert.ToInt32(rep.Ttc);
  1469. rdInfo.TTCTime =
  1470. rep.Ttctime.HasValue ? rep.Ttctime.Value.ToString("yyyy-MM-dd HH:mm:ss") /*.Replace(' ', 'T')*/ : "0001-01-01 00:00:00";
  1471. rdInfo.UploadFlag = Convert.ToByte(rep.UploadFlag);
  1472. var result = await dataCourier.SendRequest(new OfflineRequest { RechargeDebitInfo = rdInfo }, HostOperationType.CreateRechargeRecord);
  1473. return result;
  1474. }
  1475. #endregion
  1476. #region Card Operation
  1477. private async Task<SendResult> SubmitCardOperationInfoAsync(TCardreploss rl, string cardNo)
  1478. {
  1479. CardOperationInfo info = new CardOperationInfo();
  1480. if (rl != null)
  1481. {
  1482. info.CardNo = rl.CardNo;
  1483. info.AccountId = "";
  1484. info.TimeStamp = rl.LossTime.Value.ToString("yyyy-MM-dd HH:mm:ss") /*.Replace(' ', 'T')*/;
  1485. info.OperationType = rl.OperType.Value;
  1486. }
  1487. else if (!string.IsNullOrEmpty(cardNo))
  1488. {
  1489. info.CardNo = cardNo;
  1490. info.AccountId = "";
  1491. info.TimeStamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") /*.Replace(' ', 'T')*/;
  1492. info.OperationType = 3;
  1493. }
  1494. var result = await dataCourier.SendRequest(new OfflineRequest { CardOperationInfo = info }, HostOperationType.CardOperation);
  1495. return result;
  1496. }
  1497. #endregion
  1498. private async Task<SendResult> SubmitCardRepLossAsync(TCardreploss rl)
  1499. {
  1500. ReportedLostCard cardRepLoss = new ReportedLostCard();
  1501. cardRepLoss.Gid = Convert.ToInt64(rl.Gid);
  1502. cardRepLoss.CardNo = rl.CardNo;
  1503. cardRepLoss.SNo = Convert.ToUInt16(rl.Sno);
  1504. cardRepLoss.LossTime = rl.LossTime.Value.ToString("yyyy-MM-dd HH:mm:ss");
  1505. cardRepLoss.OperType = rl.OperType.Value;
  1506. cardRepLoss.OperNo = rl.OperNo;
  1507. cardRepLoss.Reason = rl.Reason;
  1508. cardRepLoss.OperationType = 0; // 0=created.
  1509. OfflineRequest request = new OfflineRequest();
  1510. request.CardRepLossInfoList = new List<ReportedLostCard>();
  1511. request.CardRepLossInfoList.Add(cardRepLoss);
  1512. var result = await dataCourier.SendRequest(request, HostOperationType.CardRepLoss);
  1513. return result;
  1514. }
  1515. #region Blacklisted card / Unblocked card
  1516. private async Task<SendResult> SendListedCardAsync(ListedCardInfo listedCardInfo)
  1517. {
  1518. var offlineRequest = new OfflineRequest();
  1519. offlineRequest.BlackCardInfoList = new List<BlackCardInfo>();
  1520. var blackCard = new BlackCardInfo();
  1521. blackCard.Gid = listedCardInfo.Gid;
  1522. blackCard.CardNo = listedCardInfo.CardNo;
  1523. blackCard.AcctGid = listedCardInfo.AccountGid;
  1524. blackCard.AcctId = listedCardInfo.AccountId;
  1525. blackCard.CardType = listedCardInfo.CardType;
  1526. blackCard.DiscountNo = listedCardInfo.DiscountNo;
  1527. blackCard.Reason = listedCardInfo.Reason;
  1528. blackCard.UploadFlag = listedCardInfo.UploadFlag;
  1529. blackCard.BlackDate = listedCardInfo.ListedDate.ToString("yyyy-MM-dd HH:mm:ss");
  1530. blackCard.OperationType = listedCardInfo.OperationType; // record added, removed or updated
  1531. if (listedCardInfo.ListedType == ListedType.Base)
  1532. {
  1533. blackCard.BlackType = 0; //base black card
  1534. offlineRequest.BlackCardInfoList.Add(blackCard);
  1535. }
  1536. else if (listedCardInfo.ListedType == ListedType.Add)
  1537. {
  1538. blackCard.BlackType = 1; //AddBlackCard
  1539. offlineRequest.BlackCardInfoList.Add(blackCard);
  1540. }
  1541. else if (listedCardInfo.ListedType == ListedType.Deleted)
  1542. {
  1543. blackCard.BlackType = 2; //DeleteBlackCard
  1544. offlineRequest.BlackCardInfoList.Add(blackCard);
  1545. }
  1546. var result = await dataCourier.SendRequest(offlineRequest, HostOperationType.ListedCard);
  1547. return result;
  1548. }
  1549. #endregion
  1550. private void StartDbMonitor()
  1551. {
  1552. if (mre != null)
  1553. mre.WaitOne();
  1554. else
  1555. logger.Error("DbMonitor mre is null");
  1556. if (dbMonitor != null)
  1557. dbMonitor.Start();
  1558. else
  1559. logger.Error("DbMonitor instance is null");
  1560. }
  1561. private bool CheckTable()
  1562. {
  1563. using (var context = new SpsDbContext(_mySqlConn))
  1564. {
  1565. var conn = context.Database.GetDbConnection();
  1566. if (conn.State.Equals(ConnectionState.Closed))
  1567. {
  1568. conn.Open();
  1569. }
  1570. using (var command = conn.CreateCommand())
  1571. {
  1572. command.CommandText = @"SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't_tableaudit'";
  1573. var exists = Convert.ToInt32(command.ExecuteScalar()) != 0;
  1574. logger.Info($"The table t_tableaudit exists? {exists}");
  1575. return exists;
  1576. }
  1577. }
  1578. }
  1579. private bool UploadExistingData()
  1580. {
  1581. if (dataCourier != null)
  1582. dataCourier.GetToken();
  1583. else
  1584. logger.Error("DataCourier instance is null");
  1585. if (!CheckTable())
  1586. {
  1587. //mre.Set();
  1588. logger.Error("*** The table t_tableaudit does not exist! Consider initialize the table first!");
  1589. return true;
  1590. }
  1591. //Existing data already being uploaded.
  1592. if (System.IO.File.Exists("sps.txt"))
  1593. {
  1594. mre.Set();
  1595. logger.Info("Existing data already uploaded!");
  1596. return true;
  1597. }
  1598. var uploadAccount = UploadAccounts();
  1599. var uploadCardInfo = UploadCardInfo();
  1600. var uploadClosedCard = UploadClosedCards();
  1601. var uploadRechRedt = UploadRechargeReductionRecords();
  1602. var uploadCardTrx = UploadCardTransactions();
  1603. if (uploadAccount && uploadCardInfo && uploadCardTrx && uploadRechRedt)
  1604. {
  1605. logger.Info("All existing records are uploaded successfully, WOW!");
  1606. }
  1607. if (uploadClosedCard)
  1608. logger.Info("Uploaded all from t_cardlogout");
  1609. System.IO.File.Create("sps.txt");
  1610. mre.Set();
  1611. return true;
  1612. }
  1613. #region Process existing records
  1614. private IEnumerable<TAcctinfo> GetExistingAccounts()
  1615. {
  1616. using (var guardDbContext = new GuardDbContext())
  1617. using (var context = new SpsDbContext(_mySqlConn))
  1618. {
  1619. var account = context.TTableaudit.FirstOrDefault(t => t.AccountCreated.HasValue && t.AccountCreated.Value != 0);
  1620. if (account != null)
  1621. {
  1622. var existingAccounts = context.TAcctinfo.Where(t => t.Gid < Convert.ToUInt64(account.AccountCreated.Value)).AsEnumerable();
  1623. if (guardDbContext.AccountUpload.Any())
  1624. {
  1625. var maxGid = guardDbContext.AccountUpload.Max(a => a.Gid);
  1626. logger.Info($"Already uploaded some Account info, max existing Gid: {maxGid}");
  1627. return existingAccounts.Where(a => Convert.ToInt64(a.Gid) > maxGid).ToList();
  1628. }
  1629. logger.Info($"Existing account count: {existingAccounts.Count()}");
  1630. return existingAccounts.ToList();
  1631. }
  1632. else
  1633. {
  1634. logger.Info($"No new account created, get all the accounts from `t_acctinfo`");
  1635. return context.TAcctinfo.ToList();
  1636. }
  1637. }
  1638. }
  1639. private bool UploadAccounts()
  1640. {
  1641. var accounts = GetExistingAccounts();
  1642. if (accounts == null)
  1643. {
  1644. logger.Error("** No existing account identified, skip uploading");
  1645. return false;
  1646. }
  1647. logger.Info($"Existing account count: {accounts.Count()}");
  1648. using (var context = new GuardDbContext())
  1649. {
  1650. foreach (var account in accounts)
  1651. {
  1652. var result = SubmitAccountRecordAsync(account, HostOperationType.CreateAccount).Result;
  1653. context.Add(new AccountUpload
  1654. {
  1655. Gid = Convert.ToInt64(account.Gid),
  1656. AccountId = account.AcctId,
  1657. Operation = 1,
  1658. OperationTime = DateTime.Now,
  1659. Status = result.Success ? 0 : 1
  1660. });
  1661. context.SaveChanges();
  1662. }
  1663. var failedUploads = context.AccountUpload.Where(a => a.Status > 0);
  1664. if (failedUploads != null && failedUploads.Count() > 0)
  1665. {
  1666. logger.Info("Existing accounts uploaded with failures\n");
  1667. return false;
  1668. }
  1669. else
  1670. {
  1671. logger.Info("Existing accounts uploaded successfully\n");
  1672. return true;
  1673. }
  1674. }
  1675. }
  1676. private IEnumerable<TCardinfo> GetExistingCards()
  1677. {
  1678. using (var guardDbContext = new GuardDbContext())
  1679. using (var context = new SpsDbContext(_mySqlConn))
  1680. {
  1681. var cardInfo = context.TTableaudit.FirstOrDefault(t => t.CardInfoCreated.HasValue && t.CardInfoCreated.Value != 0);
  1682. if (cardInfo != null)
  1683. {
  1684. var cards = context.TCardinfo.Where(t => t.Gid < Convert.ToUInt64(cardInfo.CardInfoCreated.Value)).AsEnumerable();
  1685. if (guardDbContext.CardUpload.Any())
  1686. {
  1687. var maxGid = guardDbContext.CardUpload.Max(c => c.Gid);
  1688. logger.Info($"Already uploaded some Card info, max existing Gid: {maxGid}");
  1689. return cards.Where(c => Convert.ToInt64(c.Gid) > maxGid);
  1690. }
  1691. logger.Info($"Existing card info count: {cards.Count()}");
  1692. return cards.ToList();
  1693. }
  1694. else
  1695. {
  1696. logger.Info("No new card info, get all card info from table `t_cardinfo`");
  1697. return context.TCardinfo.ToList();
  1698. }
  1699. }
  1700. }
  1701. private bool UploadCardInfo()
  1702. {
  1703. var cards = GetExistingCards();
  1704. logger.Info($"Existing card count: {cards.Count()}");
  1705. using (var context = new GuardDbContext())
  1706. {
  1707. foreach (var card in cards)
  1708. {
  1709. var result = SubmitCardInfoAsync(card, HostOperationType.CreateCard).Result;
  1710. context.Add(new CardUpload
  1711. {
  1712. Gid = Convert.ToInt64(card.Gid),
  1713. CardNo = card.CardNo,
  1714. Operation = 1, //Insert
  1715. OperationTime = DateTime.Now,
  1716. Status = result.Success ? 0 : 1 //0 = OK, 1 = NOK
  1717. });
  1718. context.SaveChanges();
  1719. }
  1720. var failedUploads = context.CardUpload.Where(c => c.Status > 0);
  1721. if (failedUploads != null && failedUploads.Count() > 0)
  1722. {
  1723. logger.Info("Existing card uploaded with failures\n");
  1724. return false;
  1725. }
  1726. else
  1727. {
  1728. logger.Info("Existing card uploaded successfully\n");
  1729. return true;
  1730. }
  1731. }
  1732. }
  1733. private IEnumerable<TCardlogout> GetExistingClosedCards()
  1734. {
  1735. using (var context = new SpsDbContext(_mySqlConn))
  1736. {
  1737. logger.Info("Get all card info from table `t_cardlogout`");
  1738. return context.TCardlogout.ToList();
  1739. }
  1740. }
  1741. private bool UploadClosedCards()
  1742. {
  1743. var cards = GetExistingClosedCards();
  1744. logger.Info($"Existing closed card count: {cards.Count()}");
  1745. using (var context = new GuardDbContext())
  1746. {
  1747. foreach (var c in cards)
  1748. {
  1749. var card = ConvertClosedCardToCardInfo(c);
  1750. var result = SubmitCardInfoAsync(card, HostOperationType.CreateCard).Result;
  1751. context.Add(new CardUpload
  1752. {
  1753. Gid = Convert.ToInt64(card.Gid),
  1754. CardNo = card.CardNo,
  1755. Operation = 1, //Insert
  1756. OperationTime = DateTime.Now,
  1757. Status = result.Success ? 0 : 1 //0 = OK, 1 = NOK
  1758. });
  1759. context.SaveChanges();
  1760. }
  1761. var failedUploads = context.CardUpload.Where(c => c.Status > 0);
  1762. if (failedUploads != null && failedUploads.Count() > 0)
  1763. {
  1764. logger.Info("Existing cardlogout uploaded with failures\n");
  1765. return false;
  1766. }
  1767. else
  1768. {
  1769. logger.Info("Existing cardlogout uploaded successfully\n");
  1770. return true;
  1771. }
  1772. }
  1773. }
  1774. private TCardinfo ConvertClosedCardToCardInfo(TCardlogout closedCard)
  1775. {
  1776. var cardInfo = new TCardinfo();
  1777. cardInfo.AcctGid = closedCard.AcctGid;
  1778. cardInfo.AcctId = closedCard.AcctId;
  1779. cardInfo.CardNo = closedCard.CardNo;
  1780. cardInfo.CardId = closedCard.CardId.HasValue ? closedCard.CardId.Value : 0;
  1781. cardInfo.CardType = closedCard.CardType.HasValue? Convert.ToByte(closedCard.CardType.Value): (byte)1;
  1782. cardInfo.Holder = closedCard.Holder;
  1783. cardInfo.PhoneNo = closedCard.PhoneNo;
  1784. cardInfo.KcDate = closedCard.KcDate;
  1785. cardInfo.Startdate = closedCard.Startdate;
  1786. cardInfo.CStatus = 2; // 2 = 注销卡
  1787. return cardInfo;
  1788. }
  1789. private IEnumerable<TTrdinfo> GetExistingCardTrans()
  1790. {
  1791. using (var context = new SpsDbContext(_mySqlConn))
  1792. {
  1793. var trx = context.TTableaudit.FirstOrDefault(a => a.TransCreated.HasValue && a.TransCreated.Value != 0);
  1794. if (trx != null)
  1795. {
  1796. var transactions = context.TTrdinfo.Where(t => t.Gid < trx.Gid && t.Mon > 0);
  1797. logger.Info($"Existing card transactions count: {transactions.Count()}");
  1798. return transactions.ToList();
  1799. }
  1800. else
  1801. {
  1802. return context.TTrdinfo.ToList();
  1803. }
  1804. }
  1805. }
  1806. private bool UploadCardTransactions()
  1807. {
  1808. logger.Info("Start to get existing card transactions");
  1809. var transactions = GetExistingCardTrans();
  1810. logger.Info("Pulled all the existing card transactions from database");
  1811. using (var spsContext = new SpsDbContext(_mySqlConn))
  1812. using (var context = new GuardDbContext())
  1813. {
  1814. foreach (var trans in transactions)
  1815. {
  1816. FuelProductInfo fuelProduct = new FuelProductInfo();
  1817. var fuel = spsContext.TFuellist.FirstOrDefault(f => f.FuelNo == trans.CommId);
  1818. if (fuel != null)
  1819. {
  1820. fuelProduct.FuelName = fuel.Name;
  1821. fuelProduct.Barcode = GetBarcode(Convert.ToInt32(fuel.FuelNo)).ToString();
  1822. }
  1823. var result = SubmitCardTrxRecordAsync(trans, null, fuelProduct).Result;
  1824. context.TradeUpload.Add(new TradeUpload
  1825. {
  1826. Gid = Convert.ToInt64(trans.Gid),
  1827. Operation = 1,
  1828. OperationTime = DateTime.Now,
  1829. Status = result.Success ? 0 : 1
  1830. });
  1831. context.SaveChanges();
  1832. }
  1833. var failedUploads = context.TradeUpload.Where(c => c.Status > 0);
  1834. if (failedUploads != null && failedUploads.Count() > 0)
  1835. {
  1836. logger.Info("Existing card trx uploaded with failures\n");
  1837. return false;
  1838. }
  1839. else
  1840. {
  1841. logger.Info("Existing card trx uploaded successfully\n");
  1842. return true;
  1843. }
  1844. }
  1845. }
  1846. private IEnumerable<TRechdebitRep> GetExistingRechargeReductions()
  1847. {
  1848. using (var context = new SpsDbContext(_mySqlConn))
  1849. {
  1850. var record = context.TTableaudit.FirstOrDefault(t => t.RechargeCreated.HasValue && t.RechargeCreated.Value != 0);
  1851. if (record != null)
  1852. {
  1853. var records = context.TRechdebitRep.Where(r => r.Gid <= Convert.ToUInt64(record.RechargeCreated.Value)).AsEnumerable();
  1854. logger.Info($"Existing recharge reduction operations count: {records.Count()}");
  1855. return records.ToList();
  1856. }
  1857. else
  1858. {
  1859. logger.Info("No new recharge reduction records");
  1860. return context.TRechdebitRep.ToList();
  1861. }
  1862. }
  1863. }
  1864. private bool UploadRechargeReductionRecords()
  1865. {
  1866. var records = GetExistingRechargeReductions();
  1867. using (var context = new GuardDbContext())
  1868. {
  1869. foreach (var r in records)
  1870. {
  1871. var result = SubmitRechargeReductionRecord(r).Result;
  1872. context.RechargeUpload.Add(new RechargeUpload
  1873. {
  1874. Gid = Convert.ToInt64(r.Gid),
  1875. AccountId = r.AcctId,
  1876. CardNo = r.CardNo,
  1877. Operation = 1,
  1878. OperationTime = DateTime.Now,
  1879. Status = result.Success ? 0 : 1
  1880. });
  1881. context.SaveChanges();
  1882. }
  1883. var failedUploads = context.RechargeUpload.Where(r => r.Status > 0);
  1884. if (failedUploads != null && failedUploads.Count() > 0)
  1885. {
  1886. logger.Info("Existing recharge/reductions uploaded with failures\n");
  1887. return false;
  1888. }
  1889. else
  1890. {
  1891. logger.Info("Existing recharge/reductions uploaded successfully\n");
  1892. return true;
  1893. }
  1894. }
  1895. }
  1896. #endregion
  1897. private void HandleMissingCard(SpsDbContext spsDbContext, string cardNo)
  1898. {
  1899. if (!string.IsNullOrEmpty(cardNo))
  1900. {
  1901. var missingCard = spsDbContext.TCardinfo.FirstOrDefault(c => c.CardNo == cardNo);
  1902. if (missingCard != null)
  1903. {
  1904. var result = SubmitCardInfoAsync(missingCard, HostOperationType.CreateCard).Result;
  1905. logger.Info($"Submit required CardInfo for CardNo: {missingCard.CardNo}, GID: {missingCard.Gid}, Success? {result.Success}");
  1906. if (result.Code == 4)
  1907. {
  1908. HandleMissingAccount(spsDbContext, missingCard.AcctId);
  1909. }
  1910. }
  1911. }
  1912. }
  1913. private void HandleMissingAccount(SpsDbContext spsDbContext, string accountId)
  1914. {
  1915. if (!string.IsNullOrEmpty(accountId))
  1916. {
  1917. var missingAccount = spsDbContext.TAcctinfo.FirstOrDefault(a => a.AcctId == accountId);
  1918. if (missingAccount != null)
  1919. {
  1920. var result = SubmitAccountRecordAsync(missingAccount, HostOperationType.CreateAccount).Result;
  1921. logger.Info($"Submit required AccountInfo for AccoutId: {missingAccount.AcctId}, " +
  1922. $"GID: {missingAccount.Gid}, Success? {result.Success}");
  1923. }
  1924. }
  1925. }
  1926. }
  1927. #region Config parameters
  1928. public class DataCourierAppContructorParameterV1
  1929. {
  1930. public int Id { get; set; }
  1931. public string Username { get; set; }
  1932. public string Password { get; set; }
  1933. public string AuthServiceBaseUrl { get; set; }
  1934. public string AccountServiceBaseUrl { get; set; }
  1935. public string AccountServiceRelativeUrl { get; set; }
  1936. public string DeviceSN { get; set; }
  1937. public int ScanInterval { get; set; }
  1938. public List<FuelMappingV1> FuelMappingArr { get; set; }
  1939. public int RetryCount { get; set; }
  1940. public bool EnableSync { get; set; }
  1941. public bool ExcludeCurrentSite { get; set; }
  1942. public int SyncInterval { get; set; }
  1943. public string CheckVersionRelativeUrl { get; set; }
  1944. public string SyncDataRelativeUrl { get; set; }
  1945. public SpsDbConnectionSetting ConnectionString { get; set; }
  1946. }
  1947. public class FuelMappingV1
  1948. {
  1949. public int Barcode { get; set; }
  1950. public string FuelNo { get; set; }
  1951. }
  1952. public class SpsDbConnectionSetting
  1953. {
  1954. public string Server { get; set; }
  1955. public int Port { get; set; }
  1956. public string Username { get; set; }
  1957. public string Password { get; set; }
  1958. }
  1959. #endregion
  1960. }