public static async Task <Result <CurrencyRate> > GetRate(string currency, DateTime date) { log.Debug("GetRate is run for " + currency + " " + date.ToString("dd/MM/yyyy")); var query = new NameValueCollection(); query["start_period"] = date.ToString("yyyy-MM-dd", new CultureInfo("en-US")); query["end_period"] = date.ToString("yyyy-MM-dd", new CultureInfo("en-US")); query["currency"] = currency; var header = new NameValueCollection(); header["api-key"] = Appconfig.BOTAPIKey; var callResult = await RESTServiceCall.GetJSONAsync(Appconfig.BOTServiceEndPoint, query, header); dynamic response = callResult; if (response.result.success == "true") { try { var data = response.result.data["data_detail"].First; string period = data.period; string currency_pair = (string)data.currency_id; string buy = data[Appconfig.BuyValue]; if (String.IsNullOrWhiteSpace(buy)) { buy = "0"; } string sell = data[Appconfig.SellValue]; if (String.IsNullOrWhiteSpace(sell)) { sell = "0"; } log.Debug("GetRate Extracting Data complete at " + period + " " + currency_pair + " " + buy + " " + sell); bool isAPIComplete = !String.IsNullOrWhiteSpace(period); if (!isAPIComplete) { var timestampDate = DateTime.ParseExact((string)response.result.timestamp, "yyyy-MM-dd HH:mm:ss", new CultureInfo("en-US")); var lastupdated = DateTime.ParseExact((string)response.result.data.data_header.last_updated, "yyyy-MM-dd", new CultureInfo("en-US")); //ถ้า date เป็นของวันก่อนหน้า ถือว่าา APIComplete //หรือถ้า date เป็นของวันนี้ และ timestamp บอกว่าเลย 6 โมงเย็น จะถือว่า complete เช่นกัน if (date.CompareTo(timestampDate.Date) < 0) { isAPIComplete = true; } else { if (timestampDate.Hour >= 18) { isAPIComplete = true; } } } return(new Result <CurrencyRate> { Success = true, Data = new CurrencyRate { Date = date, Buy = Convert.ToDecimal(buy), Sell = Convert.ToDecimal(sell), isAPIComplete = isAPIComplete, isSyncSAP = false, Currency = currency_pair } }); } catch (Exception ex) { log.Debug("GetRate REST calling pass but extracting data error" + ex.Message); ExceptionHandling.LogException(ex); return(new Result <CurrencyRate> { Success = false, Failure = FailureType.UnexpectedServiceBehaviorError, Message = ex.Message }); } } else { string errorMsg = string.Empty; JToken errors = response.result["error"] as JToken; foreach (dynamic error in errors) { errorMsg += string.Format(@" {0}:{1} ", error.code, error.message); } log.Debug("GetRate REST calling ERROR Occured" + errorMsg); return(new Result <CurrencyRate> { Success = false, Failure = FailureType.DatabaseConnectionError, Message = errorMsg }); } }
static void Main(string[] args) { string path = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); Appconfig.Initialize(path, ConfigurationManager.AppSettings, null); #region Logger log4net.GlobalContext.Properties["LOG4NET_ERROR"] = Appconfig.LOG4NET_ERROR; //log file path log4net.GlobalContext.Properties["LOG4NET_DEBUG"] = Appconfig.LOG4NET_DEBUG; //log file path log4net.Config.XmlConfigurator.Configure(); #endregion var currencyRatioDict = Appconfig.CurrencyRatioDict; DateTime programDatetime = DateTime.Now; DateTime runningDate; if (programDatetime.Hour > Appconfig.BOTHourUpdate) { runningDate = new DateTime(programDatetime.Year, programDatetime.Month, programDatetime.Day); } else { var programDatetimeYesterday = programDatetime.AddDays(-1); runningDate = new DateTime(programDatetimeYesterday.Year, programDatetimeYesterday.Month, programDatetimeYesterday.Day); } if (args != null && args.Count() > 0) { DateTime tryResult; if (DateTime.TryParseExact(args.First(), "d/MM/yyyy", new CultureInfo("en-US"), DateTimeStyles.None, out tryResult)) { runningDate = tryResult; } } log.Debug("*******************************************************************"); log.Debug("PROGRAM RUNS ON " + programDatetime.ToString("dd/MM/yyyy HH:mm:ss")); log.Debug("*******************************************************************"); JsonLogService db = new JsonLogService(Appconfig.JsonLog); var dateToRun = new List <DateTime>(); if (!Appconfig.RecoveryMode) { dateToRun.Add(runningDate); // we could check last date run is yesterday|| today ? if not we cound add lost day in between var lastDataDate = db.GetLastRunningDate(); if (lastDataDate != default(DateTime) && lastDataDate.CompareTo(runningDate) < 0) // 0 means run second time for the day, 1 is not possible (if we do not force them to run future's day) { log.Debug("-----------------------------------------------------------------"); log.Debug("CHECKING LAST RUNING DATE FOR SPECIFY DATES TO RUN (IF THERE IS MISSING RUNNING ON SOME DAYS)"); log.Debug("-----------------------------------------------------------------"); var timeSpanDiff = runningDate.Subtract(lastDataDate); if (timeSpanDiff.TotalDays > 1) { int dayToRecover = Convert.ToInt32(timeSpanDiff.TotalDays) - 1; for (int i = 1; i <= dayToRecover; i++) { dateToRun.Add(runningDate.AddDays(-i)); } } } } else { foreach (var recoveryDate in Appconfig.RecoveryDate) { DateTime tryResult; if (DateTime.TryParseExact(recoveryDate, "d/M/yyyy", new CultureInfo("en-US"), DateTimeStyles.None, out tryResult)) { dateToRun.Add(tryResult); } } } foreach (var transactionDate in dateToRun) { #region BOT API log.Debug("-----------------------------------------------------------------"); log.Debug("API Call Start"); log.Debug("-----------------------------------------------------------------"); //var todayLog = db.GetDailyLog(transactionDate);//?? List <Task> taskList = new List <Task>(); foreach (var currencyPair in Appconfig.SyncCurrency) { var currencyInDb = db.GetOrCreateCurrency(transactionDate, currencyPair); //if sap is sync we will not call api again if (currencyInDb.isSyncSAP == false) { if (currencyInDb.isAPIComplete) { log.Debug(String.Format(@"NOTE : THERE WAS FINISHED API CALL BUT SAP ERROR --> RECALL API AGAIN {0} {1}", currencyInDb.Currency, currencyInDb.Date.ToShortDateString())); } taskList.Add(APIExecute(currencyInDb, transactionDate)); } } var unfinishedAPI = db.GetUnfinishedBOTSync().Where(x => x.Date != transactionDate && Appconfig.SyncCurrency.Contains(x.Currency) && x.isSyncSAP == false); foreach (var currencyPair in unfinishedAPI) { taskList.Add(APIExecute(currencyPair, currencyPair.Date)); } Task.WhenAll(taskList).Wait(); log.Debug("-----------------------------------------------------------------"); log.Debug("API Call Successfully"); log.Debug("-----------------------------------------------------------------"); if (!db.SaveChange()) { log.Debug("-----------------------------------------------------------------"); log.Debug("Log Update Error"); log.Debug("-----------------------------------------------------------------"); } else { log.Debug("-----------------------------------------------------------------"); log.Debug("Log Update Successful"); log.Debug("-----------------------------------------------------------------"); } #endregion } #region API Patch for non-value date log.Debug("=============================================================================="); log.Debug("CHECK PATCHING START"); log.Debug("=============================================================================="); try { var patchingNeededDates = db.GetAllLog().Where(x => x.CurrenciesRate.Any(c => Appconfig.SyncCurrency.Contains(c.Currency) && c.isAPIComplete == true && c.isSyncSAP == false && c.Sell_SAP == (decimal)0 && c.Buy_SAP == (decimal)0)).ToList();//REVIEW if (patchingNeededDates.Count > 0) { log.Debug("PATCHING FOUND"); Patching(Appconfig.SyncCurrency, patchingNeededDates); log.Debug("PATCHING END"); } } catch (Exception ex) { log.Debug("=============================================================================="); log.Debug("CHECK PATCHING ERROR : CHECK THE EXCEPTION BELOW"); log.Debug("=============================================================================="); ExceptionHandling.LogException(ex); } #endregion #region SAP Part /// we will send sap only isAPIcomplete and if none of Buy and Sell we will use the last known value before that day to be value sent to SAP /// send only currency config, only isAPIComplete = true, only isSAPComplete = false log.Debug("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); log.Debug("SAP START"); log.Debug("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); bool isSAPCompleted = true; string SAPErrorMsg = string.Empty; try { var sapSent = db.GetAllLog().Where(x => x.CurrenciesRate.Any(c => Appconfig.SyncCurrency.Contains(c.Currency) && c.isAPIComplete == true && c.isSyncSAP == false && c.Sell_SAP != (decimal)0 && c.Buy_SAP != (decimal)0)).ToList(); #region SAP Connection DestinationRegister.RegistrationDestination(new SAPDestinationSetting { AppServerHost = Appconfig.SAPServerHost, Client = Appconfig.SAPClient, User = Appconfig.SAPUser, Password = Appconfig.SAPPassword, SystemNumber = Appconfig.SAPSystemNumber, SystemID = Appconfig.SAPSystemID, }); var des = RfcDestinationManager.GetDestination(DestinationRegister.Destination()); IRfcFunction function = des.Repository.CreateFunction("ZBAPI_EXCHANGERATE_UPDATE"); #endregion #region example for input structure as input bapi /* * TABLE :I_EXCHANGE * STRUCTURE BAPI1093_0 * RATE_TYPE Exchange Rate Type , B = buy // M = sell * FROM_CURR From currency * TO_CURRNCY To-currency * VALID_FROM Date from Which Entry Is Valid (yyyy-MM-dd) * EXCH_RATE Direct Quoted Exchange Rate * FROM_FACTOR Ratio for the "From" Currency Units, 1 // if JPY this is 100 * TO_FACTOR Ratio for the "To" Currency Units, 1 * EXCH_RATE_V Indirect Quoted Exchange Rate ****No input * FROM_FACTOR_V Ratio for the "From" Currency Units ****No input * TO_FACTOR_V Ratio for the "To" Currency Units ****No input */ IRfcTable table = function["I_EXCHANGE"].GetTable();//table List <CurrencyRate> sentSAP = new List <CurrencyRate>(); foreach (var dailyLog in sapSent) { foreach (var cur in dailyLog.CurrenciesRate.Where(c => Appconfig.SyncCurrency.Contains(c.Currency) && c.isAPIComplete == true && c.isSyncSAP == false && c.Sell_SAP != (decimal)0 && c.Buy_SAP != (decimal)0)) { table.Append(); //create new row IRfcStructure Buy = table.CurrentRow; //current structure ,row string structure_name = Buy.Metadata.Name; //Buy Buy.SetValue("RATE_TYPE", "B"); Buy.SetValue("FROM_CURR", cur.Currency); Buy.SetValue("TO_CURRNCY", "THB"); Buy.SetValue("VALID_FROM", dailyLog.Date.ToString("yyyy-MM-dd", new CultureInfo("en-US"))); Buy.SetValue("EXCH_RATE", cur.Buy_SAP.ToString("0.#####")); if (currencyRatioDict.ContainsKey(cur.Currency)) { Buy.SetValue("FROM_FACTOR", currencyRatioDict[cur.Currency]); } else { Buy.SetValue("FROM_FACTOR", 1); } Buy.SetValue("TO_FACTOR", 1); log.Debug(String.Format("{0} {1} {2} {3} {4}", "B", cur.Currency, "THB", dailyLog.Date.ToString("ddMMyyyy", new CultureInfo("en-US")), cur.Buy_SAP.ToString("0.#####"))); table.Append(); //create new row IRfcStructure Sell = table.CurrentRow; //current structure ,row //Sell Sell.SetValue("RATE_TYPE", "M"); Sell.SetValue("FROM_CURR", cur.Currency); Sell.SetValue("TO_CURRNCY", "THB"); Sell.SetValue("VALID_FROM", dailyLog.Date.ToString("yyyy-MM-dd", new CultureInfo("en-US"))); Sell.SetValue("EXCH_RATE", cur.Sell_SAP.ToString("0.#####")); if (currencyRatioDict.ContainsKey(cur.Currency)) { Sell.SetValue("FROM_FACTOR", currencyRatioDict[cur.Currency]); } else { Sell.SetValue("FROM_FACTOR", 1); } Sell.SetValue("TO_FACTOR", 1); log.Debug(String.Format("{0} {1} {2} {3} {4}", "M", cur.Currency, "THB", dailyLog.Date.ToString("ddMMyyyy", new CultureInfo("en-US")), cur.Sell_SAP.ToString("0.#####"))); sentSAP.Add(cur); } } var count = table.Count; #endregion if (count > 0) { try { function.Invoke(des); sentSAP.ForEach(x => { x.isSyncSAP = true; }); } catch (SAP.Middleware.Connector.RfcAbapClassicException ex) { if (ex.Key == "SAPSQL_ARRAY_INSERT_DUPREC") { //dublicate record found log.Debug("-----------------------------------------------------------------"); log.Debug("SAP BAPI CALL Error : DUBLICATED RECORD FOUND IN SAP."); log.Debug("-----------------------------------------------------------------"); } ExceptionHandling.LogException(ex); } catch (Exception ex) { isSAPCompleted = false; SAPErrorMsg += Environment.NewLine + ex.Message; log.Debug("-----------------------------------------------------------------"); log.Debug("SAP BAPI CALL Error : READ THE EXCEPTION DETAIL."); log.Debug("-----------------------------------------------------------------"); ExceptionHandling.LogException(ex); } } //Call bapi #region example for fetch structure as object /* * IRfcParameter export = function["PRHEADER"]; * IRfcStructure structure = export.GetStructure(); * var setting = new PropertiesList<DataContainer> * { * { "PREQ_NO", x=>x.PREQ_NO}, * { "PREQ_NO", x=>x.PREQ_NO}, * { "PR_TYPE", x=>x.PR_TYPE}, * { "CTRL_IND", x=>x.CTRL_IND}, * }; * DataContainer output = structure.ToObject(setting);*/ #endregion IRfcParameter returnTable = function["I_EXCHANGE"]; IRfcTable table1 = returnTable.GetTable(); //foreach (IRfcStructure record in table1) //{ // Console.WriteLine(String.Format("{0}:{1}", record.GetInt("PREQ_ITEM"), record.GetValue("PREQ_ITEM").ToString())); //} if (!db.SaveChange()) { log.Debug("-----------------------------------------------------------------"); log.Debug("Log Update Error"); log.Debug("-----------------------------------------------------------------"); } else { log.Debug("-----------------------------------------------------------------"); log.Debug("Log Update Successful"); log.Debug("-----------------------------------------------------------------"); } } catch (Exception ex) { isSAPCompleted = false; SAPErrorMsg += Environment.NewLine + ex.Message; log.Debug("-----------------------------------------------------------------"); log.Debug("SAP PART Error : READ THE EXCEPTION DETAIL."); log.Debug("-----------------------------------------------------------------"); ExceptionHandling.LogException(ex); } #endregion #region AlertMsg try { if (!Appconfig.RecoveryMode && db.GetOrCreateDailyLog(runningDate).CurrenciesRate.Any(x => Appconfig.SyncCurrency.Contains(x.Currency) && x.isSyncSAP == false && x.Sell != (decimal)0 && x.Buy != (decimal)0) && programDatetime.Date.AddDays(-1) == runningDate.Date && programDatetime.Hour < Appconfig.BOTHourUpdate && programDatetime.Hour > Appconfig.AlertCutOffTime) { //recovery mode is off //there is some sync currency which cannot sent to SAP found and it is not dayoff (sell && buy !=0) //program is running on not today for sure (not after 18.00 of the day) (not before 7.00 of the program date) MailService mailService = new MailService(Appconfig.MailServer, Appconfig.MailServerPort); //send email to user Email userMail = new Email(); userMail.Cc = Appconfig.AlertAdminEmail; userMail.From = Appconfig.MailAdminAddress; userMail.To = Appconfig.AlertUserEmail; userMail.Subject = @"[BOTExchangeRate] ERROR UPDATE TO SAP NOTIFICATION"; userMail.SenderName = @"BOTExchange Automatic Email Alert"; userMail.BodyMessage = MailTemplateUser(runningDate, Appconfig.SyncCurrency); mailService.SendMail(userMail); //send email to admin if exception found if (!isSAPCompleted) { Email adminMail = new Email(); adminMail.From = Appconfig.MailAdminAddress; adminMail.To = Appconfig.AlertAdminEmail; adminMail.Subject = @"[BOTExchangeRate] ERROR UPDATE TO SAP NOTIFICATION [DEBUG]"; adminMail.SenderName = @"BOTExchange Automatic Email Alert"; adminMail.BodyMessage = MailTemplateAdmin(runningDate, Appconfig.SyncCurrency, SAPErrorMsg); mailService.SendMail(adminMail); } } } catch (Exception ex) { log.Debug("-----------------------------------------------------------------"); log.Debug("EMAIL ALERT ERROR"); log.Debug("-----------------------------------------------------------------"); ExceptionHandling.LogException(ex); } #endregion log.Debug("*******************************************************************"); log.Debug("PROGRAM RUNS COMPLETED " + programDatetime.ToString("dd/MM/yyyy HH:mm:ss")); log.Debug("*******************************************************************"); }
public static async Task <Result <List <DailyLog> > > GetRatePatching(string currency, DateTime dateStart, DateTime dateEnd) { log.Debug("GetRate Patching is run for " + currency + " " + dateStart.ToString("dd/MM/yyyy") + " to " + dateEnd.ToString("dd/MM/yyyy")); var query = new NameValueCollection(); query["start_period"] = dateStart.ToString("yyyy-MM-dd", new CultureInfo("en-US")); query["end_period"] = dateEnd.ToString("yyyy-MM-dd", new CultureInfo("en-US")); query["currency"] = currency; var header = new NameValueCollection(); header["api-key"] = Appconfig.BOTAPIKey; var callResult = await RESTServiceCall.GetJSONAsync(Appconfig.BOTServiceEndPoint, query, header); dynamic response = callResult; if (response.result.success == "true") { try { var output = new List <DailyLog>(); foreach (var data in response.result.data["data_detail"]) { string period = data.period; string currency_pair = (string)data.currency_id; string buy = data[Appconfig.BuyValue]; if (String.IsNullOrWhiteSpace(buy)) { buy = "0"; } string sell = data[Appconfig.SellValue]; if (String.IsNullOrWhiteSpace(sell)) { sell = "0"; } log.Debug("GetRatePatching Extracting Data complete at " + period + " " + currency_pair + " " + buy + " " + sell); if (!String.IsNullOrWhiteSpace(period)) { var date = DateTime.ParseExact(period, "yyyy-MM-dd", new CultureInfo("en-US")); DailyLog log = new DailyLog() { CurrenciesRate = new List <CurrencyRate> { new CurrencyRate { Date = date, Buy = Convert.ToDecimal(buy), Sell = Convert.ToDecimal(sell), isAPIComplete = true, isSyncSAP = false, Currency = currency_pair } } , Date = date }; output.Add(log); } } return(new Result <List <DailyLog> > { Success = true, Data = output }); } catch (Exception ex) { log.Debug("GetRate REST calling pass but extracting data error" + ex.Message); ExceptionHandling.LogException(ex); return(new Result <List <DailyLog> > { Success = false, Failure = FailureType.UnexpectedServiceBehaviorError, Message = ex.Message }); } } else { string errorMsg = string.Empty; JToken errors = response.result["error"] as JToken; foreach (dynamic error in errors) { errorMsg += string.Format(@" {0}:{1} ", error.code, error.message); } log.Debug("GetRate REST calling ERROR Occured" + errorMsg); return(new Result <List <DailyLog> > { Success = false, Failure = FailureType.DatabaseConnectionError, Message = errorMsg }); } }