internal static IEnumerable <SurveyAnswerDelta> GetDeltas(
            IDictionary <string, object> currentAnswers,
            IDictionary <string, object> incomingAnswers)
        {
            var deltas = new HashSet <SurveyAnswerDelta>();

            //all keys should match
            var nonMatchingKeys = currentAnswers.Keys.Except(incomingAnswers.Keys);

            if (nonMatchingKeys.Any())
            {
                throw new ArgumentOutOfRangeException(
                          "Expected for current and incoming answer sets to have matching keys.  " +
                          $"Instead found '{string.Join(',', nonMatchingKeys)}' keys that were different");
            }

            foreach (var key in currentAnswers.Keys)
            {
                dynamic current  = currentAnswers[key];
                dynamic incoming = incomingAnswers[key];

                System.Diagnostics.Debug.WriteLine($"c='{current.GetType()}' i='{incoming.GetType()}'");

                //unbox to the correct types
                if (!SurveyAnswerBindingHelpers.IsQuestion(key) && !SurveyAnswerBindingHelpers.IsRepeater(key))
                {
                    if (current is IEnumerable <IHaveUniqueKey> )
                    {
                        foreach (var delta in DetectChanges(key, current, incoming))
                        {
                            deltas.Add(delta);
                        }
                    }
                    else
                    {
                        //throw new NotImplementedException();
                    }
                }
                else if (SurveyAnswerBindingHelpers.IsRepeater(key))
                {
                    if (!JToken.DeepEquals(current, incoming))
                    {
                        deltas.Add(
                            new SurveyAnswerDelta(key, current, incoming, AnswerState.Modified));
                    }
                }
                else
                {
                    if (!Equals(current, incoming))
                    {
                        deltas.Add(
                            new SurveyAnswerDelta(key, current, incoming, AnswerState.Modified));
                    }
                }
            }

            return(deltas);
        }
Example #2
0
        protected async override Task HandleInnerAsync(SurveyAnswerWriteContext context)
        {
            //this should only handle single questions
            if (!SurveyAnswerBindingHelpers.IsQuestion(context.Delta.Key))
            {
                return;
            }

            //handle null
            if (context.Delta.Incoming == null)
            {
                await DeleteAnswer(context);

                return;
            }

            await UpsertAnswer(context, context.Delta.Incoming);
        }
Example #3
0
        public async Task Execute(SaveSurveyAnswers command)
        {
            var questionStorageMap = await repos.GetQuestionStorageMap(command.SurveyId);

            var currentAnswers = await repos.Get(new GetSurveyAnswers
            {
                CaseId     = command.CaseId,
                SurveyId   = command.SurveyId,
                ProfileId  = command.ProfileId,
                OutbreakId = command.OutbreakId
            });

            //unwrap jArrays to complex types
            SurveyAnswerBindingHelpers.Bind(command.Answers);

            var answers = command.Answers.ToDictionary(entry => entry.Key.ToUpper(), entry => entry.Value);

            //get only the differences
            var deltas = SurveyAnswerHelpers.GetDeltas(currentAnswers, answers);

            //if no delta, exit
            if (!deltas.Any())
            {
                return;
            }

            var writer = COR <SurveyAnswerWriteContext> .CreateChain(
                new SymptomWriteHandler(),
                new TravelHistoryWriteHandler(),
                new MappedWriteHandler(dataServices),
                new RepeaterWriteHandler(),
                new MultipleWriteHandler(),
                new DefaultWriteHandler());

            var allkeys = deltas
                          .Select(delta => delta.Key)
                          .ToList();

            var storageMapping = writeContext.SurveyObjectMapping
                                 .Where(mapping => mapping.CdMappingtype == "TARGETDS")
                                 .Where(mapping => allkeys.Contains(mapping.IdQuestion))
                                 .ToDictionary(mapping => mapping.IdQuestion.ToUpper());

            var surveyInstanceId = await repos.GetSurveyInstanceId(command.ProfileId, command.CaseId, command.OutbreakId);

            var connection = writeContext.Database.GetDbConnection().EnsureOpen();

            using (var transaction = writeContext.Database.BeginTransaction().GetDbTransaction())
            {
                //TODO:  This needs better DB design
                //if no survey instance, create one
                if (surveyInstanceId == 0)
                {
                    surveyInstanceId = (int)await sequencerGenerator.GetNextAsync(SequenceType.SurveyInstance);

                    var instance = new SurveyInstance
                    {
                        IdSurveyInstance = surveyInstanceId.Value,
                        IdProfile        = command.ProfileId,
                    };

                    if (command.OutbreakId != null)
                    {
                        instance.CdEntityType = "O";
                        instance.IdEntity     = command.OutbreakId;
                    }

                    if (command.CaseId != null)
                    {
                        instance.CdEntityType = "C";
                        instance.IdEntity     = command.CaseId;
                    }

                    await writeContext.SurveyInstance.AddAsync(instance);

                    await writeContext.SaveChangesAsync();
                }
                //end

                var context = new SurveyAnswerWriteContext
                {
                    DB                 = writeContext,
                    CaseId             = command.CaseId,
                    ProfileId          = command.ProfileId,
                    OutbreakId         = command.OutbreakId,
                    SurveyInstanceId   = surveyInstanceId.Value, //should be assigned a value by this point
                    UserId             = usernameProvider.GetUsername(),
                    Timestamp          = DateTime.Now,
                    QuestionStorageMap = questionStorageMap
                };

                context.Transaction = transaction;
                context.Connection  = connection;

                //apply the changes
                foreach (var delta in deltas)
                {
                    context.Delta = delta;

                    await writer.HandleAsync(context);

                    //need to mark question as answered
                    if (SurveyAnswerBindingHelpers.IsQuestion(delta.Key))
                    {
                        var param = new
                        {
                            questionId = delta.Key
                        };
                        try
                        {
                            string sql = @"update survey_question_bank
                                set IN_ANSWERED = 1
                                where id_question = @questionId
                                and IN_ANSWERED = 0;";

                            await connection.ExecuteAsync(sql, param, 1, transaction);
                        }
                        catch (Exception e)
                        {
                            //do nothing for now
                        }
                    }
                }
                transaction.Commit();
            }
        }
 protected override bool CanHandle(SurveyAnswerWriteContext context)
 {
     return(SurveyAnswerBindingHelpers.HasMultipleAnswers(context.Delta.Incoming));
 }