public bool SaveFileInfo(file_history fileHistory) { ObjectParameter fileId = new ObjectParameter("file_id", typeof(long)); using (var context = new indigo_databaseEntities(dbObject.EFSQLConnectionString)) { context.usp_insert_file_history(fileHistory.file_load_id, fileHistory.issuer_id, fileHistory.name_of_file, fileHistory.file_created_date, fileHistory.file_size, DateTimeOffset.Now, fileHistory.file_status_id, fileHistory.file_directory, fileHistory.number_successful_records, fileHistory.number_failed_records, fileHistory.file_load_comments, fileHistory.file_type_id, fileId); } return(true); }
/// <summary> /// Reads all card info from file, checks for duplicates in the file, in the DB and verifies the branch is valid, returns a list of valid card number with their branch code. /// </summary> /// <param name="fullFileName"></param> /// <param name="config"></param> /// <param name="fileHistory"></param> /// <returns></returns> private Dictionary <string, ValidCard> ProcessCardFile_Tieto(string fullFileName, issuer config, file_history fileHistory) { //<PAN, validCard> Dictionary <string, ValidCard> validCards = new Dictionary <string, ValidCard>(); var cardsFile = new TextFile(fullFileName, false, false); try { //<BranchCode, BranchLookup> Dictionary <string, BranchLookup> validBranches = new Dictionary <string, BranchLookup>(); CardRecords = cardsFile.ReadFile(); string duplicatesInFileMessage = ""; string duplicatesInDB = ""; string unlicensesCardsErrorMessage = "";//temporary until license management is fully implemented #region basic records processing and fields settings for (int i = 0; i < CardRecords.Count; i++) { string line = CardRecords[i][0]; //text file, so each record only contains 1 string which then needs to be sub-stringed. string[] fields = line.Split(new string[] { " ".PadLeft(1), " ".PadLeft(2), " ".PadLeft(3), " ".PadLeft(4), " ".PadLeft(5), " ".PadLeft(6), " ".PadLeft(7), " ".PadLeft(8), " ".PadLeft(9), " ".PadLeft(10), " ".PadLeft(11), " ".PadLeft(12), " ".PadLeft(13), " ".PadLeft(14), " ".PadLeft(15) }, StringSplitOptions.RemoveEmptyEntries); ValidCard validCard = new ValidCard(); validCard.PAN = fields[0].Substring(1, 16); validCard.BranchCode = validCard.PAN.Substring(6, 2); validCard.PsuedoPAN = fields[1] + fields[2]; validCard.SequenceNumber = fields[PostilionDetailedRecordColumns.SEQ_NR]; BranchLookup branchLookup; //See if we've already checked the DB for the branch. If it's not in the dictionary then do a read from the DB. if (!validBranches.TryGetValue(validCard.BranchCode, out branchLookup)) { //check if branch exist branch Branch = CheckDBForBranch(config.issuer_id, validCard.BranchCode); branchLookup = new BranchLookup(validCard.BranchCode, 0, false); if (Branch != null) { branchLookup = new BranchLookup(Branch.branch_code, Branch.branch_id, true); } validBranches.Add(validCard.BranchCode, branchLookup); } //check if branch exist //if not, add a record to rejected file if (!branchLookup.IsValid) { RegisterNonExistanceBranch(line, validCard.BranchCode, config); } else { //CardRecords[i] = new[] { validCard.PsuedoPAN, validCard.BranchCode }; //, custNames, pinBlock }; //Check if the card has been added to the dictionary already, if it has dont add it again. if (validCards.ContainsKey(validCard.PsuedoPAN)) { duplicaterecords++; duplicatesInFileMessage += validCard.PsuedoPAN + ", "; } else { //check if card is within licensed ecobank bins -- temp solution //TODO: RAB Remove hard coding here.... yuck yuck yuck if (CheckIfIsLicenseCardRecord(validCard.PsuedoPAN)) { validCard.BranchId = branchLookup.BranchId; validCards.Add(validCard.PsuedoPAN, validCard); } } } } #endregion #region check card records for duplication in indigo //check if card record is in the DB List <string> results = fileLoaderDAL.ValidateCardsLoaded(new List <string>(validCards.Keys)); foreach (string result in results) { //Because the results coming back are based on the keys, the dictionary should have this key, but checking just incase if (validCards.ContainsKey(result)) { //recored is already in DB validCards.Remove(result); duplicaterecords++; duplicatesInDB += string.Format("Card Record is a duplicate in Indigo {0},", result); fileLoadComments += Environment.NewLine + string.Format("Card Record {0} is a duplicate to a previously loaded record. Record will be excluded".ToUpper() + Environment.NewLine, result); } } #endregion processedrecords = validCards.Count; //update file status UpdateFileStatusAfterRead(); //add comments for duplicates if (duplicatesInFileMessage.Trim().Length > 0) { fileLoadComments += " Duplicate records in file: ".ToUpper() + duplicatesInFileMessage + ". "; } if (duplicatesInDB.Trim().Length > 0) { fileLoadComments += " Records already exist in DB: ".ToUpper() + duplicatesInDB + ". "; } //add comments for unlicense records if (unlicensesCardsErrorMessage.Trim().Length > 0) { fileLoadComments += " - Unlicensed cards processing is disabled. Unlicensed records: ".ToUpper() + unlicensedrecords + ". "; } } catch (Exception ex) { //invalid file structure LogFileWriter.WriteFileLoaderError( config.issuer_code + ": " + fullFileName + " contains invalid data, or is not formatted correctly" + ToString(), ex); fileLoadComments += " | file contains invalid data, or is not formatted correctly"; fileStatus = FileStatus.INVALID_FORMAT; invalidformatfile++; } fileHistory.file_statuses.file_status_id = (int)fileStatus; fileHistory.number_successful_records = processedrecords; fileHistory.number_failed_records = duplicaterecords; fileHistory.file_load_comments = fileLoadComments; return(validCards); }
/// <summary> /// THIS IS NOW REDUNDENT CODE - DONT USE /// </summary> /// <param name="config"></param> private void LoadCardFile(issuer config) { //build app log comment applogcomment = DateTime.Now.ToLongTimeString() + " " + config.issuer_code + " CARD FILES: "; var dirInfo = new DirectoryInfo("" /*config.cards_file_location*/); //check there are files to load FileInfo[] filesToLoad = GetFilesToLoad(config, dirInfo); if (filesToLoad != null) { //process each file in array foreach (FileInfo fileInfo in filesToLoad) { file_history fileHistory = new file_history(); fileHistory.file_types = new file_types(); fileHistory.file_statuses = new file_statuses(); fileHistory.name_of_file = fileInfo.Name; fileHistory.file_directory = fileInfo.Directory.ToString(); fileHistory.file_size = (int)fileInfo.Length; fileHistory.file_types.file_type_id = (int)FileType.CARD_IMPORT; fileHistory.file_created_date = fileInfo.CreationTime; //setup variables SetupVariables(fileInfo); //check if the file has already been loaded if (!CheckIfDuplicateFile(config, fileInfo.Name)) { //TO DO: get this value from the database (hard coded for Ecobank) var cmsType = CMS.TIETO; string loadBatchReference = ""; //<PAN, ValidCard> Dictionary <string, ValidCard> validCards = new Dictionary <string, ValidCard>(); //card issuing switch (cmsType) { case CMS.TIETO: //Ecobank loadBatchReference = CreateCardBatchReference_Tieto(fileInfo.Name); if (fileStatus.Equals(FileStatus.READ)) { validCards = ProcessCardFile_Tieto(fullFileName, config, fileHistory); } break; } //write batch and cards to DB if (fileStatus.Equals(FileStatus.PROCESSED) || fileStatus.Equals(FileStatus.PARTIAL_LOAD)) { if (validCards.Count > 0) { if (true /*fileLoaderDAL.CreateLoadBatch(validCards, loadBatchReference, config.issuer_id, fileHistory)*/) { Veneka.Indigo.CardManagement.LoadBatchMangementService loadBatchMgm = new Veneka.Indigo.CardManagement.LoadBatchMangementService(); //SELF APPROVES LOAD BATCH Veneka.Indigo.CardManagement.objects.DatabaseResponse response = null;//loadBatchMgm.UpdateLoadBatchStatus(loadBatchReference, "SYSTEM", // indigoCardManagement.LoadBatchStatus.APPROVED.ToString()); if (response.responseSuccess) { //CREATES A DISTRIBUTION BATCH List <string> cardsList = new List <string>(); string branchCode = String.Empty; foreach (var item in this.CardRecords) { cardsList.Add(item[0]); branchCode = item[1]; } var batch = new Veneka.Indigo.CardManagement.objects.DistributionBatch ( 0, String.Empty, string.Empty, config.issuer_id, null, DateTime.Now, Veneka.Indigo.CardManagement.DistributionBatchStatus.CREATED, cardsList, branchCode, string.Empty, new List <string>()); Veneka.Indigo.CardManagement.DistBatchManagementService distBatchMgm = new Veneka.Indigo.CardManagement.DistBatchManagementService(); if (cardsList.Count > 0) { response = null;//distBatchMgm.CreateDistributionBatch(batch, "SYSTEM", cardsList); } } } } } } //write history CreateFileHistory(fileInfo.Name, fileInfo.Directory.ToString(), fileInfo.Length, FileType.CARD_IMPORT, fileInfo.CreationTime.ToString(), fileStatus, strDateTime, config.issuer_id, processedrecords, duplicaterecords, fileLoadComments); //archive ArchiveFiles(fileStatus, config, fileInfo, strDateTime); } //build app log comment applogcomment += " Success=" + successfileload + ", Partial=" + partialfileload + " Failed=" + failedfileload + ", Duplicate=" + duplicatefile + ", Invalid format=" + invalidformatfile; } //write to application log LogFileWriter.WriteFileLoaderComment(applogcomment); }
/// <summary> /// This method will run usp_create_load_batch. /// Inserts load_batch, load_batch_status, load_cards and file loader. /// Status for batch and cards should be "LOADED" /// </summary> internal bool CreateLoadBatch(Dictionary <string, CardFileRecord> cardList, string loadBatchReference, int issuer_id, file_history fileHistory) { if (InsertCardsListToTempTable(cardList)) { using (SqlConnection con = dbObject.SQLConnection) { using (SqlCommand command = con.CreateCommand()) { DateTimeOffset dateTimeNow = DateTimeOffset.Now; command.CommandType = CommandType.StoredProcedure; command.CommandText = "[usp_create_load_batch]"; //command.Parameters.AddWithValue("@card_list", dt_CardList); command.Parameters.Add("@load_batch_reference", SqlDbType.VarChar).Value = loadBatchReference; command.Parameters.Add("@batch_status_id", SqlDbType.Int).Value = (int)LoadBatchStatus.LOADED; command.Parameters.Add("@user_id", SqlDbType.BigInt).Value = -2; //Using the SYSTEM account. command.Parameters.Add("@load_card_status_id", SqlDbType.Int).Value = (int)LoadCardStatus.LOADED; command.Parameters.Add("@issuer_id", SqlDbType.Int).Value = issuer_id; command.Parameters.Add("@file_load_id", SqlDbType.Int).Value = fileHistory.file_load_id; command.Parameters.Add("@name_of_file", SqlDbType.VarChar).Value = fileHistory.name_of_file; command.Parameters.Add("@file_created_date", SqlDbType.DateTimeOffset).Value = fileHistory.file_created_date; command.Parameters.Add("@file_size", SqlDbType.Int).Value = fileHistory.file_size; command.Parameters.Add("@load_date", SqlDbType.DateTimeOffset).Value = dateTimeNow; command.Parameters.Add("@file_status_id", SqlDbType.VarChar).Value = fileHistory.file_status_id; command.Parameters.Add("@file_directory", SqlDbType.VarChar).Value = fileHistory.file_directory; command.Parameters.Add("@number_successful_records", SqlDbType.Int).Value = 1; //fileHistory.number_successful_records; command.Parameters.Add("@number_failed_records ", SqlDbType.Int).Value = 1; //fileHistory.number_failed_records; command.Parameters.Add("@file_load_comments", SqlDbType.VarChar).Value = String.IsNullOrWhiteSpace(fileHistory.file_load_comments) ? "No Comment." : fileHistory.file_load_comments; command.Parameters.Add("@file_type_id", SqlDbType.VarChar).Value = fileHistory.file_type_id; //command.Parameters.Add("@number_successful_records", SqlDbType.Int).Direction = ParameterDirection.Output; command.ExecuteNonQuery(); return(true); } } } return(false); }
/// <summary> /// Load all card files within the directory. /// </summary> public void LoadCardFile() { int fileLoadId = 0; try { //Create file_load for this file load session DateTimeOffset startTime = DateTimeOffset.Now; //get all files from issuer directory if (Directory.Exists(cardsFileLocation)) { var dirissuerInfo = new DirectoryInfo(cardsFileLocation); fileLoadId = fileLoaderDAL.CreateFileLoad(startTime, dirissuerInfo.GetFiles().Count()); log.Debug(m => m("Reading Encrypted Files from " + cardsFileLocation + "...")); foreach (FileInfo encryptedFileInfo in dirissuerInfo.GetFiles()) { List <FileCommentsObject> fileComments = new List <FileCommentsObject>(); licensedBinCodes.Clear(); log.Debug(m => m("Processing file: " + encryptedFileInfo.Name)); fileComments.Add(new FileCommentsObject("Processing file: " + encryptedFileInfo.Name)); //Build file_history object. file_history fileHistory = new file_history(); fileHistory.file_load_id = fileLoadId; fileHistory.file_types = new file_types(); fileHistory.file_statuses = new file_statuses(); fileHistory.file_status_id = (int)FileStatus.READ; fileHistory.name_of_file = encryptedFileInfo.Name; fileHistory.file_directory = encryptedFileInfo.Directory.ToString(); fileHistory.file_size = (int)encryptedFileInfo.Length; fileHistory.file_created_date = DateTime.SpecifyKind(encryptedFileInfo.CreationTime, DateTimeKind.Local); try //Catch exception per file so proccessing of each file may still happen and not stop on a single file exceptin { FileInfo fileInfo; FileStatus fstatus = DecryptPgpFile(cardsFileLocation, encryptedFileInfo, out fileInfo, ref fileComments); if (fstatus != FileStatus.READ) { fileHistory.file_status_id = (int)fstatus; continue; } //Now process the unencrypted file. log.Debug(m => m(string.Format("Start processing decrypted file:\t{0}", fileInfo.Name))); fileComments.Add(new FileCommentsObject(string.Format("Start processing decrypted file:\t{0}", fileInfo.Name))); try { //Update file history Info with new decrypted file info. fileHistory.name_of_file = fileInfo.Name; fileHistory.file_directory = fileInfo.Directory.ToString(); fileHistory.file_size = (int)fileInfo.Length; fileHistory.file_types.file_type_id = (int)FileType.CARD_IMPORT; fileHistory.file_created_date = DateTime.SpecifyKind(fileInfo.CreationTime, DateTimeKind.Local);; //read all records from the file and decode into CardFileRecord Object. List <CardFileRecord> cardFileRecords; if (!getCardRecords(fileInfo, out cardFileRecords, ref fileComments)) { fileHistory.file_status_id = (int)FileStatus.CARD_FILE_INFO_READ_ERROR; continue; } //Find Issuer Based on BIN code Branch log.Debug(m => m("Finding Issuer based on PAN: " + cardFileRecords[0].PsuedoPAN + " BIN: " + cardFileRecords[0].PAN.Substring(0, 9) + " BRANCHCODE: " + cardFileRecords[0].BranchCode)); fileComments.Add(new FileCommentsObject("Finding Issuer based on PAN: " + cardFileRecords[0].PsuedoPAN + " BIN: " + cardFileRecords[0].PAN.Substring(0, 9) + " BRANCHCODE: " + cardFileRecords[0].BranchCode)); issuer issuer; if (!fileLoaderDAL.FetchIssuerByProductAndBinCode(cardFileRecords[0].PAN, cardFileRecords[0].BranchCode, out issuer)) { log.Error("Issuer and/or Product not correctly setup."); fileComments.Add(new FileCommentsObject("Issuer and/or Product not correctly setup.")); fileHistory.file_status_id = (int)FileStatus.BRANCH_PRODUCT_NOT_FOUND; continue; } fileHistory.issuer_id = issuer.issuer_id; if (issuer == null || !issuer.instant_card_issue_YN) { log.Error("Issuer has not be setup for instant card issuing."); fileComments.Add(new FileCommentsObject("Issuer has not be setup for instant card issuing.")); fileHistory.file_status_id = (int)FileStatus.LOAD_FAIL; continue; } //Check if issuer is licenced fileComments.Add(new FileCommentsObject("Checking issuer licence.")); log.Debug(m => m("Checking issuer licence.")); if (String.IsNullOrWhiteSpace(issuer.license_key)) { log.Error("Unlicenced issuer."); fileComments.Add(new FileCommentsObject("Unlicenced issuer.")); fileHistory.file_status_id = (int)FileStatus.UNLICENSED_ISSUER; continue; } //check if the file has already been loaded for an active batch log.Debug(m => m("Checking for duplicate file in database.")); fileComments.Add(new FileCommentsObject("Checking for duplicate file in database.")); if (CheckIfDuplicateFile(fileInfo.Name)) { fileHistory.file_status_id = (int)FileStatus.DUPLICATE_FILE; log.Error("Duplicate file with name " + fileInfo.Name + ", skipping file."); fileComments.Add(new FileCommentsObject("Duplicate file with name " + fileInfo.Name + ", skipping file.")); continue; } //Validate Key, and get valid bins. log.Debug(m => m("Getting licensed bins.")); fileComments.Add(new FileCommentsObject("Getting licensed bins.")); licensedBinCodes = Veneka.Indigo.Common.License.LicenseManager.ValidateAffiliateKey(issuer.license_key); if (licensedBinCodes == null || licensedBinCodes.Count == 0) { log.Error("No licensed bins found for this issuer."); fileComments.Add(new FileCommentsObject("No licensed bins found for this issuer.")); fileHistory.file_status_id = (int)FileStatus.INVALID_ISSUER_LICENSE; continue; } //Validate all card records log.Debug(m => m("Validating cards.")); fileComments.Add(new FileCommentsObject("Validating cards.")); Dictionary <string, CardFileRecord> validCards = new Dictionary <string, CardFileRecord>(); fileHistory.file_status_id = (int)validateCardRecords(cardFileRecords, issuer.issuer_id, out validCards, ref fileComments); log.Debug(m => m("Valid cards count: " + validCards.Count)); fileComments.Add(new FileCommentsObject("Valid cards count: " + validCards.Count)); //write load batch and cards to DB if (fileHistory.file_status_id != (int)FileStatus.VALID_CARDS) { log.Error("Not all card within card file are valid."); fileComments.Add(new FileCommentsObject("Not all card within card file are valid.")); continue; } //Generate batch reference string loadBatchReference = generateBatchReference(fileInfo); fileHistory.file_status_id = (int)FileStatus.PROCESSED; fileHistory.file_load_comments = BuildFileComments(fileComments); //Persist to the DB log.Debug(m => m("Saving load batch to database, batch ref:\t" + loadBatchReference)); fileComments.Add(new FileCommentsObject("Saving load batch to database, batch ref:\t" + loadBatchReference)); if (fileLoaderDAL.CreateLoadBatch(validCards, loadBatchReference, issuer.issuer_id, fileHistory)) { log.Info("Successfully processed the file."); fileComments.Add(new FileCommentsObject("Successfully processed the file.")); fileHistory.file_status_id = (int)FileStatus.PROCESSED; } else { log.Error("Failed to save load batch to database."); fileComments.Add(new FileCommentsObject("Failed to save load batch to database.")); fileHistory.file_status_id = (int)FileStatus.LOAD_FAIL; continue; } //if (issuer.delete_card_file_YN) //{ // File.Delete(fileInfo.FullName); //} } catch (Exception ex) { log.Fatal("Error processing file " + fileInfo.Name + ".", ex); fileComments.Add(new FileCommentsObject("Error processing file:\t" + ex.Message)); fileHistory.file_status_id = (int)FileStatus.LOAD_FAIL; } finally { //Delete unencrypted file!!! fileInfo.Delete(); //archive the file ArchiveFiles((FileStatus)fileHistory.file_status_id, encryptedFileInfo); } } catch (Exception ex) { log.Error(ex); fileHistory.file_status_id = (int)FileStatus.LOAD_FAIL; } finally { fileHistory.file_load_comments = BuildFileComments(fileComments); //Write FileHistory to DB. if (fileHistory.file_status_id != (int)FileStatus.PROCESSED) { fileLoaderDAL.SaveFileInfo(fileHistory); } } } } } catch (DirectoryNotFoundException dirEx) { log.Warn(dirEx); } catch (Exception ex) { log.Fatal("Error when running file loader.", ex); } finally { if (fileLoadId != 0) { fileLoaderDAL.UpdateFileLoad(fileLoadId); } } }