public static string HandleDeletes(string community, string startingDate, string endingDate, int maxRecords, ref int recordsDeleted) { int pageNbr = 1; int pageSize = 50; //string importError = ""; //may want to just do all types! string type = ""; List <string> messages = new List <string>(); List <ReadEnvelope> list = new List <ReadEnvelope>(); SaveStatus status = new SaveStatus(); int pTotalRows = 0; int cntr = 0; bool isComplete = false; int exceptionCtr = 0; string statusMessage = ""; string importResults = ""; string importNote = ""; LoggingHelper.DoTrace(1, string.Format("=== DELETES ===", thisClassName)); //startingDate = "2017-10-29T00:00:00"; try { while (pageNbr > 0 && !isComplete) { list = RegistryImport.GetDeleted(community, type, startingDate, endingDate, pageNbr, pageSize, ref pTotalRows, ref statusMessage); if (list == null || list.Count == 0) { isComplete = true; if (pageNbr == 1) { importNote = "Deletes: No records where found for date range "; //Console.WriteLine( thisClassName + ".HandleDeletes() - " + importNote ); LoggingHelper.DoTrace(1, thisClassName + ".HandleDeletes() - " + importNote); } break; } foreach (ReadEnvelope item in list) { cntr++; string payload = item.DecodedResource.ToString(); string ctdlType = RegistryServices.GetResourceType(payload); string ctid = RegistryServices.GetCtidFromUnknownEnvelope(item); //may not be available in database, may want to use ctid string envelopeIdentifier = item.EnvelopeIdentifier; string envelopeUrl = RegistryServices.GetEnvelopeUrl(item.EnvelopeIdentifier); LoggingHelper.DoTrace(5, " envelopeUrl: "+ envelopeUrl); LoggingHelper.DoTrace(6, string.Format("{0}. EnvelopeIdentifier: {1} ", cntr, item.EnvelopeIdentifier)); try { //only need the envelopeId and type //so want a full delete, or set EntityStateId to 4 or greater - just as a precaution messages = new List <string>(); status = new SaveStatus(); status.ValidationGroup = "Deletes"; //importError = ""; //each delete method will add an entry to SearchPendingReindex. //at the end of the process, call method to handle all the deletes switch (ctdlType.ToLower()) { case "credentialorganization": case "qacredentialorganization": case "organization": DisplayMessages(string.Format("{0}. Deleting {3} by EnvelopeIdentifier/ctid: {1}/{2} ", cntr, item.EnvelopeIdentifier, ctid, ctdlType)); if (!new OrganizationManager().Delete(envelopeIdentifier, ctid, ref statusMessage)) { DisplayMessages(string.Format(" Delete failed: {0} ", statusMessage)); } break; case "assessmentprofile": DisplayMessages(string.Format("{0}. Deleting Assessment by EnvelopeIdentifier/ctid: {1}/{2} ", cntr, item.EnvelopeIdentifier, ctid)); if (!new AssessmentManager().Delete(envelopeIdentifier, ctid, ref statusMessage)) { DisplayMessages(string.Format(" Delete failed: {0} ", statusMessage)); } break; case "learningopportunityprofile": DisplayMessages(string.Format("{0}. Deleting LearningOpportunity by EnvelopeIdentifier/ctid: {1}/{2} ", cntr, item.EnvelopeIdentifier, ctid)); if (!new LearningOpportunityManager().Delete(envelopeIdentifier, ctid, ref statusMessage)) { DisplayMessages(string.Format(" Delete failed: {0} ", statusMessage)); } break; case "conditionmanifest": DisplayMessages(string.Format("{0}. Deleting ConditionManifest by EnvelopeIdentifier/ctid: {1}/{2} ", cntr, item.EnvelopeIdentifier, ctid)); if (!new ConditionManifestManager().Delete(envelopeIdentifier, ctid, ref statusMessage)) { DisplayMessages(string.Format(" Delete failed: {0} ", statusMessage)); } break; case "costmanifest": DisplayMessages(string.Format("{0}. Deleting CostManifest by EnvelopeIdentifier/ctid: {1}/{2} ", cntr, item.EnvelopeIdentifier, ctid)); if (!new CostManifestManager().Delete(envelopeIdentifier, ctid, ref statusMessage)) { DisplayMessages(string.Format(" Delete failed: {0} ", statusMessage)); } break; case "competencyframework": //CompetencyFramework DisplayMessages(string.Format("{0}. Deleting CompetencyFramework by EnvelopeIdentifier/ctid: {1}/{2} ", cntr, item.EnvelopeIdentifier, ctid)); if (!new EducationFrameworkManager().Delete(envelopeIdentifier, ctid, ref statusMessage)) { DisplayMessages(string.Format(" Delete failed: {0} ", statusMessage)); } break; default: //default to credential DisplayMessages(string.Format("{0}. Deleting Credential ({2}) by EnvelopeIdentifier/ctid: {1}/{3} ", cntr, item.EnvelopeIdentifier, ctdlType, ctid)); if (!new CredentialManager().Delete(envelopeIdentifier, ctid, ref statusMessage)) { DisplayMessages(string.Format(" Delete failed: {0} ", statusMessage)); } break; } } catch (Exception ex) { LoggingHelper.LogError(ex, string.Format("Exception encountered in envelopeId: {0}", item.EnvelopeIdentifier), false, "CredentialFinder Import exception"); //importError = ex.Message; } if (maxRecords > 0 && cntr > maxRecords) { break; } } //foreach ( ReadEnvelope item in list ) pageNbr++; if ((maxRecords > 0 && cntr > maxRecords) || cntr > pTotalRows) { isComplete = true; DisplayMessages(string.Format("Delete EARLY EXIT. Completed {0} records out of a total of {1} ", cntr, pTotalRows)); } } //while //delete from elastic if (cntr > 0) { messages = new List <string>(); ElasticServices.HandlePendingDeletes(ref messages); } importResults = string.Format("HandleDeletes - Processed {0} records, with {1} exceptions. \r\n", cntr, exceptionCtr); if (!string.IsNullOrWhiteSpace(importNote)) { importResults += importNote; } } catch (Exception ex) { LoggingHelper.LogError(ex, "Import.HandleDeletes"); } //actually only attepted at this time, need to account for errors! recordsDeleted = cntr; return(importResults); }
static void Main(string[] args) { //NOTE: consider the IOER approach that all candidate records are first downloaded, and then a separate process does the import LoggingHelper.DoTrace(1, "======================= STARTING IMPORT ======================="); TimeZone zone = TimeZone.CurrentTimeZone; // Demonstrate ToLocalTime and ToUniversalTime. DateTime local = zone.ToLocalTime(DateTime.Now); DateTime universal = zone.ToUniversalTime(DateTime.Now); LoggingHelper.DoTrace(1, "Local time: " + local); LoggingHelper.DoTrace(1, "Universal time: " + universal); //need to determine how to get last start date //may be run multiple times during day, so use a schedule type string scheduleType = UtilityManager.GetAppKeyValue("scheduleType", "daily"); int deleteAction = UtilityManager.GetAppKeyValue("deleteAction", 0); bool doingDownloadOnly = UtilityManager.GetAppKeyValue("DoingDownloadOnly", false); string defaultCommunity = UtilityManager.GetAppKeyValue("defaultCommunity"); string additionalCommunity = UtilityManager.GetAppKeyValue("additionalCommunity"); #region Import Type/Arguments if (args != null) { if (args.Length >= 1) { scheduleType = args[0]; } if (args.Length == 2) { // var altCommunity = args[1]; if (!string.IsNullOrWhiteSpace(altCommunity) && altCommunity.ToLower() == additionalCommunity.ToLower()) { //has to match additional to be valid defaultCommunity = additionalCommunity; } } } RegistryImport registryImport = new RegistryImport(defaultCommunity); string startingDate = DateTime.Now.AddDays(-1).ToString(); //typically will want this as registry server is UTC (+6 hours from central) bool usingUTC_ForTime = UtilityManager.GetAppKeyValue("usingUTC_ForTime", true); string endingDate = ""; string importResults = ""; //could ignore end date until a special scedule type of adhoc is used, then read the dates from config importResults = DisplayMessages(string.Format(" - Schedule type: {0} ", scheduleType)); int minutes = 0; if (Int32.TryParse(scheduleType, out minutes)) { //minutes //may want more flexibility and use input parms if (minutes < 1 || minutes > 1440) //doesn't really matter { DisplayMessages(string.Format("invalid value encountered for Minutes option: {0} - defaulting to 60.", scheduleType)); minutes = 60; } if (usingUTC_ForTime) { //UTC is +6 hours (360 minutes), so subtract entered minutes and add to current time // ex: If -60, want 5 hours (360 - 60) minutes = minutes * -1; //startingDate = DateTime.Now.AddMinutes( minutes ).ToString( "yyyy-MM-ddTHH:mm:ss" ); startingDate = zone.ToUniversalTime(DateTime.Now.AddMinutes(minutes)).ToString("yyyy-MM-ddTHH:mm:ss"); //no end date? endingDate = ""; } else { startingDate = DateTime.Now.AddMinutes(-minutes).ToString("yyyy-MM-ddTHH:mm:ss"); //the server date is UTC, so if we leave enddate open, we will get the same stuff all day, so setting an endate to the current hour endingDate = DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss"); } importResults = importResults + "<br/>" + DisplayMessages(string.Format(" - Community: {0}, Updates since: {1} {2}", defaultCommunity, startingDate, usingUTC_ForTime ? " (UTC)" : "")); } else if (scheduleType == "sinceLastRun") { SiteActivity lastRun = ActivityServices.GetLastImport(); if (usingUTC_ForTime) { startingDate = zone.ToUniversalTime(lastRun.Created).ToString("yyyy-MM-ddTHH:mm:ss"); } else { startingDate = lastRun.Created.ToString("yyyy-MM-ddTHH:mm:ss"); } endingDate = ""; importResults = importResults + "<br/>" + DisplayMessages(string.Format(" - Updates since: {0} {1}", startingDate, usingUTC_ForTime ? " (UTC)" : "")); } else if (scheduleType == "adhoc") { startingDate = UtilityManager.GetAppKeyValue("startingDate", ""); endingDate = UtilityManager.GetAppKeyValue("endingDate", ""); DateTime dtcheck = System.DateTime.Now; //LoggingHelper.DoTrace( 1, string.Format( " - Updates from: {0} to {1} ", startingDate, endingDate ) ); if (usingUTC_ForTime) { if (DateTime.TryParse(startingDate, out dtcheck)) { startingDate = zone.ToUniversalTime(dtcheck).ToString("yyyy-MM-ddTHH:mm:ss"); } if (DateTime.TryParse(endingDate, out dtcheck)) { endingDate = zone.ToUniversalTime(dtcheck).ToString("yyyy-MM-ddTHH:mm:ss"); } //no end date? //endingDate = ""; } importResults = importResults + "<br/>" + DisplayMessages(string.Format(" - Updates from: {0} to {1} for community: {2}", startingDate, endingDate, defaultCommunity)); } else if (scheduleType == "hourly") { if (usingUTC_ForTime) { //6 hour diff, so add 5 hours, equiv to +6 hours - 1 hour startingDate = zone.ToUniversalTime(DateTime.Now.AddHours(-1)).ToString("yyyy-MM-ddTHH:mm:ss"); } else { startingDate = DateTime.Now.AddHours(-1).ToString("yyyy-MM-ddTHH:mm:ss"); //format into: 2016-08-01T23:59:59 //the server date is UTC, so if we leave enddate open, we will get the same stuff all day, so setting an endate to the current hour //HOWEVER - THIS COULD RESULT IN BEING 6 HOURS BEHIND endingDate = DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss"); } //LoggingHelper.DoTrace( 1, string.Format( " - Updates since: {0} ", startingDate ) ); importResults = importResults + "<br/>" + DisplayMessages(string.Format(" - Updates since: {0} {1}, community: {2}", startingDate, usingUTC_ForTime ? " (UTC)" : "", defaultCommunity)); } else { //assume daily startingDate = DateTime.Now.AddDays(-1).ToString("yyyy-MM-ddTHH:mm:ss"); //format into: 2016-08-01T23:59:59 endingDate = ""; //LoggingHelper.DoTrace( 1, string.Format( " - Updates since: {0} ", startingDate ) ); importResults = importResults + "<br/>" + DisplayMessages(string.Format(" - Updates since: {0} ", startingDate)); } #endregion //=================================================================================================== if (!doingDownloadOnly) { LogStart(); } //set to zero to handle all, or a number to limit records to process //partly for testing //although once can sort by date, we can use this, and update the start date int maxImportRecords = UtilityManager.GetAppKeyValue("maxImportRecords", 50); //NOTE - NEED TO REBUILD CACHE TABLES BEFORE BUILDING ELASTIC INDICES //Actions: 0-normal; 1-DeleteOnly; 2-SkipDelete int recordsDeleted = 0; if (deleteAction < 2) { //handle deleted records importResults = importResults + "<br/>" + HandleDeletes(defaultCommunity, startingDate, endingDate, maxImportRecords, ref recordsDeleted); } int recordsImported = 0; if (deleteAction != 1) { //do manifests if (UtilityManager.GetAppKeyValue("importing_condition_manifest_schema", true)) { importResults = importResults + "<br/>" + registryImport.Import("condition_manifest_schema", CodesManager.ENTITY_TYPE_CONDITION_MANIFEST, startingDate, endingDate, maxImportRecords, doingDownloadOnly, ref recordsImported); } // if (UtilityManager.GetAppKeyValue("importing_cost_manifest_schema", true)) { importResults = importResults + "<br/>" + registryImport.Import("cost_manifest_schema", CodesManager.ENTITY_TYPE_COST_MANIFEST, startingDate, endingDate, maxImportRecords, doingDownloadOnly, ref recordsImported); } //handle credentials // if (UtilityManager.GetAppKeyValue("importing_credential", true)) { importResults = importResults + "<br/>" + registryImport.Import("credential", CodesManager.ENTITY_TYPE_CREDENTIAL, startingDate, endingDate, maxImportRecords, doingDownloadOnly, ref recordsImported); } //handle assessments // if (UtilityManager.GetAppKeyValue("importing_assessment_profile", true)) { importResults = importResults + "<br/>" + registryImport.Import("assessment_profile", CodesManager.ENTITY_TYPE_ASSESSMENT_PROFILE, startingDate, endingDate, maxImportRecords, doingDownloadOnly, ref recordsImported); } //handle learning opps // if (UtilityManager.GetAppKeyValue("importing_learning_opportunity_profile", true)) { importResults = importResults + "<br/>" + registryImport.Import("learning_opportunity_profile", CodesManager.ENTITY_TYPE_LEARNING_OPP_PROFILE, startingDate, endingDate, maxImportRecords, doingDownloadOnly, ref recordsImported); } // if (UtilityManager.GetAppKeyValue("importing_competency_frameworks", true)) { importResults = importResults + "<br/>" + new CompetencyFramesworksImport().Import(startingDate, endingDate, maxImportRecords, defaultCommunity, doingDownloadOnly); } //new pathways //if ( UtilityManager.GetAppKeyValue( "importing_pathways", true ) ) // importResults = importResults + "<br/>" + new CompetencyFramesworksImport().Import( startingDate, endingDate, maxImportRecords, doingDownloadOnly ); //handle organizations //might be better to do last, then can populate placeholders, try first // if (UtilityManager.GetAppKeyValue("importing_organization", true)) { importResults = importResults + "<br/>" + registryImport.Import("organization", 2, startingDate, endingDate, maxImportRecords, doingDownloadOnly, ref recordsImported); } if (!doingDownloadOnly && recordsImported > 0) { if (UtilityManager.GetAppKeyValue("processingPendingRecords", true)) { //============================================================== //import pending string pendingStatus = new RegistryServices().ImportPending(); importResults = importResults + "<br/>TODO: add stats from ImportPending."; } } } //=================================================================================================== if (!doingDownloadOnly) { if (recordsImported > 0 || recordsDeleted > 0) { //update elastic if not included - probably will always delay elastic, due to multiple possible updates //may want to move this to services for use by other process, including adhoc imports if (UtilityManager.GetAppKeyValue("delayingAllCacheUpdates", true)) { //update elastic if a elasticSearchUrl exists if (UtilityManager.GetAppKeyValue("elasticSearchUrl") != "") { LoggingHelper.DoTrace(1, string.Format("=== ***************** UpdateElastic ***************** ")); ElasticServices.UpdateElastic(true); } } if (recordsImported > 0) { //set all resolved records in Import_EntityResolution to be resolved. LoggingHelper.DoTrace(1, string.Format("=== ***************** SetAllResolvedEntities ***************** ")); new ImportManager().SetAllResolvedEntities(); } //update code table counts LoggingHelper.DoTrace(1, string.Format("=== ***************** UpdateCodeTableCounts ***************** ")); new CacheManager().UpdateCodeTableCounts(); //send summary email string message = string.Format("<h2>Import Results</h2><p>{0}</p>", importResults); EmailManager.NotifyAdmin(string.Format("Credential Finder Import Results ({0})", envType), message); new ActivityServices().AddActivity(new SiteActivity() { ActivityType = "System", Activity = "Import", Event = "End", Comment = string.Format("Summary: {0} records were imported, {1} records were deleted.", recordsImported, recordsDeleted), SessionId = "batch job", IPAddress = "local" }); } else { new ActivityServices().AddActivity(new SiteActivity() { ActivityType = "System", Activity = "Import", Event = "End", Comment = "No data was found to import", SessionId = "batch job", IPAddress = "local" }); } } //summary, and logging LoggingHelper.DoTrace(1, "======================= all done =============================="); }