internal void RegisterStageConfigSteps(AutoNumbering preConfig, AutoNumbering postConfig) { var types = (from typeQ in xrmContext.PluginTypeSet where typeQ.Name == "Yagasoft.AutoNumbering.Plugins.Target.Plugins.PreCreateTargetAutoNum" || typeQ.Name == "Yagasoft.AutoNumbering.Plugins.Target.Plugins.PostCreateTargetAutoNum" select new PluginType { PluginTypeId = typeQ.PluginTypeId, Name = typeQ.Name }).ToList(); var entityName = (postConfig ?? preConfig)?.EntityLogicalName_ldv_EntityLogicalName; var id = (postConfig ?? preConfig)?.UniqueID; entityName.RequireNotEmpty("Entity Name"); id.RequireNotEmpty("Unique ID"); var createMessage = GetMessage(entityName, "Create"); if (preConfig != null) { foreach (var type in types) { createMessage.PluginTypeId = type.PluginTypeId.GetValueOrDefault(); DeleteExistingSteps(createMessage, id); } } var stage = postConfig?.AutoregisterStepStage; if (stage == null) { log.Log("No stage defined. Exiting ..."); return; } var stageType = types.FirstOrDefault(t => stage == AutoNumbering.AutoregisterStepStageEnum.Preoperation ? t.Name.Contains("PreCreateTargetAutoNum") : t.Name.Contains("PostCreateTargetAutoNum")); if (stageType == null) { throw new InvalidPluginExecutionException($"Couldn't find Auto-numbering plugin type for stage '{stage}'."); } createMessage.PluginTypeId = stageType.PluginTypeId.GetValueOrDefault(); createMessage.TypeName = stageType.Name; createMessage.ExecutionStage = stage == AutoNumbering.AutoregisterStepStageEnum.Preoperation ? SdkMessageProcessingStep.ExecutionStageEnum.Preoperation : SdkMessageProcessingStep.ExecutionStageEnum.Postoperation; CreateStep(createMessage, entityName, 900, id); }
internal AutoNumberingEngine(IOrganizationService service, CrmLog log, AutoNumbering autoNumberConfig, Entity target, Entity image, string orgId, IEnumerable <string> inputParams = null) { this.log = log; this.service = service; this.orgId = orgId; this.autoNumberConfig = autoNumberConfig; isInlineConfig = autoNumberConfig.Id == Guid.Empty; this.target = target; this.image = image; this.inputParams = inputParams; }
internal Result GenerateAndUpdateRecord(bool useService = true, bool isUpdate = false, bool isBackLogged = false) { var autoNumberConfigId = autoNumberConfig.Id; if (autoNumberConfig.FormatString == null) { throw new InvalidPluginExecutionException("Couldn't find a format string in the auto-numbering configuration."); } var updatedAutoNumbering = new AutoNumbering { Id = autoNumberConfigId }; // generate a string, and make sure it's unique var field = autoNumberConfig.FieldLogicalName?.Trim(); var result = GenerateUniqueString(isUpdate, updatedAutoNumbering, field); log.Log($"Final auto-number: {result}"); // if target and field exist, then user wants to update the record if (target != null && field != null) { log.Log($"Adding generated number: '{result.GeneratedString}', to field: '{field}' ..."); if (useService) { var updatedTarget = new Entity(target.LogicalName) { Id = target.Id, [field] = result.GeneratedString }; service.Update(updatedTarget); } else { target[field] = result.GeneratedString; } } if (!isInlineConfig && !isBackLogged) { log.Log($"Updating auto-numbering with index {updatedAutoNumbering.CurrentIndex} ..."); // set the new dates and index in the auto-numbering record service.Update(updatedAutoNumbering); } return(result); }
private Result GenerateUniqueString(bool isUpdate, AutoNumbering updatedAutoNumbering, string field = null) { var generatedString = ""; bool isUnique; var iterations = 1; Result result; if (autoNumberConfig.ValidateUniqueString != false) { if (field == null) { throw new InvalidPluginExecutionException( "To generate a unique string, a target field must be specified in the config record."); } if (target == null) { throw new InvalidPluginExecutionException( "To generate a unique string, a target must be passed as a parameter to the execution."); } } do { if (iterations > 10) { throw new InvalidPluginExecutionException($"Couldn't generate a unique random string => \"{generatedString}\""); } result = GenerateString(isUpdate, updatedAutoNumbering); generatedString = result.GeneratedString; log.Log($"Generated string: {generatedString}", LogLevel.Debug); isUnique = autoNumberConfig.ValidateUniqueString != false && field != null && target != null && new OrganizationServiceContext(service) .CreateQuery(target.LogicalName) .Where(targetQ => (string)targetQ[field] == generatedString) .Select(targetQ => targetQ[field]) .ToList().Count <= 0; iterations++; }while (autoNumberConfig.ValidateUniqueString != false && !isUnique); log.Log($"Accepted generated string: {generatedString}"); return(result); }
/// <summary> /// A plug-in that creates a follow-up task activity when a new account is created. /// </summary> /// <remarks>Register this plug-in on the Create message, account entity, /// and asynchronous mode. /// </remarks> public void Execute(IServiceProvider serviceProvider) { //Extract the tracing service for use in debugging sandboxed plug-ins. ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService)); // Obtain the execution context from the service provider. IPluginExecutionContext context = (IPluginExecutionContext) serviceProvider.GetService(typeof(IPluginExecutionContext)); IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory)); var service = serviceFactory.CreateOrganizationService(context.UserId); // The InputParameters collection contains all the data passed in the message request. if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity) { // Obtain the target entity from the input parameters. Entity entity = (Entity)context.InputParameters["Target"]; if (entity.LogicalName != "gcbase_client") { return; } //FaultException ex1 = new FaultException(); //throw new InvalidPluginExecutionException("test", ex1); AutoNumbering autoNumbering = new AutoNumbering(entity, service); String clientId = autoNumbering.getAutoNumber(); try { entity["gcbase_name"] = clientId; } catch (FaultException <OrganizationServiceFault> ex) { throw new InvalidPluginExecutionException("An error occurred in the PreClientCreate plug-in.", ex); } catch (Exception ex) { tracingService.Trace("FollowupPlugin: {0}", ex.ToString()); throw; } } }
private int ProcessIndex(Match match, bool isReset, int resetValue, bool isUpdate, AutoNumbering updatedAutoNumbering) { var fieldName = match.Groups[1].Value; var fieldValue = match.Groups[2].Value; var isDefaultIndex = !fieldName.IsNotEmpty(); var currentIndex = 0; AutoNumberingStream stream = null; if (isDefaultIndex) { log.Log("Using default index."); currentIndex = autoNumberConfig.CurrentIndex.GetValueOrDefault(); } else if (match.Success) { fieldValue = fieldValue.IsNotEmpty() ? fieldValue : Libraries.Common.CrmHelpers.GetAttributeStringValue(image.GetAttributeValue <object>(fieldName)); log.Log($"Parsing stream '{match.Value}' ..."); log.Log($"Field name: {fieldName}"); log.Log($"Field value: {fieldValue}"); log.Log($"Retrieving stream ..."); stream = (from s in new XrmServiceContext(service) { MergeOption = MergeOption.NoTracking }.AutoNumberingStreamSet where s.FieldName == fieldName && s.FieldValue == fieldValue && s.AutoNumberingConfig == autoNumberConfig.Id select new AutoNumberingStream { Id = s.Id, CurrentIndex = s.CurrentIndex }).FirstOrDefault(); if (stream == null) { log.Log($"Couldn't find stream."); stream = new AutoNumberingStream { CurrentIndex = 0, FieldName = fieldName, FieldValue = fieldValue, AutoNumberingConfig = autoNumberConfig.Id }; log.Log("Creating new stream ..."); stream.Id = service.Create(stream); log.Log("Finished creating new stream."); } currentIndex = stream.CurrentIndex.GetValueOrDefault(); } log.Log($"Current index: {currentIndex}."); // if invalid value, reset // if updating and not incrementing, then keep index, else increment index var index = currentIndex <= 0 ? 1 : (isUpdate && autoNumberConfig.IncrementOnUpdate != true ? currentIndex : currentIndex + 1); if (isReset) { index = resetValue; } log.Log($"New index: {index}."); if (isDefaultIndex) { updatedAutoNumbering.CurrentIndex = index; } else if (stream != null) { log.Log($"Updating stream with new index ..."); service.Update( new AutoNumberingStream { Id = stream.Id, CurrentIndex = index }); log.Log($"Finished updating stream with new index."); } return(index); }
private string ProcessIndices(string generatedString, int padding, bool isUpdate, AutoNumbering updatedAutoNumbering) { #region Date stuff var resetInterval = autoNumberConfig.ResetInterval; var resetDate = autoNumberConfig.ResetDate; var lastResetDate = autoNumberConfig.LastResetDate; var isReset = false; var resetValue = 0; // if index reset config is set, and the time has passed, then reset index to value set if (resetDate != null && (resetInterval != AutoNumbering.ResetIntervalEnum.Never && DateTime.UtcNow >= resetDate.Value && (lastResetDate == null || lastResetDate < resetDate))) { lastResetDate = resetDate; // add the interval to the reset date switch (resetInterval) { case AutoNumbering.ResetIntervalEnum.Yearly: resetDate = resetDate.Value.AddYears(1); break; case AutoNumbering.ResetIntervalEnum.Monthly: resetDate = resetDate.Value.AddMonths(1); break; case AutoNumbering.ResetIntervalEnum.Daily: resetDate = resetDate.Value.AddDays(1); break; case AutoNumbering.ResetIntervalEnum.Once: case AutoNumbering.ResetIntervalEnum.Never: break; default: throw new InvalidPluginExecutionException("Interval does not exist in code. Please contact the administrator."); } isReset = true; resetValue = autoNumberConfig.ResetIndex ?? 0; } if (resetInterval == AutoNumbering.ResetIntervalEnum.Never) { resetDate = null; } #endregion generatedString = Regex.Replace(generatedString, @"{!index!(?:(\w+?)(?::(.*?))?)?}", match => { var index = ProcessIndex(match, isReset, resetValue, isUpdate, updatedAutoNumbering); return(index.ToString().PadLeft(padding, '0')); }); updatedAutoNumbering.ResetDate = resetDate; updatedAutoNumbering.LastResetDate = lastResetDate; return(generatedString); }
private Result GenerateString(bool isUpdate, AutoNumbering updatedAutoNumbering) { var parser = new Parser(service, image, log, autoNumberConfig.Owner.Id, orgId, cachedValues); log.Log("Preparing attribute variables ..."); var generatedString = parser.ParseAttributeVariables(autoNumberConfig.FormatString ?? ""); log.Log($"Generated string: {generatedString}"); if (!isInlineConfig) { if (Regex.Matches(generatedString, @"{!param!.+?}").Count > 0) { log.Log("Preparing param variables ..."); generatedString = parser.ParseParamVariables(generatedString, inputParams); log.Log($"Generated string: {generatedString}"); } } if (!isInlineConfig) { log.Log("Preparing random string variables ..."); if (autoNumberConfig.IsRandomLetterStart == null || autoNumberConfig.IsNumberLetterRatio == null) { throw new InvalidPluginExecutionException( "Couldn't find a setting for the ratio or letter start in the auto-numbering configuration."); } } generatedString = parser.ParseRandomStringVariables(generatedString, autoNumberConfig.IsRandomLetterStart == true, (autoNumberConfig.IsNumberLetterRatio == true && autoNumberConfig.NumberLetterRatio != null) ? autoNumberConfig.NumberLetterRatio.Value : -1); log.Log($"Generated string: {generatedString}"); log.Log("Preparing date variables ..."); generatedString = parser.ParseDateVariables(generatedString); log.Log($"Generated string: {generatedString}"); if (!isInlineConfig) { log.Log("Preparing index ..."); log.Log("Preparing padding ..."); if (autoNumberConfig.IndexPadding == null) { throw new InvalidPluginExecutionException("Couldn't find the padding in the auto-numbering configuration."); } var padding = autoNumberConfig.IndexPadding >= 0 ? autoNumberConfig.IndexPadding : 0; log.Log("Preparing autonumber variable ..."); generatedString = ProcessIndices(generatedString, padding.Value, isUpdate, updatedAutoNumbering); log.Log($"Generated string: {generatedString}"); } if (!isInlineConfig && !string.IsNullOrEmpty(autoNumberConfig.ReplacementCharacters)) { log.Log("Replacing characters ..."); var pairs = autoNumberConfig.ReplacementCharacters.Split(';').Select(e => e.Split(',')).ToArray(); if (pairs.Any(e => e.Length < 2)) { throw new InvalidPluginExecutionException( $"Replacement Characters' config is invalid: {autoNumberConfig.ReplacementCharacters}."); } foreach (var pair in pairs) { generatedString = Regex.Replace(generatedString, pair[0], pair[1]); } log.Log($"Generated string: {generatedString}"); } return (new Result { Index = updatedAutoNumbering.CurrentIndex.GetValueOrDefault(), IndexString = updatedAutoNumbering.CurrentIndex.GetValueOrDefault().ToString(), GeneratedString = generatedString }); }
/// <summary> /// A plug-in that creates a follow-up task activity when a new account is created. /// </summary> /// <remarks>Register this plug-in on the Create message, account entity, /// and asynchronous mode. /// </remarks> public void Execute(IServiceProvider serviceProvider) { //Extract the tracing service for use in debugging sandboxed plug-ins. ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService)); // Obtain the execution context from the service provider. IPluginExecutionContext context = (IPluginExecutionContext) serviceProvider.GetService(typeof(IPluginExecutionContext)); // The InputParameters collection contains all the data passed in the message request. if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity) { // Obtain the target entity from the input parameters. Entity entity = (Entity)context.InputParameters["Target"]; if (entity.LogicalName != "gcbase_fundingcase") { return; } FaultException ex1 = new FaultException(); // throw new InvalidPluginExecutionException("test", ex1); try { //// Obtain the organization service reference. IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory)); IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId); AutoNumbering autoNumbering = new AutoNumbering(entity, service); String caseNumber = autoNumbering.getAutoNumber(); entity["gcbase_name"] = caseNumber; service.Update(entity); if (entity.Attributes.Contains("gcbase_amountsbyfiscalyearserver")) { char[] delimitedChar = { ';' }; Entity fundingAmountByFY = new Entity("gcbase_fundingcaseamountbyfy"); string[] yearlyAmounts = entity.Attributes["gcbase_amountsbyfiscalyearserver"].ToString().Split(delimitedChar); EntityReference fundCentre = entity.GetAttributeValue <EntityReference>("gcbase_program"); foreach (string ya in yearlyAmounts) { fundingAmountByFY["gcbase_fundingcase"] = new EntityReference("gcbase_fundingcase", entity.Id); //fys[index] = (string)Enum.GetName(typeof(goal_fiscalyear), year); OptionSetValue fy = new OptionSetValue(); var indexForFY = ya.IndexOf("Y"); var indexForAmount = ya.IndexOf("-"); var yearStr = ya.Substring(indexForFY + 1, 4); var amountStr = ya.Substring(indexForAmount + 1); tracingService.Trace("year is:" + yearStr); tracingService.Trace("amount is:" + amountStr); Money amount = new Money(decimal.Parse(amountStr)); fy.Value = Int32.Parse(yearStr); fundingAmountByFY["gcbase_fiscalyear"] = fy; fundingAmountByFY["gcbase_amount"] = amount; fundingAmountByFY["gcbase_fundcentre"] = fundCentre; tracingService.Trace("PostFundingCasePlugin: Creating the budget item."); service.Create(fundingAmountByFY); tracingService.Trace(ya); } } if (entity.Attributes.Contains("gcbase_program")) { ColumnSet cols = new ColumnSet ( new String[] { "gcbase_fundingcaseriskrequired" } ); //program configuration options var program = service.Retrieve("gcbase_fundcentre", entity.GetAttributeValue <EntityReference>("gcbase_program").Id, cols); tracingService.Trace("there"); if (program.GetAttributeValue <Boolean>("gcbase_fundingcaseriskrequired")) { var ratype = new OptionSetHelper().getIndexOfLabel("gcbase_fundingcaseriskassessment", "gcbase_fundingcaseriskassessmenttype", "Initial", service); OptionSetValue raTypeOpt = new OptionSetValue(ratype); //create initial risk assessment - should be custom class since this will be reused by other plugins if (!new RiskTemplate(null, service).generateRiskAssessment(entity, raTypeOpt)) { throw new InvalidPluginExecutionException("The funding program is not fully configured therefore a funding case cannot be created yet", ex1); } //newRA.generateAssessment(); } //var results = service.Retrieve("gcbase_fundcentre", entity.GetAttributeValue<Guid>("gcbase_program"), null); } } catch (FaultException <OrganizationServiceFault> ex) { throw new InvalidPluginExecutionException("An error occurred in the FollowupPlugin plug-in.", ex); } catch (Exception ex) { tracingService.Trace("FollowupPlugin: {0}", ex.ToString()); throw; } } }
internal static AutoNumbering GetAutoNumberingConfig(Entity target, string config, IPluginExecutionContext context, IOrganizationService service, CrmLog log, out bool isBackLogged) { var xrmContext = new XrmServiceContext(service) { MergeOption = MergeOption.NoTracking }; var configIds = config.Split(',').Select(item => item.Trim()).ToArray(); var isInlineConfig = config.Contains(";;"); AutoNumbering autoNumberConfig = null; if (isInlineConfig) { autoNumberConfig = GetInlineConfig(config, context.UserId); } // get it once to check for generator field update below log.Log("Getting auto-numbering config ..."); // if a condition is found in any of the configs, then don't throw an error if none match // it simply means that the user wants the auto-numbering to work only if the condition is satisified // this is useful for multiple fields var isConditioned = false; // if using a backlog, then no need to lock isBackLogged = false; if (!isInlineConfig) { var autoNumberConfigTemp = GetBackloggedConfig(context, service, log); if (autoNumberConfigTemp == null) { foreach (var configId in configIds) { autoNumberConfigTemp = (from autoNumberQ in xrmContext.AutoNumberingSet where autoNumberQ.UniqueID == configId || autoNumberQ.Name == configId && autoNumberQ.Status == AutoNumbering.StatusEnum.Active select autoNumberQ).FirstOrDefault(); if (autoNumberConfigTemp == null) { continue; } if (autoNumberConfigTemp.Condition != null) { isConditioned = true; log.Log($"Checking condition for '{autoNumberConfigTemp.Name}':'{autoNumberConfigTemp.Id}' ..."); var parsedCondition = ParseAttributeVariables(service, autoNumberConfigTemp.Condition, target, context.UserId, context.OrganizationId.ToString()); var isConditionMet = IsConditionMet(service, parsedCondition, target.ToEntityReference(), context.OrganizationId.ToString()); if (isConditionMet) { log.Log("Condition met for auto-numbering record."); autoNumberConfig = autoNumberConfigTemp; break; } log.Log("Condition not met for auto-numbering record."); } else if (autoNumberConfig == null) { autoNumberConfig = autoNumberConfigTemp; } } } else { autoNumberConfig = autoNumberConfigTemp; isBackLogged = true; } } return(PreValidation(service, target, autoNumberConfig, log, isConditioned, isBackLogged)); }
internal static int GetNextIndex(AutoNumbering autoNumberConfig, AutoNumbering updatedAutoNumbering) { #region Date stuff var resetInterval = autoNumberConfig.ResetInterval; var resetDate = autoNumberConfig.ResetDate; var lastResetDate = autoNumberConfig.LastResetDate; var isReset = false; var resetValue = 0; // if index reset config is set, and the time has passed, then reset index to value set if (resetDate != null && (resetInterval != AutoNumbering.ResetIntervalEnum.Never && DateTime.UtcNow >= resetDate.Value && (lastResetDate == null || lastResetDate < resetDate))) { lastResetDate = resetDate; // add the interval to the reset date switch (resetInterval) { case AutoNumbering.ResetIntervalEnum.Yearly: resetDate = resetDate.Value.AddYears(1); break; case AutoNumbering.ResetIntervalEnum.Monthly: resetDate = resetDate.Value.AddMonths(1); break; case AutoNumbering.ResetIntervalEnum.Daily: resetDate = resetDate.Value.AddDays(1); break; case AutoNumbering.ResetIntervalEnum.Once: case AutoNumbering.ResetIntervalEnum.Never: break; default: throw new InvalidPluginExecutionException("Interval does not exist in code. Please contact the administrator."); } isReset = true; resetValue = autoNumberConfig.ResetIndex ?? 0; } if (resetInterval == AutoNumbering.ResetIntervalEnum.Never) { resetDate = null; } #endregion var currentIndex = autoNumberConfig.CurrentIndex.GetValueOrDefault(); // if invalid value, reset // if updating and not incrementing, then keep index, else increment index var index = currentIndex <= 0 ? 1 : currentIndex + 1; if (isReset) { index = resetValue; } updatedAutoNumbering.ResetDate = resetDate; updatedAutoNumbering.LastResetDate = lastResetDate; return(index); }
internal static AutoNumbering PreValidation(IOrganizationService service, Entity target, AutoNumbering autoNumberingConfig, CrmLog log, bool isConditioned, bool isBackLogged) { if (autoNumberingConfig == null) { // condition satisfaction failed before, so there's nothing to do here if (isConditioned) { return(null); } throw new InvalidPluginExecutionException("Couldn't find an auto-numbering configuration."); } // if the auto-numbering is inactive, then don't apply if (autoNumberingConfig.Status == AutoNumbering.StatusEnum.Inactive) { //throw new InvalidPluginExecutionException("Autonumbering config record is inactive."); log.Log("AutoNumbering record is inactive."); return(null); } // exit if auto-number field is updating to prevent looping if (target != null && autoNumberingConfig.FieldLogicalName != null && target.Contains(autoNumberingConfig.FieldLogicalName)) { log.Log("Numbering is in progress in another instance."); return(null); } if (autoNumberingConfig.Id == Guid.Empty) { log.Log("Using inline config."); return(autoNumberingConfig); } if (autoNumberingConfig.Condition != null && autoNumberingConfig.EntityLogicalName_ldv_EntityLogicalName == null) { throw new InvalidPluginExecutionException("Condition is set but entity name is not set in auto-numbering config."); } // only lock if an index is needed if (autoNumberingConfig.FormatString.Contains("{!index!}") && !isBackLogged) { log.Log("Locking ...", LogLevel.Debug); // ensure locking service.Update( new AutoNumbering { Id = autoNumberingConfig.Id, Locking = new Random().Next(999999, 999999999).ToString() }); log.Log("Refetching numbering record ...", LogLevel.Debug); // get it again to ensure locking took effect var currentIndex = (from autoNumberQ in new XrmServiceContext(service).AutoNumberingSet where autoNumberQ.AutoNumberingId == autoNumberingConfig.Id && autoNumberQ.Status == AutoNumbering.StatusEnum.Active select autoNumberQ.CurrentIndex).First(); autoNumberingConfig.CurrentIndex = currentIndex; } return(autoNumberingConfig); }
/// <summary> /// Default constructor that setup the attribute type /// </summary> public DocumentContextInterpreter() { Numbering = new AutoNumbering(); ShapeManager = new ContextShapeManager(); ActiveSketch = -1; }
private void AllocateBacklog(AutoNumbering config) { var triggerId = config.TriggerID; var index = config.CurrentIndex; var threshold = config.BacklogThreshold; var backlogEntry = new AutoNumberingBacklog { TriggerID = triggerId, AutoNumberingConfig = config.Id, }; // get an old backLog, if not, then create a new one if (threshold.HasValue) { var queryXml = $@"<fetch top='1' > <entity name='ldv_autonumberingbacklog' > <attribute name='ldv_autonumberingbacklogid' /> <attribute name='ldv_indexvalue' /> <attribute name='ldv_triggerid' /> <filter> <condition attribute='modifiedon' operator='olderthan-x-minutes' value='{threshold.Value}' /> <condition attribute='ldv_autonumberingconfigid' operator='eq' value='{config.Id}' /> </filter> <order attribute='ldv_indexvalue' /> </entity> </fetch>"; Log.LogDebug("Query XML", queryXml); Log.Log($"Retrieving first old backlog entry older than {threshold.Value} ..."); var backlogEntryTemp = Service.RetrieveMultiple(new FetchExpression(queryXml)).Entities.FirstOrDefault(); Log.Log($"Finished retrieving first old backlog entry."); if (backlogEntryTemp == null) { Log.Log($"Couldn't find any old backlog entries."); var updatedAutoNumbering = new AutoNumbering { Id = config.Id }; backlogEntry.IndexValue = Helper.GetNextIndex(config, updatedAutoNumbering); Log.Log("Incrementing auto-numbering config's index ..."); Service.Update(updatedAutoNumbering); Log.Log("Finished incrementing auto-numbering config's index."); } else { backlogEntry = backlogEntryTemp.ToEntity <AutoNumberingBacklog>(); } } backlogEntry.TriggerID = triggerId; backlogEntry.KeyAttributes.Add(AutoNumberingBacklog.Fields.TriggerID, triggerId); Log.Log($"Upserting backlog with trigger ID '{triggerId}' and index {index} ..."); Service.Execute( new UpsertRequest { Target = backlogEntry }); Log.Log($"Finished Upserting backLog."); }