public async Task <IHttpActionResult> CreateProtocol( int customerId, CreateProtocolRequestDto request ) { var result = await protocolsControllerHelper.CreateProtocol(customerId, request); if (!result.Status.HasFlag(CreateUpdateProtocolStatus.Success)) { return(Content( HttpStatusCode.BadRequest, new ErrorResponseDto() { Error = ErrorCode.InvalidRequest, Message = ErrorCode.InvalidRequest.Description(), Details = result.Status.GetConcatString() } )); } return(Created( new Uri(Request.RequestUri, result.Content.ToString()), new PostResponseDto <Guid> { Id = result.Content } )); }
/// <summary> /// Creates the protocol. /// </summary> /// <param name="protocol">The protocol.</param> /// <returns></returns> public async Task <PostResponseDto <Guid> > CreateProtocol(CreateProtocolRequestDto protocol) { var token = authDataStorage.GetToken(); var result = await healthLibraryService .CreateProtocol(token, CustomerContext.Current.Customer.Id, protocol); return(result); }
/// <summary> /// Creates the protocol. /// </summary> /// <param name="customerId"></param> /// <param name="request">The request.</param> /// <returns></returns> public async Task <OperationResultDto <Guid, CreateUpdateProtocolStatus> > CreateProtocol( int customerId, CreateProtocolRequestDto request ) { #region Step 1 - Client IDs validation var validationResult = PerformValidationStep1(request); if (!validationResult.HasFlag(CreateUpdateProtocolStatus.Success)) { return(new OperationResultDto <Guid, CreateUpdateProtocolStatus>() { Status = validationResult }); } #endregion #region Step 2 - Remaining Validation which can be made only after successfuly passed step 1 validationResult = await PerformValidationStep2(request); if (!validationResult.HasFlag(CreateUpdateProtocolStatus.Success)) { return(new OperationResultDto <Guid, CreateUpdateProtocolStatus>() { Status = validationResult }); } #endregion var protocol = await BuildProtocol(customerId, request); var createdProtocol = await protocolService.CreateProtocol(protocol); await globalSearchCacheHelper.AddOrUpdateEntry(customerId, Mapper.Map <Protocol, SearchEntryDto>(protocol)); await tagsSearchCacheHelper.AddOrUpdateTags(customerId, createdProtocol.Tags.Select(t => t.Name).ToList()); var unusedTags = await tagsService.RemoveUnusedTags(customerId); await tagsSearchCacheHelper.RemoveTags(customerId, unusedTags); return(new OperationResultDto <Guid, CreateUpdateProtocolStatus>() { Content = createdProtocol.Id, Status = validationResult }); }
/// <summary> /// Creates the protocol. /// </summary> /// <param name="token">The token.</param> /// <param name="customerId">The customer identifier.</param> /// <param name="protocol">The protocol.</param> /// <returns></returns> public async Task <PostResponseDto <Guid> > CreateProtocol(string token, int customerId, CreateProtocolRequestDto protocol) { var result = await healthLibraryDataProvider.CreateProtocol(token, customerId, protocol); return(result); }
public async Task <ActionResult> CreateProtocol(CreateProtocolRequestDto request) { var result = await careBuilderManager.CreateProtocol(request); return(Json(result)); }
/// <summary> /// Builds the protocol. /// </summary> /// <param name="customerId"></param> /// <param name="request">The request.</param> /// <returns></returns> private async Task <Protocol> BuildProtocol(int customerId, CreateProtocolRequestDto request) { var protocol = new Protocol { CustomerId = customerId, NameLocalizedStrings = new List <ProtocolString>() { new ProtocolString() { Value = request.Name, Language = careElementContext.DefaultLanguage } }, IsPrivate = request.IsPrivate, Tags = await tagsService.BuildTagsList(customerId, request.Tags), ProtocolElements = new List <ProtocolElement>() }; foreach (var protocolElementDto in request.ProtocolElements) { var protocolElement = new ProtocolElement { Id = protocolElementDto.Id, // Temporary storing client id to build up relationships and dump it before saving to the database ElementId = protocolElementDto.ElementId, Sort = protocolElementDto.Sort, Branches = new List <Branch>(), Alerts = new List <Alert>() }; if (protocolElementDto.Branches != null) { foreach (var branchDto in protocolElementDto.Branches) { if (branchDto.Conditions != null) { var branch = new Branch() { NextProtocolElementId = branchDto.NextProtocolElementId, ThresholdAlertSeverityId = branchDto.ThresholdAlertSeverityId, Conditions = new List <Condition>() }; foreach (var conditionDto in branchDto.Conditions) { var condition = new Condition() { Operand = conditionDto.Operand, Operator = conditionDto.Operator, Value = conditionDto.Value }; branch.Conditions.Add(condition); } protocolElement.Branches.Add(branch); } } } if (protocolElementDto.Alerts != null) { foreach (var alertDto in protocolElementDto.Alerts) { if (alertDto.Conditions != null) { var alert = new Alert() { Conditions = new List <Condition>() }; foreach (var conditionDto in alertDto.Conditions) { var condition = new Condition() { Operand = conditionDto.Operand, Operator = conditionDto.Operator, Value = conditionDto.Value }; alert.Conditions.Add(condition); } alert.AlertSeverityId = alertDto.AlertSeverityId; protocolElement.Alerts.Add(alert); } } } protocol.ProtocolElements.Add(protocolElement); } // Assigning FirstProtocolElement var firstProtocolElement = protocol.ProtocolElements.Single(pe => pe.Id == request.FirstProtocolElementId); firstProtocolElement.IsFirstProtocolElement = true; // Assigning NextProtocolElements and removing client Ids foreach (var protocolElement in protocol.ProtocolElements) { var nextProtocolElementIdForProtocolElement = request.ProtocolElements.Single(pe => pe.Id == protocolElement.Id).NextProtocolElementId; if (nextProtocolElementIdForProtocolElement != null) { protocolElement.NextProtocolElement = protocol.ProtocolElements.Single(pe => pe.Id == nextProtocolElementIdForProtocolElement); } foreach (var branch in protocolElement.Branches.Where(b => b.NextProtocolElementId != null)) { branch.NextProtocolElement = protocol.ProtocolElements.Single(pe => pe.Id == branch.NextProtocolElementId); branch.NextProtocolElementId = null; // Removing client Id } } foreach (var protocolElement in protocol.ProtocolElements) { protocolElement.Id = default(Guid); // Removing client Id } return(protocol); }
/// <summary> /// Validation, which depends on data retrieved from the database. /// </summary> /// <param name="request">The request.</param> /// <returns></returns> private async Task <CreateUpdateProtocolStatus> PerformValidationStep2(CreateProtocolRequestDto request) { // Validating that ElementIds provided in the request correspond to existing Elements in the database var elementIds = request .ProtocolElements .Select(pe => pe.ElementId) .Distinct() .ToList(); var existingElements = await protocolService.GetElementsByIds(elementIds); if (existingElements.Count != elementIds.Count) { return(CreateUpdateProtocolStatus.OneOfElementIdsInvalid); } // Validating that ProtocolElement associated with particular Element have conditions with appropriate Operand based on ElementType foreach (var protocolElement in request.ProtocolElements) { var alertConditions = protocolElement.Alerts != null && protocolElement.Alerts.Any() ? protocolElement.Alerts.SelectMany(b => b.Conditions).ToList() : new List <ConditionDto>(); var branchConditions = protocolElement.Branches != null && protocolElement.Branches.Any() ? protocolElement.Branches.SelectMany(b => b.Conditions).ToList() : new List <ConditionDto>(); var conditions = alertConditions.Concat(branchConditions).ToList(); if (conditions.Any()) { var associatedElement = existingElements.SingleOrDefault(e => e.Id == protocolElement.ElementId); if (associatedElement != null) { if (associatedElement is QuestionElement) { var questionElement = (QuestionElement)associatedElement; if (questionElement.AnswerSet is SelectionAnswerSet) { Guid tempGuid; var selectionAnswerSet = questionElement.AnswerSet as SelectionAnswerSet; if (conditions.Any(c => c.Operand != OperandType.SelectionAnswerChoice || !Guid.TryParse(c.Value, out tempGuid) || !selectionAnswerSet.SelectionAnswerChoices.Select(ac => ac.Id).Contains(Guid.Parse(c.Value))) ) { return(CreateUpdateProtocolStatus.OneOfBranchesOrAlertsInproperlyFilledIn); } } if (questionElement.AnswerSet is ScaleAnswerSet) { if (conditions.Any(c => c.Operand != OperandType.ScaleAnswerSet)) { return(CreateUpdateProtocolStatus.OneOfBranchesOrAlertsInproperlyFilledIn); } } } if (associatedElement is MeasurementElement) { if (conditions.Any(c => c.Operand == OperandType.SelectionAnswerChoice || c.Operand == OperandType.ScaleAnswerSet)) { return(CreateUpdateProtocolStatus.OneOfBranchesOrAlertsInproperlyFilledIn); } } if (associatedElement is TextMediaElement) { return(CreateUpdateProtocolStatus.OneOfBranchesOrAlertsInproperlyFilledIn); } } } } return(CreateUpdateProtocolStatus.Success); }
/// <summary> /// Validation, which doesn't depend on data retrieved from the database. /// </summary> /// <param name="request">The request.</param> /// <returns></returns> private CreateUpdateProtocolStatus PerformValidationStep1(CreateProtocolRequestDto request) { CreateUpdateProtocolStatus validationResult = 0; var validProtocolElementClientIds = request.ProtocolElements.Select(e => e.Id).ToList(); // Validating FirstProtocolElementClientId if (validProtocolElementClientIds.All(e => e != request.FirstProtocolElementId)) { validationResult |= CreateUpdateProtocolStatus.FirstProtocolElementClientIdInvalid; } // Validating that ProtocolElements list contains only unique ProtocolElements if (request.ProtocolElements.Count != request.ProtocolElements.Select(pe => pe.Id).Distinct().Count()) { validationResult |= CreateUpdateProtocolStatus.ProtocolElementsListShouldBeDistinct; } // Validating NextProtocolElementClientId inside ProtocolElements foreach (var protocolElement in request.ProtocolElements) { if (protocolElement.NextProtocolElementId != null && validProtocolElementClientIds.All(e => e != protocolElement.NextProtocolElementId)) { validationResult |= CreateUpdateProtocolStatus.OneOfNextProtocolElementClientIdsInProtocolElementsInvalid; } if (protocolElement.Branches != null) { // Validating NextProtocolElementClientId inside Branches if (protocolElement.Branches .Where(b => b.NextProtocolElementId != null) .Any(b => validProtocolElementClientIds.All(e => e != b.NextProtocolElementId))) { validationResult |= CreateUpdateProtocolStatus.OneOfNextProtocolElementClientIdsInBranchesInvalid; } } // Validating that each ProtocolElement should be used within the protocol // It means that ProtocolElement should be referenced at least as FirstProtocolElement or NextProtocolElement var protocolElementClientId = protocolElement.Id; if (!(request.FirstProtocolElementId == protocolElementClientId || request.ProtocolElements.Any(pe => pe.NextProtocolElementId == protocolElementClientId) || request.ProtocolElements.Where(pe => pe.Branches != null).SelectMany(pe => pe.Branches).Any(b => b.NextProtocolElementId == protocolElementClientId))) { validationResult |= CreateUpdateProtocolStatus.OneOfProtocolElementsIsNotUsedWithinProtocol; } } // Validating that ProtocolElement (or it's branches) shouldn't point to itself if (request.ProtocolElements.Any(pe => pe.NextProtocolElementId == pe.Id) || request.ProtocolElements.Where(pe => pe.Branches != null).Any(pe => pe.Branches.Any(b => b.NextProtocolElementId == pe.Id))) { validationResult |= CreateUpdateProtocolStatus.ProtocolElementShouldNotPointToItself; } // Validating that branch should have at least one condition // and also that branch should contain conditions with operands related with ONLY measurements OR ONLY answer sets OR ONLY answer choices var branches = request.ProtocolElements.Where(pe => pe.Branches != null).SelectMany(pe => pe.Branches).ToList(); if (!branches.All(b => b.Conditions != null && b.Conditions.Any() && !(b.Conditions.Any(c => c.Operand == OperandType.ScaleAnswerSet) && b.Conditions.Any(c => c.Operand != OperandType.ScaleAnswerSet)) && !(b.Conditions.Any(c => c.Operand == OperandType.SelectionAnswerChoice) && b.Conditions.Any(c => c.Operand != OperandType.SelectionAnswerChoice)))) { validationResult |= CreateUpdateProtocolStatus.OneOfBranchesOrAlertsInproperlyFilledIn; } // Validating that Alert should have at least one Condition // and also that alert should contain conditions with operands related with ONLY measurements OR ONLY answer sets OR ONLY answer choices var alerts = request.ProtocolElements.Where(pe => pe.Alerts != null).SelectMany(pe => pe.Alerts).ToList(); if (!alerts.All(a => a.Conditions != null && a.Conditions.Any() && !(a.Conditions.Any(c => c.Operand == OperandType.ScaleAnswerSet) && a.Conditions.Any(c => c.Operand != OperandType.ScaleAnswerSet)) && !(a.Conditions.Any(c => c.Operand == OperandType.SelectionAnswerChoice) && a.Conditions.Any(c => c.Operand != OperandType.SelectionAnswerChoice)))) { validationResult |= CreateUpdateProtocolStatus.OneOfBranchesOrAlertsInproperlyFilledIn; } // Validating that conditions with Operand == ScaleAnswerSet have decimal value // Conditions from Branches var scaleAnswerChoiceStrings = request .ProtocolElements .Where(pe => pe.Branches != null) .SelectMany(pe => pe.Branches) .Where(b => b.Conditions != null && b.Conditions.All(c => c.Operand == OperandType.ScaleAnswerSet)) .SelectMany(b => b.Conditions) .Select(c => c.Value) .Distinct() .ToList(); // Adding Conditions from Alerts scaleAnswerChoiceStrings.AddRange( request .ProtocolElements .Where(pe => pe.Alerts != null) .SelectMany(pe => pe.Alerts) .Where(a => a.Conditions != null && a.Conditions.All(c => c.Operand == OperandType.ScaleAnswerSet)) .SelectMany(a => a.Conditions) .Select(c => c.Value) .Distinct() .ToList() ); foreach (var scaleAnswerChoiceString in scaleAnswerChoiceStrings) { decimal scaleAnswerChoiceValue; if (!decimal.TryParse(scaleAnswerChoiceString, out scaleAnswerChoiceValue)) { validationResult |= CreateUpdateProtocolStatus.OneOfBranchesOrAlertsInproperlyFilledIn; break; } } // Validating that conditions with Operand == "MeasurementType" have valid value // Conditions from Branches var measurementValueStrings = request .ProtocolElements .Where(pe => pe.Branches != null) .SelectMany(pe => pe.Branches) .Where(b => b.Conditions != null && b.Conditions.All(c => c.Operand != OperandType.SelectionAnswerChoice) && b.Conditions.All(c => c.Operand != OperandType.ScaleAnswerSet)) .SelectMany(b => b.Conditions) .Select(c => c.Value) .Distinct() .ToList(); // Adding Conditions from Alerts measurementValueStrings.AddRange( request .ProtocolElements .Where(pe => pe.Alerts != null) .SelectMany(pe => pe.Alerts) .Where(a => a.Conditions != null && a.Conditions.All(c => c.Operand != OperandType.SelectionAnswerChoice) && a.Conditions.All(c => c.Operand != OperandType.ScaleAnswerSet)) .SelectMany(b => b.Conditions) .Select(c => c.Value) .Distinct() .ToList() ); foreach (var measurementValueString in measurementValueStrings) { MeasurementLimitType parsedValue; if (!Enum.TryParse(measurementValueString, out parsedValue)) { validationResult |= CreateUpdateProtocolStatus.OneOfBranchesOrAlertsInproperlyFilledIn; break; } } // Validating that conditions with Operand == SelectionAnswerChoice have Guid value // Conditions from Branches var branchesSelectionAnswerChoiceStringIds = request .ProtocolElements .Where(pe => pe.Branches != null) .SelectMany(pe => pe.Branches) .Where(b => b.Conditions != null && b.Conditions.All(c => c.Operand == OperandType.SelectionAnswerChoice)) .SelectMany(b => b.Conditions) .Select(c => c.Value) .Distinct() .ToList(); // Conditions from Alerts var alertsSelectionAnswerChoiceStringIds = request .ProtocolElements .Where(pe => pe.Alerts != null) .SelectMany(pe => pe.Alerts) .Where(a => a.Conditions != null && a.Conditions.All(c => c.Operand == OperandType.SelectionAnswerChoice)) .SelectMany(a => a.Conditions) .Select(c => c.Value) .Distinct() .ToList(); var allSelectionAnswerChoiceStringIds = branchesSelectionAnswerChoiceStringIds .Concat(alertsSelectionAnswerChoiceStringIds) .ToList(); var clientSelectionAnswerChoiceId = new Guid(); var clientSelectionAnswerChoiceIds = allSelectionAnswerChoiceStringIds .Where(sid => Guid.TryParse(sid, out clientSelectionAnswerChoiceId)) .Select(e => clientSelectionAnswerChoiceId) .ToList(); if (clientSelectionAnswerChoiceIds.Count != allSelectionAnswerChoiceStringIds.Count) { validationResult |= CreateUpdateProtocolStatus.OneOfBranchesOrAlertsInproperlyFilledIn; } if (validationResult > 0) { return(validationResult); } return(CreateUpdateProtocolStatus.Success); }
/// <summary> /// Creates the protocol. /// </summary> /// <param name="token">The token.</param> /// <param name="customerId">The customer identifier.</param> /// <param name="protocol">The protocol.</param> /// <returns></returns> public async Task <PostResponseDto <Guid> > CreateProtocol(string token, int customerId, CreateProtocolRequestDto protocol) { var url = string.Format("/api/{0}/protocols", customerId); return(await apiClient.SendRequestAsync <PostResponseDto <Guid> >(url, protocol, Method.POST, null, token)); }