static void Main(string[] args) { var 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 #region Cache Appconfig to memory List <string> tableoptions = Appconfig.TableOptions; Dictionary <string, string> TableOptionPair = new Dictionary <string, string>(); tableoptions.ForEach(x => { string tablename = x.SubstringUntil("["); string tableOption = x.SubstringBetween('[', ']'); TableOptionPair.Add(tablename, tableOption); }); #endregion #region setting sap DestinationRegister.RegistrationDestination(new SAPDestinationSetting { AppServerHost = Appconfig.SAPServerHost, Client = Appconfig.SAPClient, SystemNumber = Appconfig.SAPSystemNumber, SystemID = Appconfig.SAPSystemID, User = Appconfig.SAPUser, Password = Appconfig.SAPPassword }); #endregion /*** * Step to cache new table * 1.defined model/model manager and add to intramartdbcontext * 2.put option/table to app config * 3.register table in program class * */ #region RegisteringTable and Type Dictionary <string, Type> tableDict = new Dictionary <string, Type>(); tableDict.Add("KNA1", typeof(KNA1Manger)); tableDict.Add("COAS", typeof(COASManager)); tableDict.Add("V_AUART", typeof(V_AUARTManager)); tableDict.Add("LFA1", typeof(LFA1Manager)); tableDict.Add("KNVV", typeof(KNVVManager)); tableDict.Add("TVV1T", typeof(TVV1TManager)); tableDict.Add("TVV2T", typeof(TVV2TManager)); tableDict.Add("TVV3T", typeof(TVV3TManager)); tableDict.Add("TVKOV", typeof(TVKOVManager)); tableDict.Add("TVKBZ", typeof(TVKBZManager)); tableDict.Add("TVTWT", typeof(TVTWTManager)); tableDict.Add("TVKBT", typeof(TVKBTManager)); tableDict.Add("TVBVK", typeof(TVBVKManager)); tableDict.Add("TVGRT", typeof(TVGRTManager)); tableDict.Add("T171T", typeof(T171TManager)); tableDict.Add("TVKOT", typeof(TVKOTManager)); tableDict.Add("MARA", typeof(MARAManager)); tableDict.Add("MAKT", typeof(MAKTManager)); tableDict.Add("SKA1", typeof(SKA1Manager)); tableDict.Add("SKAT", typeof(SKATManager)); tableDict.Add("MVKE", typeof(MVKEManager)); tableDict.Add("T179", typeof(T179Manager)); tableDict.Add("T179T", typeof(T179TManager)); tableDict.Add("TVM1T", typeof(TVM1TManager)); tableDict.Add("TVM2T", typeof(TVM2TManager)); tableDict.Add("TVM3T", typeof(TVM3TManager)); tableDict.Add("TVM4T", typeof(TVM4TManager)); tableDict.Add("T134T", typeof(T134TManager)); tableDict.Add("T006A", typeof(T006AManager)); tableDict.Add("T001K", typeof(T001KManager)); tableDict.Add("T190ST", typeof(T190STManager)); tableDict.Add("TWSPR", typeof(TWSPRManager)); tableDict.Add("T023T", typeof(T023TManager)); tableDict.Add("TSPAT", typeof(TSPATManager)); tableDict.Add("TVSMT", typeof(TVSMTManager)); tableDict.Add("TVKMT", typeof(TVKMTManager)); tableDict.Add("TMVFT", typeof(TMVFTManager)); tableDict.Add("TTGRT", typeof(TTGRTManager)); tableDict.Add("TLGRT", typeof(TLGRTManager)); tableDict.Add("T024", typeof(T024Manager)); tableDict.Add("T438X", typeof(T438XManager)); tableDict.Add("T438T", typeof(T438TManager)); tableDict.Add("T439T", typeof(T439TManager)); tableDict.Add("T024D", typeof(T024DManager)); tableDict.Add("T001L", typeof(T001LManager)); tableDict.Add("TQ30T", typeof(TQ30TManager)); tableDict.Add("TQ08T", typeof(TQ08TManager)); tableDict.Add("TQ05T", typeof(TQ05TManager)); tableDict.Add("T025", typeof(T025Manager)); tableDict.Add("T025T", typeof(T025TManager)); tableDict.Add("TCK14", typeof(TCK14Manager)); tableDict.Add("TCK15", typeof(TCK15Manager)); tableDict.Add("CEPCT", typeof(CEPCTManager)); tableDict.Add("MBEW", typeof(MBEWManager)); tableDict.Add("T077X", typeof(T077XManager)); tableDict.Add("T151T", typeof(T151TManager)); tableDict.Add("TZONT", typeof(TZONTManager)); tableDict.Add("T005U", typeof(T005UManager)); tableDict.Add("T052U", typeof(T052UManager)); tableDict.Add("PA0001", typeof(PA0001Manager)); tableDict.Add("T005T", typeof(T005TManager)); tableDict.Add("T014T", typeof(T014TManager)); tableDict.Add("ADRC", typeof(ADRCManager)); tableDict.Add("ADR2", typeof(ADR2Manager)); tableDict.Add("ADR6", typeof(ADR6Manager)); tableDict.Add("KNVP", typeof(KNVPManager)); tableDict.Add("KNKK", typeof(KNKKManager)); tableDict.Add("TVSBT", typeof(TVSBTManager)); #endregion log.Debug("-----------------------------------------------------------------------------------------"); log.Debug("Sync Begin"); log.Debug("-----------------------------------------------------------------------------------------"); #region startSync foreach (var tablename in Appconfig.TableToSync) { var option = new List <string>(); if (TableOptionPair.ContainsKey(tablename)) { option.Add(TableOptionPair[tablename]); } if (tableDict.ContainsKey(tablename)) { var targetClass = tableDict[tablename]; CacheTable instance = (CacheTable)Activator.CreateInstance(targetClass, option); var syncComplete = instance.SyncStart(); if (syncComplete) { Console.WriteLine("Table [" + instance._tableName + "] has been synced."); log.Debug("Table [" + instance._tableName + "] has been synced."); } else { Console.WriteLine("Table [" + instance._tableName + "] ERROR occured."); log.Error("Table [" + instance._tableName + "] ERROR occured."); } } } #endregion log.Debug("-----------------------------------------------------------------------------------------"); log.Debug("Sync End"); log.Debug("-----------------------------------------------------------------------------------------"); log.Debug(Environment.NewLine); }
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("*******************************************************************"); }