using Newtonsoft.Json;
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using System.Linq;
using Dfs.WayneChina.SpsDataCourier.HostModels;
using Dfs.WayneChina.SpsDataCourier.Guard;
using System.Collections.Generic;
using Dfs.WayneChina.SpsDataCourier.SpsData;
using Microsoft.EntityFrameworkCore;
namespace Dfs.WayneChina.SpsDataCourier
{
public class Downloader
{
#region Fields
private Timer _timer;
private readonly int _interval;
private readonly ConnectionInfo _connectionInfo;
private HttpClient _client = new HttpClient();
private string grantType = "password";
private string tokenAuthPath = "token";
private string authScheme = "bearer";
private AuthToken currentAuthToken;
private string _spsDbConnString;
private long? localVersion = null;
private readonly DbMonitor _dbMonitor;
private readonly string _checkVersionRelativeUrl;
private readonly string _syncDataRelativeUrl;
private bool _excludeCurrentSite = false;
#endregion
#region Logger
static NLog.Logger logger = NLog.LogManager.LoadConfiguration("NLog.config").GetLogger("SpsDataCourier");
#endregion
#region Constructor
public Downloader(ConnectionInfo connectionInfo, DbMonitor dbMonitor, string spsConnString, int interval,
string versionRelativeUrl, string dataRelativeUrl, bool excludeCurrentSite)
{
_connectionInfo = connectionInfo;
_dbMonitor = dbMonitor;
_spsDbConnString = spsConnString;
_interval = interval;
_checkVersionRelativeUrl = versionRelativeUrl;
_syncDataRelativeUrl = dataRelativeUrl;
_excludeCurrentSite = excludeCurrentSite;
}
#endregion
#region Start
public void Start()
{
_timer = new Timer();
_timer.Interval = _interval * 1000;
_timer.Elapsed += DownloadTimerElapsed;
_timer.Start();
}
#endregion
#region Stop
public void Stop()
{
if (_timer != null)
{
_timer.Elapsed -= DownloadTimerElapsed;
_timer.Close();
}
}
#endregion
#region Timer elapsed event
///
/// 同步云端定时器
///
///
///
private async void DownloadTimerElapsed(object sender, ElapsedEventArgs e)
{
logger.Info("Downloader timer elapsed");
_timer.Stop();
//优先上传
var count = await CheckPendingUpload();
if (count > 0)
{
logger.Info($"There are {count} accounts or cards updated, wait for them to be uploaded first!");
_timer.Start();
return;
}
else
{
await CheckHostDataVersionAsync();
_timer.Start();
}
}
#endregion
#region Check pending account updates
private Task CheckPendingUpload()
{
using (var context = new SpsDbContext(_spsDbConnString))
{
var records = context.TTableaudit
.Where(e => e.AccountUpdated.HasValue && e.AccountUpdated.Value != 0 ||
e.CardInfoUpdated.HasValue && e.CardInfoUpdated.Value != 0)
.ToList();
logger.Info($"Before download, Accounts updated count: " +
$"{records.Count(r => r.AccountUpdated.HasValue && r.AccountUpdated.Value != 0)}");
logger.Info($"Before download, Cards updated count: " +
$"{records.Count(r => r.CardInfoUpdated.HasValue && r.CardInfoUpdated.Value != 0)}");
return Task.FromResult(records.Count);
}
}
#endregion
#region Check host data version
private async Task CheckHostDataVersionAsync()
{
if (currentAuthToken != null && currentAuthToken.IsTokenValid())
{
using (var context = new GuardDbContext())
{
var currentVersion = context.DataVersion
.OrderByDescending(v => v.LastUpdate).FirstOrDefault();
if (currentVersion != null)
{
localVersion = currentVersion.VersionNo;
logger.Info($"Setting local version to {localVersion}");
logger.Info($"Current local version: {currentVersion.VersionNo}");
await CheckVersionStartDownloadAsync(currentVersion.VersionNo);
}
else if(currentVersion == null)
{
logger.Info($"Local version does not exist!");
await CheckVersionStartDownloadAsync(0);
}
}
}
else
{
logger.Info("No valid token now, start to get it.");
await GetTokenAsync(_connectionInfo.UserName, _connectionInfo.Password, _connectionInfo.AuthServiceBaseUrl);
}
}
#endregion
#region Compare version and start download
private async Task CheckVersionStartDownloadAsync(long versionNo)
{
var hostVersionInfo = await GetDataVersionAsync(versionNo);
if (hostVersionInfo != null)
{
logger.Info($"Host data version: {hostVersionInfo.VersionNo}");
long innerDataVersion = 0;
if (hostVersionInfo.VersionNo != versionNo)
{
_dbMonitor.Stop(); // stop for a while
innerDataVersion = await DownloadDataAsync(versionNo);
logger.Info($"Inner data version: {innerDataVersion}");
}
if (innerDataVersion != 0)
{
logger.Info($"Inner data version: {innerDataVersion}, host data version: {hostVersionInfo.VersionNo}");
hostVersionInfo.VersionNo = innerDataVersion;
}
await SaveHostVersion(hostVersionInfo);
_dbMonitor.Start();
localVersion = hostVersionInfo.VersionNo;
}
}
///
/// 数据版本同步
///
///
///
private async Task GetDataVersionAsync(long versionNo)
{
string baseUrl = _connectionInfo.AccountServiceBaseUrl;
//string accountingUrl = _connectionInfo.AccountServiceRelativeUrl;
string versionUrl = string.Format(_checkVersionRelativeUrl + "?excludingCurrentBu={0}&versionNo={1}", _excludeCurrentSite, versionNo);
string url = string.Concat(baseUrl, versionUrl);
logger.Info($"Version url: {url}");
_client.DefaultRequestHeaders.Clear();
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(authScheme, currentAuthToken.AccessToken);
_client.DefaultRequestHeaders.Add("DeviceSN", _connectionInfo.DeviceSN);
try
{
var versionResult = await _client.GetAsync(url).ConfigureAwait(false);
if (versionResult.IsSuccessStatusCode)
{
HostVersionResult hostVersionResult = null;
await versionResult.Content.ReadAsStringAsync().ContinueWith(x =>
{
hostVersionResult = JsonConvert.DeserializeObject(x?.Result);
});
if (hostVersionResult != null && hostVersionResult.Result != null)
{
return hostVersionResult.Result;
}
}
else
{
logger.Warn($"Get host version, status code: {versionResult.StatusCode}");
var content = await versionResult.Content.ReadAsStringAsync();
versionResult.Content?.Dispose();
}
}
catch (Exception ex)
{
logger.Error(ex.ToString());
}
return null;
}
private async Task SaveHostVersion(HostVersionInfo hostVersionInfo)
{
try
{
using (var context = new GuardDbContext())
{
if (!context.DataVersion.Any(v => v.VersionNo == hostVersionInfo.VersionNo))
{
var version = new DataVersion();
version.VersionNo = hostVersionInfo.VersionNo;
version.CommitFlag = 1;
version.LastUpdate = DateTime.Now;
context.DataVersion.Add(version);
await context.SaveChangesAsync();
logger.Info($"Host version no: {hostVersionInfo.VersionNo}, saved into db");
}
}
}
catch (Exception ex)
{
logger.Error($"Exception in saving host version info: {ex.ToString()}");
}
}
#endregion
#region Download
private async Task DownloadDataAsync(long versionNo)
{
logger.Info("==============================");
logger.Info($"Start data synchronizing, from local version: {versionNo}");
string versionSyncRelativeUrl = string.Format(_syncDataRelativeUrl + "?versionNo={0}&excludingCurrentBu={1}", versionNo, _excludeCurrentSite);
var url = string.Concat(_connectionInfo.AuthServiceBaseUrl, versionSyncRelativeUrl);
_client.DefaultRequestHeaders.Clear();
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(authScheme, currentAuthToken.AccessToken);
_client.DefaultRequestHeaders.Add("DeviceSN", _connectionInfo.DeviceSN);
logger.Info($"sync data url: {url}");
try
{
var response = await _client.GetAsync(url).ConfigureAwait(false);
logger.Info($"Downloading finished, status code: {response.StatusCode}");
HostDataResponse hostDataResponse = null;
if (response.IsSuccessStatusCode)
{
await response.Content.ReadAsStringAsync().ContinueWith(x =>
{
logger.Info($"data response: {x?.Result}");
hostDataResponse = JsonConvert.DeserializeObject(x?.Result);
});
if (hostDataResponse != null && hostDataResponse.Result != null)
{
await SaveOfflineAccounts(hostDataResponse.Result.OfflineAccountInfoList, hostDataResponse.Result.VersionNo);
logger.Info($"Saved account info at: {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}, " +
$"total count: {hostDataResponse.Result.OfflineAccountInfoList?.Count}");
await SaveOfflineCardInfoList(hostDataResponse.Result.OfflineCardInfoList, hostDataResponse.Result.VersionNo);
logger.Info($"Saved card info at: {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}, " +
$"total count: {hostDataResponse.Result.OfflineCardInfoList?.Count}");
await SaveOfflineGrayInfoList(hostDataResponse.Result.OfflineGrayInfoList, hostDataResponse.Result.VersionNo);
logger.Info($"Saved gray info at: {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}, " +
$"total count: {hostDataResponse.Result.OfflineGrayInfoList?.Count}");
await SaveOfflineBlackCardInfoList(hostDataResponse.Result.OfflineBlackCardInfoList, hostDataResponse.Result.VersionNo);
logger.Info($"Saved black card info at: {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}, " +
$"total count: {hostDataResponse.Result.OfflineBlackCardInfoList?.Count}");
await SaveOfflineCardRepLossInfoList(hostDataResponse.Result.OfflineCardRepLossList,
hostDataResponse.Result.VersionNo);
logger.Info($"Saved CardRepLoss info at: {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}, " +
$"total count: {hostDataResponse.Result.OfflineCardRepLossList?.Count}");
var firstAccount = hostDataResponse?.Result?.OfflineAccountInfoList.FirstOrDefault();
var firstCard = hostDataResponse?.Result?.OfflineCardInfoList.FirstOrDefault();
var firstBlackCard = hostDataResponse?.Result?.OfflineBlackCardInfoList.FirstOrDefault();
var firstGrayInfo = hostDataResponse?.Result?.OfflineGrayInfoList.FirstOrDefault();
var firstCardRepLoss = hostDataResponse?.Result?.OfflineBlackCardInfoList.FirstOrDefault();
logger.Info($"size: {hostDataResponse?.Result?.Size}, first account: {firstAccount?.acctID}, " +
$"first card: {firstCard?.cardNo}, first black card: {firstBlackCard?.cardNo}," +
$"first gray info: {firstGrayInfo?.cardNo}, first cardRepLoss info: {firstCardRepLoss?.cardNo}");
return hostDataResponse.Result.VersionNo;
}
}
else
{
var content = await response.Content.ReadAsStringAsync();
response.Content?.Dispose();
}
}
catch (Exception ex)
{
logger.Error(ex.ToString());
}
return versionNo;
}
#endregion
#region Persist Offline AccountInfo
private async Task SaveOfflineAccounts(List offlineAccountInfoList, long versionNo)
{
var accounts = new List();
foreach (var accountInfo in offlineAccountInfoList)
{
var account = new Account();
account.Gid = Convert.ToUInt64(accountInfo.gid);
account.AccountSNo = accountInfo.acctSNo;
account.SNo = accountInfo.sno;
account.AccountId = accountInfo.acctID;
account.AccountName = accountInfo.belongTo;
account.Address = accountInfo.address;
account.PhoneNo = accountInfo.phoneNo;
account.AccountType = accountInfo.acctType;
account.Amount = Convert.ToInt32(accountInfo.amount);
account.AmountType = 0;
account.FuelNo = accountInfo.fuelNo;
account.Credit = accountInfo.gift;
account.State = accountInfo.acctState;
account.AccountDate = accountInfo.acctDate;
account.CertType = accountInfo.certfType;
account.CertNo = accountInfo.certfNo;
account.RechargeTotal = accountInfo.rechgTotal;
account.TMac = accountInfo.tmac;
account.WaitMalloc = accountInfo.waitMalloc;
account.EnableSms = accountInfo.enableSms;
account.UploadFlag = accountInfo.uploadFlag;
account.VersionNo = versionNo;
account.LastUpdate = DateTime.Now;
accounts.Add(account);
}
try
{
using (var context = new GuardDbContext())
{
context.Account.AddRange(accounts);
await context.SaveChangesAsync();
}
await SaveToSpsDbAcctInfo(accounts);
}
catch (Exception ex)
{
logger.Error(ex.ToString());
}
}
private async Task SaveToSpsDbAcctInfo(IEnumerable accounts)
{
var spsAccounts = ConvertToSpsAccounts(accounts);
using (var spsDbContext = new SpsDbContext(_spsDbConnString))
{
if (localVersion == null || localVersion.HasValue && localVersion.Value == 0)
{
spsDbContext.TAcctinfo.AddRange(spsAccounts);
await spsDbContext.SaveChangesAsync();
await CleanSyncCreatedAccounts(spsAccounts.Select(a => a.Gid).ToList());
}
else
{
logger.Info("Insert or update acct info...");
var acctIds = spsAccounts.Select(a => a.AcctId).ToList();
var matchedAccounts = spsDbContext.TAcctinfo
.AsEnumerable()
.Where(a => acctIds.Contains(a.AcctId))
.ToList();
var newAccounts = spsAccounts
.Except(matchedAccounts, new GenericComparer(a => a.AcctId))
.ToList();
var existingAccounts = spsAccounts
.Except(newAccounts, new GenericComparer(a => a.AcctId))
.ToList();
if (existingAccounts != null && existingAccounts.Count > 0)
{
existingAccounts.ForEach(a => logger.Info($" current batch, update, acct id: {a.AcctId}"));
foreach (var account in existingAccounts)
{
var acctinfo = matchedAccounts.FirstOrDefault(x => x.AcctId == account.AcctId);
account.Gid = acctinfo.Gid; //Gid is the key, could not be updated.
spsDbContext.Entry(acctinfo).CurrentValues.SetValues(account);
}
await spsDbContext.SaveChangesAsync();
await CleanSyncUpdatedAccounts(matchedAccounts.Select(a => a.Gid).ToList());
}
if (newAccounts != null && newAccounts.Count > 0)
{
newAccounts.ForEach(a => logger.Info($" current batch, insert, acct id: {a.AcctId}"));
spsDbContext.TAcctinfo.AddRange(newAccounts);
await spsDbContext.SaveChangesAsync();
await CleanSyncCreatedAccounts(newAccounts.Select(a => a.Gid).ToList());
}
}
foreach (var spsAccount in spsAccounts)
{
logger.Info($" acct id: {spsAccount.AcctId}, gid: {spsAccount.Gid}, recharge total: {spsAccount.RechgTotal}, balance: {spsAccount.Amount}");
}
}
}
private async Task CleanSyncCreatedAccounts(List accountGids)
{
using (var context = new SpsDbContext(_spsDbConnString))
{
var accountsGeneratedBySync = context.TTableaudit
.AsEnumerable()
.Where(a => accountGids.Contains(Convert.ToUInt64(a.AccountCreated))).ToList();
context.RemoveRange(accountsGeneratedBySync);
await context.SaveChangesAsync();
}
}
private async Task CleanSyncUpdatedAccounts(List accountGids)
{
using (var context = new SpsDbContext(_spsDbConnString))
{
var accountsUpdatedBySync = context.TTableaudit
.AsEnumerable()
.Where(a => accountGids.Contains(Convert.ToUInt64(a.AccountUpdated))).ToList();
context.RemoveRange(accountsUpdatedBySync);
await context.SaveChangesAsync();
}
}
private List ConvertToSpsAccounts(IEnumerable accounts)
{
var spsAccounts = new List();
foreach (var account in accounts)
{
var acctinfo = new TAcctinfo();
acctinfo.AcctSno = Convert.ToByte(account.SNo);
acctinfo.Sno = account.SNo;
acctinfo.AcctId = account.AccountId;
acctinfo.BelongTo = account.AccountName;
acctinfo.Address = account.Address;
acctinfo.PhoneNo = account.PhoneNo;
acctinfo.AcctType = account.AccountType;
acctinfo.Amount = account.Amount;
acctinfo.AmtType = account.AmountType;
acctinfo.FuelNo = account.FuelNo;
acctinfo.Gift = account.Credit;
acctinfo.AcctState = account.State;
acctinfo.AcctDate = account.AccountDate;
acctinfo.CertfType = account.CertType;
acctinfo.CertfNo = account.CertNo;
acctinfo.RechgTotal = account.RechargeTotal;
acctinfo.Tmac = account.TMac;
acctinfo.Waitmalloc = account.WaitMalloc;
acctinfo.EnableSms = account.EnableSms;
acctinfo.UploadFlag = account.UploadFlag;
spsAccounts.Add(acctinfo);
}
return spsAccounts;
}
#endregion
#region Persist Offline Card Info
private async Task SaveOfflineCardInfoList(List offlineCardInfoList, long versionNo)
{
var cards = new List();
foreach (var cardinfo in offlineCardInfoList)
{
var card = new Card();
card.Gid = Convert.ToUInt64(cardinfo.gid);
card.CardSNo = cardinfo.cardSNo;
card.SNo = cardinfo.sno;
card.CardId = cardinfo.cardID;
card.CardNo = cardinfo.cardNo;
card.CTC = cardinfo.ctc;
card.CTCTime = cardinfo.ctctime;
card.AccountGid = 0; // not available
card.AccountId = cardinfo.acctID;
card.UserNo = cardinfo.userNo;
card.Holder = cardinfo.holder;
card.PhoneNo = cardinfo.phoneNo;
card.DMaxPay = cardinfo.dmaxPay;
card.MMaxPay = cardinfo.mmaxPay;
card.YMaxPay = 0; // not available
card.OnceMaxPay = cardinfo.onceMaxPay;
card.LimitCar = cardinfo.bLimitCar;
card.CarNo = cardinfo.carno;
card.Status = cardinfo.cStatus;
card.UserPin = cardinfo.userPIN;
card.OverDate = cardinfo.overDate;
card.KcDate = cardinfo.kcDate;
card.LimitOil = cardinfo.lmtOil;
card.CardType = cardinfo.cardType;
card.AuthStr = ""; // not available
card.TempCheckStr = ""; // not available
card.DiscountNo = cardinfo.discountNo;
card.StartDate = cardinfo.startdate;
card.PreMalloc = cardinfo.pre_malloc;
card.Balance = cardinfo.money;
card.RechargeTotal = cardinfo.rechgTotal;
card.IntegralTotal = Convert.ToUInt32(cardinfo.integralTotal);
card.CardClass = cardinfo.cardClass;
card.TMac = cardinfo.tmac;
card.LimitTimes = cardinfo.limitTimes;
card.UploadFlag = cardinfo.uploadFlag;
card.CTCFlag = cardinfo.ctcflag;
card.EnableSms = cardinfo.enableSms;
card.VersionNo = versionNo;
card.LastUpdate = DateTime.Now;
cards.Add(card);
}
try
{
using (var context = new GuardDbContext())
{
context.Card.AddRange(cards);
await context.SaveChangesAsync();
}
await SaveToSpsDbCardInfo(cards);
}
catch (Exception ex)
{
logger.Error(ex.ToString());
}
}
private async Task SaveToSpsDbCardInfo(IEnumerable cards)
{
var spsCards = ConvertToSpsCards(cards);
using (var spsDbContext = new SpsDbContext(_spsDbConnString))
{
if (localVersion == null || localVersion.HasValue && localVersion.Value == 0)
{
var validCards = spsCards.Where(c => c.CStatus != 2);
spsDbContext.TCardinfo.AddRange(validCards);
await spsDbContext.SaveChangesAsync();
await CleanSyncCreatedCards(spsCards.Select(c => c.Gid).ToList());
}
else
{
logger.Info("Insert, update or remove card info...");
var cardInfoComparer = new GenericComparer(c => c.CardNo);
var validCards = spsCards
.Where(c => c.CStatus != 2)
.ToList();
var validCardNos = validCards
.Select(a => a.CardNo)
.ToList();
var closedCardNos = spsCards
.Where(c => c.CStatus == 2)
.Select(x => x.CardNo)
.ToList();
if (closedCardNos.Count > 0)
{
closedCardNos.ForEach(c => logger.Info("Closed/Deactivated card no: " + c));
var closedCards = spsDbContext.TCardinfo
.AsEnumerable()
.Where(c => closedCardNos.Contains(c.CardNo))
.ToList();
spsDbContext.RemoveRange(closedCards);
await spsDbContext.SaveChangesAsync();
await CleanSyncDeletedCards(closedCards.Select(c => c.CardNo).ToList());
}
// These are db records, not host records.
var matchedCards = spsDbContext.TCardinfo
.AsEnumerable()
.Where(c => validCardNos.Contains(c.CardNo))
.ToList();
var newCards = validCards
.Except(matchedCards, cardInfoComparer)
.ToList();
var existingCards = validCards
.Except(newCards, cardInfoComparer)
.ToList();
if (existingCards != null && existingCards.Count > 0)
{
existingCards.ForEach(c => logger.Info($" current batch, update, card no: {c.CardNo}, balance: {c.Money}, PreMalloc: {c.PreMalloc}"));
foreach (var card in existingCards)
{
var cardinfo = matchedCards.FirstOrDefault(x => x.CardNo == card.CardNo);
card.Gid = cardinfo.Gid; //Gid is the key, could not be updated.
spsDbContext.Entry(cardinfo).CurrentValues.SetValues(card);
}
await spsDbContext.SaveChangesAsync();
await CleanSyncUpdatedCards(matchedCards.Select(c => c.Gid).ToList());
}
if (newCards != null && newCards.Count > 0)
{
logger.Info($"new cards count, before : {newCards.Count}");
newCards.ForEach(c => logger.Info($" current batch, insert, card no: {c.CardNo}"));
//
// This is a very strange case, there are two records of card '11000120215000003172'
// one of them contains a blank space ' '.
//
var cardWithSpace = newCards.Where(c => c.CardNo.Contains(' '));
int cnt = cardWithSpace.Count();
logger.Info($"card no w space, count: {cnt}");
if (cardWithSpace.Count() > 0)
{
for (int i = 0; i < cnt; i++)
{
var result = newCards.Remove(cardWithSpace.ToArray()[i]);
logger.Info($"remove result: {result}");
}
}
logger.Info($"new cards count, after: {newCards.Count}");
var distinctNewCards = newCards.Distinct(cardInfoComparer);
logger.Info($"distinct new cards, count: {distinctNewCards.Count()}");
spsDbContext.TCardinfo.AddRange(distinctNewCards);
await spsDbContext.SaveChangesAsync();
await CleanSyncCreatedCards(distinctNewCards.Select(c => c.Gid).ToList());
}
}
foreach (var card in spsCards)
{
logger.Info($" card no: {card.CardNo}, gid: {card.Gid}, balance: {card.Money}");
}
}
}
private async Task CleanSyncCreatedCards(List cardGids)
{
using (var context = new SpsDbContext(_spsDbConnString))
{
var cardsGeneratedBySync = context
.TTableaudit
.AsEnumerable()
.Where(a => cardGids.Contains(Convert.ToUInt64(a.CardInfoCreated)))
.ToList();
context.RemoveRange(cardsGeneratedBySync);
await context.SaveChangesAsync();
}
}
private async Task CleanSyncUpdatedCards(List cardGids)
{
using (var context = new SpsDbContext(_spsDbConnString))
{
var cardsUpdatedBySync = context
.TTableaudit
.AsEnumerable()
.Where(a => cardGids.Contains(Convert.ToUInt64(a.CardInfoUpdated)))
.ToList();
foreach (var cardGid in cardsUpdatedBySync)
{
logger.Info($" gid for updated card (to be cleaned): {cardGid.CardInfoUpdated}, " +
$"created at: {cardGid.OperationTime.ToString("yyyy-MM-dd HH:mm:ss")}");
}
context.RemoveRange(cardsUpdatedBySync);
await context.SaveChangesAsync();
}
}
private async Task CleanSyncDeletedCards(List cardNos)
{
using (var context = new SpsDbContext(_spsDbConnString))
{
var cardsDeletedBySync = context.TTableaudit
.AsEnumerable()
.Where(a => cardNos.Contains(a.CardInfoDeleted)).ToList();
context.RemoveRange(cardsDeletedBySync);
await context.SaveChangesAsync();
}
}
private List ConvertToSpsCards(IEnumerable cards)
{
var spsCards = new List();
foreach (var card in cards)
{
var cardinfo = new TCardinfo();
cardinfo.CardSno = card.CardSNo;
cardinfo.Sno = card.SNo;
cardinfo.CardId = card.CardId;
cardinfo.CardNo = card.CardNo;
cardinfo.Ctc = card.CTC;
cardinfo.Ctctime = card.CTCTime;
cardinfo.AcctGid = card.AccountGid;
cardinfo.AcctId = card.AccountId;
cardinfo.UserNo = card.UserNo;
cardinfo.Holder = card.Holder;
cardinfo.PhoneNo = card.PhoneNo;
cardinfo.DmaxPay = card.DMaxPay;
cardinfo.MmaxPay = card.MMaxPay;
cardinfo.YmaxPay = card.YMaxPay;
cardinfo.OnceMaxPay = card.OnceMaxPay;
cardinfo.BLimitCar = card.LimitCar;
cardinfo.Carno = card.CarNo;
cardinfo.CStatus = card.Status;
cardinfo.UserPin = card.UserPin;
cardinfo.OverDate = card.OverDate;
cardinfo.KcDate = card.KcDate;
cardinfo.OperNo = string.IsNullOrEmpty(card.OperatorNo) ? "0" : card.OperatorNo;
cardinfo.BLmtGood = card.LimitGood;
cardinfo.LmtOil = card.LimitOil;
cardinfo.CardType = card.CardType;
cardinfo.AuthStr = card.AuthStr;
cardinfo.TmpChkStr = card.TempCheckStr;
cardinfo.DiscountNo = card.DiscountNo;
cardinfo.Startdate = card.StartDate;
cardinfo.PreMalloc = card.PreMalloc;
cardinfo.Money = card.Balance;
cardinfo.RechgTotal = card.RechargeTotal;
cardinfo.IntegralTotal = card.IntegralTotal;
cardinfo.CardClass = card.CardClass;
cardinfo.Tmac = card.TMac;
cardinfo.LimitTimes = card.LimitTimes;
cardinfo.UploadFlag = card.UploadFlag;
cardinfo.Ctcflag = Convert.ToInt32(card.CTCFlag);
cardinfo.EnableSms = card.EnableSms;
spsCards.Add(cardinfo);
}
return spsCards;
}
#endregion
#region Persist Offline Gray Info
private List ConvertToLocalGrayTrades(IEnumerable offlineGrayInfoList, long versionNo)
{
var grayTrades = new List();
foreach (var grayinfo in offlineGrayInfoList)
{
var grayTrade = new GrayTrade();
grayTrade.Gid = Convert.ToUInt64(grayinfo.gid);
grayTrade.SNo = grayinfo.sno;
grayTrade.PumpType = grayinfo.pumpType;
grayTrade.CardNo = grayinfo.cardNo;
grayTrade.PayModeId = grayinfo.paymodeID;
grayTrade.TrdType = grayinfo.trdType;
grayTrade.CommId = grayinfo.commID;
grayTrade.Price = grayinfo.prc;
grayTrade.Volume = grayinfo.vol;
grayTrade.Amount = grayinfo.mon;
grayTrade.PayAmount = grayinfo.realMON;
grayTrade.CardBalance = Convert.ToUInt32(grayinfo.cardBal);
grayTrade.CTC = grayinfo.ctc;
grayTrade.TtcTime = grayinfo.ttctime;
grayTrade.TtcTimeEnd = grayinfo.ttctimeEnd;
grayTrade.TTC = grayinfo.ttc;
grayTrade.SeqNo = grayinfo.seqNo;
grayTrade.NozzleNo = grayinfo.nozNo;
grayTrade.PumpNo = grayinfo.pumpNo;
grayTrade.PayTermId = grayinfo.payTemID;
grayTrade.VolumeTotalizer = Convert.ToUInt32(grayinfo.endPump);
grayTrade.DiscountNo = grayinfo.discountNo;
grayTrade.PsamAsn = grayinfo.psamasn;
grayTrade.PsamTac = grayinfo.psamtac;
grayTrade.PsamTid = grayinfo.psamtid;
grayTrade.PsamTtc = uint.Parse(grayinfo.psamttc);
grayTrade.Tac = grayinfo.tac;
grayTrade.GMac = grayinfo.gmac;
grayTrade.TMac = grayinfo.tmac;
grayTrade.UploadFlag = grayinfo.uploadFlag;
grayTrade.OperationType = grayinfo.operationType;
grayTrade.VersionNo = versionNo;
grayTrade.LastUpdate = DateTime.Now;
grayTrades.Add(grayTrade);
}
return grayTrades;
}
private async Task SaveOfflineGrayInfoList(IEnumerable offlineGrayInfoList, long versionNo)
{
var grayTrades = ConvertToLocalGrayTrades(offlineGrayInfoList, versionNo);
var groupList = grayTrades.GroupBy(x => new { x.CardNo, x.CTC, x.TtcTime },
(key, grp) => new
{
Key1 = key.CardNo,
Key2 = key.CTC,
Key3 = key.TtcTime,
Result = grp.ToList()
});
foreach (var grp in groupList)
{
logger.Info("----------------------------");
foreach (var item in grp.Result)
{
logger.Info($"card no: {item.CardNo}, ctc: {item.CTC}, ttc time: {item.TtcTime.ToString("yyyy-MM-dd HH:mm:ss")}, op typ: {item.OperationType}");
}
}
var validGrayTrades = new List();
foreach (var group in groupList)
{
if (group.Result.Count == 2)
{
if (group.Result[0].OperationType != group.Result[1].OperationType)
{
logger.Info($"{group.Key1}, {group.Key2}, {group.Key3}, Gray and Ungray, skip");
}
}
else
{
validGrayTrades.AddRange(group.Result);
}
}
foreach (var vgi in validGrayTrades)
{
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}");
}
try
{
using (var context = new GuardDbContext())
{
context.GrayTrade.AddRange(grayTrades);
await context.SaveChangesAsync();
}
await SaveToSpsGrayInfo(validGrayTrades);
}
catch (Exception ex)
{
logger.Error(ex.ToString());
}
}
private async Task SaveToSpsGrayInfo(IEnumerable grayTrades)
{
var toBeAddedSpsGrayInfos = ConvertToSpsGrayInfo(grayTrades.Where(t => t.OperationType == 0));
var toBeDeletedSpsGrayInfos = ConvertToSpsGrayInfo(grayTrades.Where(t => t.OperationType == 2));
var spsGrayInfos = ConvertToSpsGrayInfo(grayTrades);
using (var spsDbContext = new SpsDbContext(_spsDbConnString))
{
////// Handle the to be added ///////
if (toBeAddedSpsGrayInfos.Count > 0)
{
logger.Info($"To be added gray info, count: {toBeAddedSpsGrayInfos.Count}");
}
// find out existing gray info, do we need this check?
var matchedGrayInfos = spsDbContext.TGrayinfo
.AsEnumerable()
.Where(g => toBeAddedSpsGrayInfos.Where(gt => gt.CardNo == g.CardNo && gt.Ctc == g.Ctc && gt.Ttctime == g.Ttctime).Count() >= 1)
.ToList();
foreach (var item in matchedGrayInfos)
{
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")}");
}
// should insert them into sps db.
var newGrayInfos = toBeAddedSpsGrayInfos.Except(matchedGrayInfos,
new GenericComparer(g => string.Concat(g.CardNo, g.Ttc.ToString(), g.Ttctime.Value.ToString("yyyy-MM-dd HH:mm:ss"))));
logger.Info($"should insert new gray info, count: {newGrayInfos.Count()}");
spsDbContext.TGrayinfo.AddRange(newGrayInfos);
////// Handle the to be deleted ///////
if (toBeDeletedSpsGrayInfos.Count > 0)
{
logger.Info($"To be deleted gray info, count: {toBeDeletedSpsGrayInfos.Count}");
}
var matchedToBeRemovedGrayInfos = spsDbContext.TGrayinfo
.AsEnumerable()
.Where(g => toBeDeletedSpsGrayInfos.Where(gt => gt.CardNo == g.CardNo && gt.Ctc == g.Ctc && gt.Ttctime == g.Ttctime).Count() >= 1)
.ToList();
foreach (var item in matchedToBeRemovedGrayInfos)
{
logger.Info($"gray info matched to be deleted, card no: {item.CardNo}, ctc: {item.Ctc}, gid: {item.Gid}");
}
spsDbContext.TGrayinfo.RemoveRange(matchedToBeRemovedGrayInfos);
await spsDbContext.SaveChangesAsync();
foreach (var grayinfo in spsGrayInfos)
{
logger.Info($"gray info, card no: {grayinfo.CardNo}, gid: {grayinfo.Gid}");
}
await CleanSyncGrayInfo(newGrayInfos.Select(g => g.Gid).ToList());
await CleanSyncDeletedGrayInfo(matchedToBeRemovedGrayInfos.Select(g => g.CardNo).ToList());
}
}
private async Task CleanSyncGrayInfo(List grayInfoGids)
{
using (var context = new SpsDbContext(_spsDbConnString))
{
var grayInfosGeneratedBySync = context.TTableaudit
.AsEnumerable()
.Where(a => grayInfoGids.Contains(Convert.ToUInt64(a.GrayInfoCreated)))
.ToList();
context.RemoveRange(grayInfosGeneratedBySync);
await context.SaveChangesAsync();
}
}
private async Task CleanSyncDeletedGrayInfo(List grayInfoCardNos)
{
using (var context = new SpsDbContext(_spsDbConnString))
{
var grayInfosRemovedBySync = context.TTableaudit
.AsEnumerable()
.Where(a => grayInfoCardNos.Contains(a.GrayInfoDeleted))
.ToList();
context.RemoveRange(grayInfosRemovedBySync);
await context.SaveChangesAsync();
}
}
private List ConvertToSpsGrayInfo(IEnumerable grayTrades)
{
var spsGrayInfoList = new List();
foreach (var grayTrade in grayTrades)
{
var grayinfo = new TGrayinfo();
grayinfo.Sno = grayTrade.SNo;
grayinfo.PumpType = grayTrade.PumpType;
grayinfo.CardNo = grayTrade.CardNo;
grayinfo.PaymodeId = grayTrade.PayModeId;
grayinfo.TrdType = grayTrade.TrdType;
grayinfo.CommId = grayTrade.CommId;
grayinfo.Prc = grayTrade.Price;
grayinfo.Vol = grayTrade.Volume;
grayinfo.Mon = grayTrade.Amount;
grayinfo.RealMon = grayTrade.PayAmount;
grayinfo.CardBal = grayTrade.CardBalance;
grayinfo.Ctc = grayTrade.CTC;
grayinfo.Ttctime = grayTrade.TtcTime;
grayinfo.TtctimeEnd = grayTrade.TtcTimeEnd;
grayinfo.Ttc = grayTrade.TTC;
grayinfo.SeqNo = grayTrade.SeqNo;
grayinfo.NozNo = grayTrade.NozzleNo;
grayinfo.PumpNo = grayTrade.PumpNo;
grayinfo.PayTemId = grayTrade.PayTermId;
grayinfo.EndPumpId = grayTrade.VolumeTotalizer;
grayinfo.DiscountNo = grayTrade.DiscountNo;
grayinfo.Psamasn = grayTrade.PsamAsn;
grayinfo.Psamtac = grayTrade.PsamTac;
grayinfo.Psamtid = grayTrade.PsamTid;
grayinfo.Psamttc = grayTrade.PsamTtc;
grayinfo.Tac = grayTrade.Tac;
grayinfo.Gmac = grayTrade.GMac;
grayinfo.Tmac = grayTrade.TMac;
grayinfo.UploadFlag = grayTrade.UploadFlag;
spsGrayInfoList.Add(grayinfo);
}
return spsGrayInfoList;
}
#endregion
#region Persist Offline Black Card Info
private async Task SaveOfflineBlackCardInfoList(List offlineBlackCardInfoList, long versionNo)
{
////////// add black card
var offlineBaseBlackCardInfoList = offlineBlackCardInfoList.Where(c => c.blackType == 0).ToList();
var baseBlackCards = new List();
foreach (var baseBlackCardInfo in offlineBaseBlackCardInfoList)
{
var baseBlackCard = new BaseBlackCard();
baseBlackCard.Gid = Convert.ToUInt64(baseBlackCardInfo.gid);
baseBlackCard.CardNo = baseBlackCardInfo.cardNo;
baseBlackCard.DateTime = baseBlackCardInfo.blackDate;
baseBlackCard.AccountGid = Convert.ToUInt64(baseBlackCardInfo.acctGid);
baseBlackCard.AccountId = baseBlackCardInfo.acctId;
baseBlackCard.CardType = baseBlackCardInfo.cardType;
baseBlackCard.DiscountNo = baseBlackCardInfo.discountNo;
baseBlackCard.Reason = baseBlackCardInfo.reason;
baseBlackCard.UploadFlag = baseBlackCardInfo.uploadFlag;
baseBlackCard.OperationType = baseBlackCardInfo.operationType;
baseBlackCard.VersionNo = versionNo;
baseBlackCard.LastUpdate = DateTime.Now;
baseBlackCards.Add(baseBlackCard);
}
logger.Info($"base blackcard record, count: {baseBlackCards.Count}");
await SaveBaseBlackCards(baseBlackCards);
////////// add black card
var offlineAddBlackCardInfoList = offlineBlackCardInfoList
.Where(c => c.blackType == 1)
.ToList();
var addBlackCards = new List();
foreach (var addBlackCardInfo in offlineAddBlackCardInfoList)
{
var addBlackCard = new AddBlackCard();
addBlackCard.Gid = Convert.ToUInt64(addBlackCardInfo.gid);
addBlackCard.CardNo = addBlackCardInfo.cardNo;
addBlackCard.DateTime = addBlackCardInfo.blackDate;
addBlackCard.AccountGid = Convert.ToUInt64(addBlackCardInfo.acctGid);
addBlackCard.AccountId = addBlackCardInfo.acctId;
addBlackCard.CardType = addBlackCardInfo.cardType;
addBlackCard.DiscountNo = addBlackCardInfo.discountNo;
addBlackCard.Reason = addBlackCardInfo.reason;
addBlackCard.UploadFlag = addBlackCardInfo.uploadFlag;
addBlackCard.OperationType = addBlackCardInfo.operationType;
addBlackCard.VersionNo = versionNo;
addBlackCard.LastUpdate = DateTime.Now;
addBlackCards.Add(addBlackCard);
}
logger.Info($"addblackcard record, count: {addBlackCards.Count}");
await SaveAddBlackCards(addBlackCards);
////////// delete black card
var offlineDeleteBlackCardInfoList = offlineBlackCardInfoList
.Where(c => c.blackType == 2)
.ToList();
var deleteBlackCards = new List();
foreach (var deleteBlackCardInfo in offlineDeleteBlackCardInfoList)
{
var deleteBlackCard = new DeleteBlackCard();
deleteBlackCard.Gid = Convert.ToUInt64(deleteBlackCardInfo.gid);
deleteBlackCard.CardNo = deleteBlackCardInfo.cardNo;
deleteBlackCard.DateTime = deleteBlackCardInfo.blackDate;
deleteBlackCard.AccountGid = Convert.ToUInt64(deleteBlackCardInfo.acctGid);
deleteBlackCard.AccountId = deleteBlackCardInfo.acctId;
deleteBlackCard.CardType = deleteBlackCardInfo.cardType;
deleteBlackCard.DiscountNo = deleteBlackCardInfo.discountNo;
deleteBlackCard.Reason = deleteBlackCardInfo.reason;
deleteBlackCard.UploadFlag = deleteBlackCardInfo.uploadFlag;
deleteBlackCard.OperationType = deleteBlackCardInfo.operationType;
deleteBlackCard.VersionNo = versionNo;
deleteBlackCard.LastUpdate = DateTime.Now;
deleteBlackCards.Add(deleteBlackCard);
}
logger.Info($"deleteblackcard record, count: {deleteBlackCards.Count}");
await SaveDeleteBlackCards(deleteBlackCards);
}
#region Base BlackCard processing
private async Task SaveBaseBlackCards(List baseBlackCards)
{
try
{
using (var context = new GuardDbContext())
{
context.BaseBlackCard.AddRange(baseBlackCards);
await context.SaveChangesAsync();
}
await SaveToSpsBaseBlackCards(baseBlackCards);
}
catch (Exception ex)
{
logger.Error(ex.ToString());
}
}
private async Task SaveToSpsBaseBlackCards(IEnumerable baseBlackCards)
{
var comparer = new GenericComparer(c => c.CardNo);
var spsBaseBlackCards = ConvertToSpsBaseBlackCards(baseBlackCards);
var toBeAddedBaseBlackCards = ConvertToSpsBaseBlackCards(baseBlackCards.Where(c => c.OperationType == 0));
var toBeUpdatedBaseBlackCards = ConvertToSpsBaseBlackCards(baseBlackCards.Where(c => c.OperationType == 1));
var toBeRemovedBaseBlackCards = ConvertToSpsBaseBlackCards(baseBlackCards.Where(c => c.OperationType == 2));
if (toBeUpdatedBaseBlackCards.Count > 0)
logger.Warn($"Base black cards, there are records to be updated??? count: {toBeUpdatedBaseBlackCards.Count}");
try
{
using (var context = new SpsDbContext(_spsDbConnString))
{
// handle `to be added Base BlackCard records`
var existingToBeAdded = context.TBlackcard
.AsEnumerable()
.Where(bc => toBeAddedBaseBlackCards.Any(c => c.CardNo == bc.CardNo))
.ToList();
var pendingAdd = toBeAddedBaseBlackCards.Except(existingToBeAdded, comparer).ToList();
pendingAdd.ForEach(c => logger.Info($" bc, add, card no: {c.CardNo}"));
context.TBlackcard.AddRange(pendingAdd);
// handle `to be removed Base BlackCard records`
var matchedToBeRemoved = context.TBlackcard
.AsEnumerable()
.Where(bc => toBeRemovedBaseBlackCards.Any(c => c.CardNo == bc.CardNo))
.ToList();
matchedToBeRemoved.ForEach(c => logger.Info($" bc, del, card no: {c.CardNo}"));
context.TBlackcard.RemoveRange(matchedToBeRemoved);
await context.SaveChangesAsync();
await CleanSyncInsertedBaseBlackCards(pendingAdd.Select(a => a.Gid).ToList());
await CleanSyncRemovedBaseBlackCards(matchedToBeRemoved.Select(c => c.CardNo).ToList());
spsBaseBlackCards
.ForEach(c => logger.Info($"base blackcard, card no: {c.CardNo}, gid: {c.Gid}"));
}
}
catch (Exception ex)
{
logger.Error(ex.ToString());
}
}
private async Task CleanSyncInsertedBaseBlackCards(List baseBlackCardGids)
{
using (var context = new SpsDbContext(_spsDbConnString))
{
var baseBlackCardsGeneratedBySync = context.TTableaudit
.AsEnumerable()
.Where(a => baseBlackCardGids.Contains(Convert.ToUInt64(a.BaseBlackCardCreated)))
.ToList();
context.RemoveRange(baseBlackCardsGeneratedBySync);
await context.SaveChangesAsync();
}
}
private async Task CleanSyncRemovedBaseBlackCards(List baseBlackCardCardNos)
{
using (var context = new SpsDbContext(_spsDbConnString))
{
var baseBlackCardsDeletedBySync = context.TTableaudit
.AsEnumerable()
.Where(a => baseBlackCardCardNos.Contains(a.BaseBlackCardDeleted))
.ToList();
context.RemoveRange(baseBlackCardsDeletedBySync);
await context.SaveChangesAsync();
}
}
private List ConvertToSpsBaseBlackCards(IEnumerable baseBlackCards)
{
var spsBaseBlackCards = new List();
foreach (var baseBlackCard in baseBlackCards)
{
var baseblackcard = new TBlackcard();
baseblackcard.CardNo = baseBlackCard.CardNo;
baseblackcard.BlackDate = baseBlackCard.DateTime;
baseblackcard.AcctGid = baseBlackCard.AccountGid;
baseblackcard.AcctId = baseBlackCard.AccountId;
baseblackcard.CardType = baseBlackCard.CardType;
baseblackcard.DiscountNo = baseBlackCard.DiscountNo;
baseblackcard.Reason = baseBlackCard.Reason;
baseblackcard.UploadFlag = baseBlackCard.UploadFlag;
spsBaseBlackCards.Add(baseblackcard);
}
return spsBaseBlackCards;
}
#endregion
#region AddBlackCard processing
private async Task SaveAddBlackCards(List addBlackCards)
{
try
{
using (var context = new GuardDbContext())
{
context.AddBlackCard.AddRange(addBlackCards);
await context.SaveChangesAsync();
}
await SaveToSpsAddBlackCards(addBlackCards);
}
catch (Exception ex)
{
logger.Error(ex.ToString());
}
}
private async Task SaveToSpsAddBlackCards(IEnumerable addBlackCards)
{
var comparer = new GenericComparer(c => c.CardNo);
var toBeAddedAddBlackCards = ConvertToSpsAddBlackCards(addBlackCards.Where(c => c.OperationType == 0));
var toBeUpdatedAddBlackCards = ConvertToSpsAddBlackCards(addBlackCards.Where(c => c.OperationType == 1));
var toBeRemovedAddBlackCards = ConvertToSpsAddBlackCards(addBlackCards.Where(c => c.OperationType == 2));
var spsAddBlackCards = ConvertToSpsAddBlackCards(addBlackCards);
using (var spsDbContext = new SpsDbContext(_spsDbConnString))
{
// handle `to be added AddBlackCard records`
var matchedInToBeAdded = spsDbContext.TAddblackcard
.AsEnumerable()
.Where(abc => toBeAddedAddBlackCards.Where(c => c.CardNo == abc.CardNo).Count() >= 1)
.ToList();
var pendingAddedAddBlackCard = toBeAddedAddBlackCards.Except(matchedInToBeAdded, comparer).ToList();
pendingAddedAddBlackCard.ForEach(c => logger.Info($" abc, pending add, card no: {c.CardNo}"));
spsDbContext.TAddblackcard.AddRange(pendingAddedAddBlackCard);
// handle `to be updated AddBlackCard records`
var pendingUpdateAddBlackCard = toBeAddedAddBlackCards.Except(pendingAddedAddBlackCard, comparer).ToList();
pendingUpdateAddBlackCard.ForEach(c => logger.Info($" abc, pending upd within add, card no: {c.CardNo}"));
toBeUpdatedAddBlackCards.AddRange(pendingUpdateAddBlackCard);
var matchedToBeUpdated = spsDbContext.TAddblackcard
.AsEnumerable()
.Where(abc => toBeUpdatedAddBlackCards.Where(c => c.CardNo == abc.CardNo).Count() >= 1)
.ToList();
var candidatesToBeInserted = toBeUpdatedAddBlackCards
.Except(matchedToBeUpdated, comparer)
.ToList();
if (candidatesToBeInserted.Count > 0)
logger.Info($" abc, pending upd, some are new??? count: {candidatesToBeInserted.Count}");
var toBeUpdated = toBeUpdatedAddBlackCards
.Except(candidatesToBeInserted, comparer)
.ToList();
toBeUpdated.ForEach(c => logger.Info($" abc, pending upd, card no: {c.CardNo}"));
foreach (var card in toBeUpdated)
{
var match = matchedToBeUpdated.FirstOrDefault(c => c.CardNo == card.CardNo);
if (match != null)
{
card.Gid = match.Gid;
spsDbContext.Entry(match).CurrentValues.SetValues(card);
}
}
// handle `to be removed AddBalckCard records`
var matchedToBeRemoved = spsDbContext.TAddblackcard
.AsEnumerable()
.Where(abc => toBeRemovedAddBlackCards.Where(c => c.CardNo == abc.CardNo).Count() >= 1)
.ToList();
matchedToBeRemoved.ForEach(c => logger.Info($" abc, pending del, card no: {c.CardNo}"));
spsDbContext.TAddblackcard.RemoveRange(matchedToBeRemoved);
await spsDbContext.SaveChangesAsync();
await CleanSyncInsertedAddBlackCards(pendingAddedAddBlackCard.Select(a => a.Gid).ToList());
await CleanSyncUpdatedAddBlackCards(toBeUpdated.Select(c => c.Gid).ToList());
await CleanSyncDeletedAddBlackCards(matchedToBeRemoved.Select(c => c.CardNo).ToList());
spsAddBlackCards.ForEach(c =>
logger.Info($"addblackcard, card no: {c.CardNo}, gid: {c.Gid}"));
}
}
private async Task CleanSyncInsertedAddBlackCards(List addBlackCardGids)
{
using (var context = new SpsDbContext(_spsDbConnString))
{
var addBlackCardsGeneratedBySync = context.TTableaudit
.AsEnumerable()
.Where(a => addBlackCardGids.Contains(Convert.ToUInt64(a.BlacklistedCardCreated)))
.ToList();
context.RemoveRange(addBlackCardsGeneratedBySync);
await context.SaveChangesAsync();
}
}
private async Task CleanSyncUpdatedAddBlackCards(List addBlackCardGids)
{
using (var context = new SpsDbContext(_spsDbConnString))
{
var addBlackCardsUpdatedBySync = context.TTableaudit
.AsEnumerable()
.Where(a => addBlackCardGids.Contains(Convert.ToUInt64(a.BlacklistedCardUpdated)))
.ToList();
context.RemoveRange(addBlackCardsUpdatedBySync);
await context.SaveChangesAsync();
}
}
private async Task CleanSyncDeletedAddBlackCards(List addBlackCardCardNos)
{
using (var context = new SpsDbContext(_spsDbConnString))
{
var addBlackCardsDeletedBySync = context.TTableaudit
.AsEnumerable()
.Where(a => addBlackCardCardNos.Contains(a.BlacklistedCardDeleted))
.ToList();
context.RemoveRange(addBlackCardsDeletedBySync);
await context.SaveChangesAsync();
}
}
private List ConvertToSpsAddBlackCards(IEnumerable addBlackCards)
{
var spsAddBlackCards = new List();
foreach (var addBlackCard in addBlackCards)
{
var addblackcard = new TAddblackcard();
addblackcard.CardNo = addBlackCard.CardNo;
addblackcard.BlackDate = addBlackCard.DateTime;
addblackcard.AcctGid = addBlackCard.AccountGid;
addblackcard.AcctId = addBlackCard.AccountId;
addblackcard.CardType = addBlackCard.CardType;
addblackcard.DiscountNo = addBlackCard.DiscountNo;
addblackcard.Reason = addBlackCard.Reason;
addblackcard.UploadFlag = addBlackCard.UploadFlag;
spsAddBlackCards.Add(addblackcard);
}
return spsAddBlackCards;
}
#endregion
#region DeleteBlackCard processing
private async Task SaveDeleteBlackCards(List deleteBlackCards)
{
try
{
using (var context = new GuardDbContext())
{
context.DeleteBlackCard.AddRange(deleteBlackCards);
await context.SaveChangesAsync();
}
await SaveToSpsDeleteBlackCards(deleteBlackCards);
}
catch (Exception ex)
{
logger.Error(ex.ToString());
}
}
private async Task SaveToSpsDeleteBlackCards(IEnumerable deleteBlackCards)
{
var comparer = new GenericComparer(c => c.CardNo);
var toBeAddedDeleteBlackCards = ConvertToSpsDeleteBlackCards(deleteBlackCards.Where(c => c.OperationType == 0));
var toBeRemovedDeleteBlackCards = ConvertToSpsDeleteBlackCards(deleteBlackCards.Where(c => c.OperationType == 2));
var spsDeleteBlackCards = ConvertToSpsDeleteBlackCards(deleteBlackCards);
using (var spsDbContext = new SpsDbContext(_spsDbConnString))
{
// handle `to be added DeleteBlackCard records`
var existingInToBeAdded = spsDbContext.TDeleteblackcard
.AsEnumerable()
.Where(dbc => toBeAddedDeleteBlackCards.Where(c => c.CardNo == dbc.CardNo).Count() >= 1)
.ToList();
var newDeleteBlackCards = toBeAddedDeleteBlackCards.Except(existingInToBeAdded, comparer).ToList();
newDeleteBlackCards.ForEach(c => logger.Info($" dbc, add, card no: {c.CardNo}"));
spsDbContext.TDeleteblackcard.AddRange(newDeleteBlackCards);
// handle `to be updated DeleteBlackCard records`
var toBeUpdated = toBeAddedDeleteBlackCards.Except(newDeleteBlackCards, comparer).ToList();
toBeUpdated.ForEach(c => logger.Info($" dbc, upd, card no: {c.CardNo}, time: {c.BlackDate.Value}"));
foreach (var card in toBeUpdated)
{
var match = existingInToBeAdded.FirstOrDefault(c => c.CardNo == card.CardNo);
if (match != null)
{
card.Gid = match.Gid;
spsDbContext.Entry(match).CurrentValues.SetValues(card);
}
}
// handle `to be removed DeleteBlackCard records`
var matchedToBeRemoved = spsDbContext.TDeleteblackcard
.AsEnumerable()
.Where(dbc => toBeRemovedDeleteBlackCards.Where(c => c.CardNo == dbc.CardNo).Count() >= 1)
.ToList();
matchedToBeRemoved.ForEach(c => logger.Info($" dbc, del, card no: {c.CardNo}"));
spsDbContext.TDeleteblackcard.RemoveRange(matchedToBeRemoved);
await spsDbContext.SaveChangesAsync();
spsDeleteBlackCards
.ForEach(c => logger.Info($"deleteblackcard, card no: {c.CardNo}, gid: {c.Gid}"));
await CleanSyncAddedDeleteBlackCards(newDeleteBlackCards.Select(d => d.Gid).ToList());
await CleanSyncRemovedDeleteBlackCards(matchedToBeRemoved.Select(c => c.CardNo).ToList());
}
}
private async Task CleanSyncAddedDeleteBlackCards(List deleteBlackCardGids)
{
using (var context = new SpsDbContext(_spsDbConnString))
{
var deleteBlackCardsGeneratedBySync = context.TTableaudit
.AsEnumerable()
.Where(a => deleteBlackCardGids.Contains(Convert.ToUInt64(a.ReleasedCardCreated)))
.ToList();
context.RemoveRange(deleteBlackCardsGeneratedBySync);
await context.SaveChangesAsync();
}
}
private async Task CleanSyncRemovedDeleteBlackCards(List deleteBlackCardCardNos)
{
using (var context = new SpsDbContext(_spsDbConnString))
{
var deleteBlackCardsRemovedBySync = context.TTableaudit
.AsEnumerable()
.Where(a => deleteBlackCardCardNos.Contains(a.ReleasedCardDeleted))
.ToList();
context.RemoveRange(deleteBlackCardsRemovedBySync);
await context.SaveChangesAsync();
}
}
private List ConvertToSpsDeleteBlackCards(IEnumerable deleteBlackCards)
{
var spsDeleteBlackCards = new List();
foreach (var deleteBlackCard in deleteBlackCards)
{
var deleteblackcard = new TDeleteblackcard();
deleteblackcard.CardNo = deleteBlackCard.CardNo;
deleteblackcard.BlackDate = deleteBlackCard.DateTime;
deleteblackcard.AcctGid = deleteBlackCard.AccountGid;
deleteblackcard.AcctId = deleteBlackCard.AccountId;
deleteblackcard.CardType = deleteBlackCard.CardType;
deleteblackcard.DiscountNo = deleteBlackCard.DiscountNo;
deleteblackcard.Reason = deleteBlackCard.Reason;
deleteblackcard.UploadFlag = deleteBlackCard.UploadFlag;
spsDeleteBlackCards.Add(deleteblackcard);
}
return spsDeleteBlackCards;
}
#endregion
#endregion
#region Persist Offline CardRepLoss
private async Task SaveOfflineCardRepLossInfoList(List offlineCardRepLossInfoList,
long versionNo)
{
if (offlineCardRepLossInfoList == null || offlineCardRepLossInfoList?.Count == 0)
{
return;
}
logger.Info($"cardRepLossInfoList, count: {offlineCardRepLossInfoList.Count}");
var comparer = new GenericComparer(c => c.CardNo);
var spsCardRepLoss = ConvertToSpsCardRepLoss(offlineCardRepLossInfoList);
foreach (var item in spsCardRepLoss)
{
logger.Info($"To be added CardRepLoss, card no: {item.CardNo}, operType: {item.OperType}");
}
using (var spsDbContext = new SpsDbContext(_spsDbConnString))
{
var matches = spsDbContext.TCardreploss
.AsEnumerable()
.Where(tc =>
spsCardRepLoss.Where(s => s.CardNo == tc.CardNo && s.LossTime == tc.LossTime).Count() >= 1)
.ToList();
foreach (var c in matches)
{
logger.Info($"cardreploss, matched, cardNo: {c.CardNo}, lossTime: {c.LossTime?.ToString("yyyy-MM-dd HH:mm:ss")}");
}
var toBeAdded = spsCardRepLoss.Except(matches, comparer).ToList();
if (toBeAdded.Count == 0)
{
logger.Info($"cardreploss, no new records to be added");
return;
}
foreach (var c in toBeAdded)
{
logger.Info($"cardreploss, to be added, cardNo: {c.CardNo}, lossTime: {c.LossTime?.ToString("yyyy-MM-dd HH:mm:ss")}");
}
await spsDbContext.TCardreploss.AddRangeAsync(toBeAdded);
int result = 0;
try
{
result = await spsDbContext.SaveChangesAsync();
logger.Info($"Cardreploss, inserted {result} records");
}
catch (Exception ex)
{
logger.Error($"Exception raised in saving CardReploss: {ex}");
}
var cardRepLossCreated =
await spsDbContext.TTableaudit.Where(r => r.LostCardCreated != 0).ToListAsync();
if (cardRepLossCreated.Count == result)
{
var toBeCleandGids = spsCardRepLoss.Select(r => r.Gid).ToList();
foreach (var gid in toBeCleandGids)
{
logger.Info($"to be cleand gid: {gid}");
}
await CleanSyncCardRepLoss(toBeCleandGids);
}
}
}
private async Task CleanSyncCardRepLoss(List cardRepLosGids)
{
using (var context = new SpsDbContext(_spsDbConnString))
{
var cardRepLossGeneratedBySync = context.TTableaudit
.AsEnumerable()
.Where(a => cardRepLosGids.Contains(Convert.ToUInt64(a.LostCardCreated)))
.ToList();
context.RemoveRange(cardRepLossGeneratedBySync);
await context.SaveChangesAsync();
}
}
private List ConvertToSpsCardRepLoss(IEnumerable cardRepLosses)
{
var cardRepLossList = new List();
foreach (var crp in cardRepLosses)
{
var cardRepLoss = new TCardreploss();
cardRepLoss.CardNo = crp.cardNo;
cardRepLoss.OperNo = crp.operNo;
cardRepLoss.OperType = crp.operType;
cardRepLoss.Sno = Convert.ToUInt32(crp.sNo);
cardRepLoss.LossTime = crp.LossTime;
cardRepLoss.Reason = crp.reason;
cardRepLossList.Add(cardRepLoss);
}
return cardRepLossList;
}
#endregion
#region Get token
private async Task GetTokenAsync(string userName, string password, string baseUrl)
{
logger.Info("Downloader starts to get token...");
_client.DefaultRequestHeaders.Clear();
string tokenUrl = string.Concat(baseUrl, tokenAuthPath);
var formParam = new AuthenticationParameter(grantType, userName, password);
try
{
var response = await _client.PostAsync(tokenUrl, new FormUrlEncodedContent(formParam.Params)).ConfigureAwait(false);
logger.Info($"Token response for downloader, StatusCode = {(int)response.StatusCode}");
if (response.IsSuccessStatusCode)
{
await response.Content.ReadAsStringAsync().ContinueWith(x =>
{
currentAuthToken = JsonConvert.DeserializeObject(x?.Result);
currentAuthToken.TokenRetrievedTime = DateTime.Now;
});
}
else
{
var content = await response.Content.ReadAsStringAsync();
response.Content?.Dispose();
}
return currentAuthToken;
}
catch (Exception ex)
{
logger.Error(ex.ToString());
return null;
}
}
#endregion
}
}