예제 #1
0
 private void PersistActivityProgress(ActivityProgress activityProgress, OperationName operationName, OperationState?operationState = null, int?operationContactCount = null, string operationDuration = null)
 {
     activityProgress.Operations[operationName.ToString()].Duration       = operationDuration ?? activityProgress.Operations[operationName.ToString()].Duration;
     activityProgress.Operations[operationName.ToString()].ContactCount   = operationContactCount ?? activityProgress.Operations[operationName.ToString()].ContactCount;
     activityProgress.Operations[operationName.ToString()].OperationState = operationState ?? activityProgress.Operations[operationName.ToString()].OperationState;
     _jobRepository.PersistActivityProgress(activityProgress);
 }
예제 #2
0
        public override async void ViewWillAppear(bool animated)
        {
            base.ViewWillAppear(animated);

            // Load this activity's progress from the database if available
            ActivityProgress progress = (await GetDatabaseManager()).GetProgress(DisplayedActivity);
            List <AppTask>   appTasks = null;

            if (progress != null)
            {
                appTasks = JsonConvert.DeserializeObject <List <AppTask> >(progress.AppTaskJson,
                                                                           new JsonSerializerSettings {
                    TypeNameHandling = TypeNameHandling.Auto
                });
            }

            if (appTasks == null)
            {
                appTasks = new List <AppTask>();

                foreach (LearningTask t in DisplayedActivity.LearningTasks)
                {
                    appTasks.Add(new AppTask(t));
                }
            }

            TaskViewSource source = new TaskViewSource(DisplayedActivity, appTasks, StartTask, ResultClicked, NameEdit);

            source.enteredName = progress?.EnteredUsername;

            TableView.Source = source;

            hiddenChildren = new Dictionary <int, List <AppTask> >();
            AppTask[] temp = appTasks.ToArray();

            foreach (AppTask parent in temp)
            {
                if (parent.TaskType.IdName == "INFO")
                {
                    parent.IsCompleted = true;
                }

                if (parent.ChildAppTasks?.Count > 0)
                {
                    hiddenChildren.Add(parent.Id, parent.ChildAppTasks);
                    CheckForChildren(appTasks.IndexOf(parent));
                }
            }

            TableView.ReloadData();

            if (!loaded)
            {
                var suppress = PrepActivityFiles();
            }
        }
예제 #3
0
 public void PersistActivityProgress(ActivityProgress activityProgress)
 {
     _mongoDatabase
     .GetCollection <ActivityProgressKeyValue>(nameof(ActivityProgressKeyValue))
     .ReplaceOne(
         filter: Builders <ActivityProgressKeyValue> .Filter.Eq("_id", nameof(ActivityProgressKeyValue)),
         replacement: new ActivityProgressKeyValue {
         LastUpdatedUtc = _clock.UtcNow, Value = activityProgress
     },
         options: new UpdateOptions {
         IsUpsert = true
     });
 }
예제 #4
0
        public async Task <Activity> Sync()
        {
            var activity         = new Activity(_clock.UtcNow);
            var activityProgress = default(ActivityProgress);

            _logger.LogInformation("Starting MP to HubSpot one-way sync operations (create new registrations first, followed by 2 update operations).");
            try
            {
                activityProgress = _configurationService.GetCurrentActivityProgress();
                if (activityProgress.ActivityState == ActivityState.Processing)
                {
                    _logger.LogWarning("Job is already currently processing.");
                    return(activity);
                }

                // set job processing state; get last successful sync dates
                _jobRepository.PersistActivityProgress(activityProgress = new ActivityProgress {
                    ActivityState = ActivityState.Processing
                });
                var operationDates   = activity.PreviousOperationDates = _configurationService.GetLastSuccessfulOperationDates();
                var ageGradeDeltaLog = default(ChildAgeAndGradeDeltaLogDto);

                Util.TryCatchSwallow(() => { // running this in advance of the create process with the express purpose of avoiding create/update race conditions when we consume the results for update
                    PersistActivityProgress(activityProgress, OperationName.AgeGradeDataCalculationInMp, OperationState.Processing);
                    activity.ChildAgeAndGradeCalculationOperation = CalculateAndPersistChildAgeGradeDataByHousehold(activity.PreviousOperationDates);
                    ageGradeDeltaLog          = activity.ChildAgeAndGradeCalculationOperation.AgeGradeDeltaLog;
                    var operationContactCount = ageGradeDeltaLog.InsertCount + ageGradeDeltaLog.UpdateCount;
                    var operationDuration     = activity.ChildAgeAndGradeCalculationOperation.Execution.Duration;
                    PersistActivityProgress(activityProgress, OperationName.AgeGradeDataCalculationInMp, operationContactCount: operationContactCount, operationDuration: operationDuration);
                    operationDates.AgeAndGradeProcessDate = ageGradeDeltaLog.ProcessedUtc;
                    operationDates.AgeAndGradeSyncDate    = ageGradeDeltaLog.SyncCompletedUtc ?? default(DateTime); // go ahead and set in case there's nothing to do
                    _jobRepository.PersistLastSuccessfulOperationDates(operationDates);
                    PersistActivityProgress(activityProgress, OperationName.AgeGradeDataCalculationInMp, OperationState.Completed);
                }, () => {
                    _logger.LogWarning("Age/grade calculation and persistence operation aborted.");
                    PersistActivityProgress(activityProgress, OperationName.AgeGradeDataCalculationInMp, OperationState.Aborted);
                });

                Util.TryCatchSwallow(() => { // sync newly registered contacts to hubspot
                    PersistActivityProgress(activityProgress, OperationName.NewContactRegistrationSync, OperationState.Processing);
                    activity.NewRegistrationSyncOperation = SyncNewRegistrations(activity.PreviousOperationDates.RegistrationSyncDate, activityProgress);
                    if (_activityValidator.Validate(activity, ruleSet: RuleSetName.NewRegistrationSync).IsValid)
                    {
                        operationDates.RegistrationSyncDate = activity.NewRegistrationSyncOperation.Execution.StartUtc;
                        _jobRepository.PersistLastSuccessfulOperationDates(operationDates);
                        PersistActivityProgress(activityProgress, OperationName.NewContactRegistrationSync, OperationState.Completed, operationDuration: activity.NewRegistrationSyncOperation.Execution.Duration);
                    }
                    else
                    {
                        PersistActivityProgress(activityProgress, OperationName.NewContactRegistrationSync, OperationState.CompletedButWithIssues, operationDuration: activity.NewRegistrationSyncOperation.Execution.Duration);
                    }
                }, () => {
                    _logger.LogWarning("Sync new registrations operation aborted.");
                    PersistActivityProgress(activityProgress, OperationName.NewContactRegistrationSync, OperationState.Aborted, operationDuration: activity.NewRegistrationSyncOperation.Execution.Duration);
                });

                Util.TryCatchSwallow(() => { // sync core contact property updates to hubspot
                    PersistActivityProgress(activityProgress, OperationName.CoreContactAttributeUpdateSync, OperationState.Processing);
                    activity.CoreContactAttributeSyncOperation = SyncCoreUpdates(activity.PreviousOperationDates.CoreUpdateSyncDate, activityProgress);
                    if (_activityValidator.Validate(activity, ruleSet: RuleSetName.CoreContactAttributeSync).IsValid)
                    {
                        operationDates.CoreUpdateSyncDate = activity.CoreContactAttributeSyncOperation.Execution.StartUtc;
                        _jobRepository.PersistLastSuccessfulOperationDates(operationDates);
                        PersistActivityProgress(activityProgress, OperationName.CoreContactAttributeUpdateSync, OperationState.Completed, operationDuration: activity.CoreContactAttributeSyncOperation.Execution.Duration);
                    }
                    else
                    {
                        PersistActivityProgress(activityProgress, OperationName.CoreContactAttributeUpdateSync, OperationState.CompletedButWithIssues, operationDuration: activity.CoreContactAttributeSyncOperation.Execution.Duration);
                    }
                }, () => {
                    _logger.LogWarning("Sync core updates operation aborted.");
                    PersistActivityProgress(activityProgress, OperationName.CoreContactAttributeUpdateSync, OperationState.Aborted, operationDuration: activity.CoreContactAttributeSyncOperation.Execution.Duration);
                });

                Util.TryCatchSwallow(() => { // sync age/grade data to hubspot contacts
                    PersistActivityProgress(activityProgress, OperationName.AgeGradeDataSync, OperationState.Processing);
                    activity.ChildAgeAndGradeSyncOperation = SyncChildAgeAndGradeData(ageGradeDeltaLog, activity.PreviousOperationDates.AgeAndGradeSyncDate);
                    if (_activityValidator.Validate(activity, ruleSet: RuleSetName.ChildAgeGradeSync).IsValid)
                    {
                        if (ageGradeDeltaLog.InsertCount > 0 || ageGradeDeltaLog.UpdateCount > 0)
                        {
                            ageGradeDeltaLog.SyncCompletedUtc = operationDates.AgeAndGradeSyncDate = _ministryPlatformContactRepository.SetChildAgeAndGradeDeltaLogSyncCompletedUtcDate();
                        }
                        _jobRepository.PersistLastSuccessfulOperationDates(operationDates);
                        PersistActivityProgress(activityProgress, OperationName.AgeGradeDataSync, OperationState.Completed, activity.ChildAgeAndGradeSyncOperation.SuccessCount, activity.ChildAgeAndGradeSyncOperation.Execution.Duration);
                    }
                    else
                    {
                        PersistActivityProgress(activityProgress, OperationName.AgeGradeDataSync, OperationState.CompletedButWithIssues, operationDuration: activity.ChildAgeAndGradeSyncOperation.Execution.Duration);
                    }
                }, () => {
                    _logger.LogWarning("Sync age/grade data operation aborted.");
                    PersistActivityProgress(activityProgress, OperationName.AgeGradeDataSync, OperationState.Aborted, operationDuration: activity.ChildAgeAndGradeSyncOperation.Execution.Duration);
                });

                // reset sync job state
                PersistActivityProgress(activityProgress, ActivityState.Idle);

                return(activity);
            }
            catch (Exception exc)
            {
                _logger.LogError(CoreEvent.Exception, exc, "An exception occurred while syncing MP contacts to HubSpot.");
                PersistActivityProgress(activityProgress, ActivityState.Idle);
                throw;
            }
            finally // *** ALWAYS *** capture the activity, even if the job is already processing or an exception occurs
            {
                activity.ActivityProgress    = activityProgress;
                activity.Execution.FinishUtc = _clock.UtcNow;
                PersistActivityProgress(activityProgress, activityDuration: activity.Execution.Duration);
                _activityCleaner.CleanUp(activity);
                if (_configurationService.PersistActivity())
                {
                    _jobRepository.PersistActivity(activity);
                }
                _logger.LogInformation("Exiting...");
            }
        }
예제 #5
0
 private void PersistActivityProgress(ActivityProgress activityProgress, ActivityState?activityState = null, string activityDuration = null)
 {
     activityProgress.ActivityState = activityState ?? activityProgress.ActivityState;
     activityProgress.Duration      = activityDuration ?? activityProgress.Duration;
     _jobRepository.PersistActivityProgress(activityProgress);
 }
예제 #6
0
        /// <summary>
        /// Capable of accommodating email address (unique identifier in HubSpot) change and other core contact attribute/property updates.
        /// Can also create a contact if it does not exist.
        /// </summary>
        private ActivitySyncOperation SyncCoreUpdates(DateTime lastSuccessfulSyncDate, ActivityProgress activityProgress)
        {
            var activity = new ActivitySyncOperation(_clock.UtcNow)
            {
                PreviousSyncDate = lastSuccessfulSyncDate
            };

            try
            {
                _logger.LogInformation("Starting MP contact core updates to HubSpot one-way sync operation...");
                var updates = _dataPrep.Prep(_ministryPlatformContactRepository.GetAuditedContactUpdates(lastSuccessfulSyncDate));
                PersistActivityProgress(activityProgress, OperationName.CoreContactAttributeUpdateSync, operationContactCount: updates.Length);
                activity.SerialUpdateResult         = _contactSyncer.SerialUpdate(updates);
                activity.SerialCreateResult         = _contactSyncer.SerialCreate(activity.SerialUpdateResult.EmailAddressesDoNotExist.ToArray());
                activity.SerialReconciliationResult = _contactSyncer.ReconcileConflicts(activity.SerialUpdateResult.EmailAddressesAlreadyExist.ToArray());

                return(activity);
            }
            catch (Exception exc)
            {
                _logger.LogError(CoreEvent.Exception, exc, "An exception occurred while syncing MP contact core updates to HubSpot.");
                throw;
            }
            finally // *** ALWAYS *** capture the HubSpot API request count, even if an exception occurs
            {
                activity.Execution.FinishUtc = _clock.UtcNow;
                _jobRepository.PersistHubSpotApiDailyRequestCount(activity.HubSpotApiRequestCount, activity.Execution.StartUtc);
            }
        }
예제 #7
0
        /// <summary>
        /// Handles create, update and reconciliation scenarios for MP CRM contacts identified as new registrants that ought to exist
        /// in the HubSpot CRM.
        /// </summary>
        private ActivitySyncOperation SyncNewRegistrations(DateTime lastSuccessfulSyncDate, ActivityProgress activityProgress)
        {
            var activity = new ActivitySyncOperation(_clock.UtcNow)
            {
                PreviousSyncDate = lastSuccessfulSyncDate
            };

            try
            {
                _logger.LogInformation("Starting new MP registrations to HubSpot one-way sync operation...");
                var newContacts = _ministryPlatformContactRepository.GetNewlyRegisteredContacts(lastSuccessfulSyncDate);                             // talk to MP
                PersistActivityProgress(activityProgress, OperationName.NewContactRegistrationSync, operationContactCount: newContacts.Count);
                activity.SerialCreateResult         = _contactSyncer.SerialCreate(_dataPrep.Prep(newContacts));                                      // create in HubSpot
                activity.SerialUpdateResult         = _contactSyncer.SerialUpdate(activity.SerialCreateResult.EmailAddressesAlreadyExist.ToArray()); // update in HubSpot
                activity.SerialReconciliationResult = _contactSyncer.ReconcileConflicts(activity.SerialUpdateResult.EmailAddressesAlreadyExist.ToArray());

                return(activity);
            }
            catch (Exception exc)
            {
                _logger.LogError(CoreEvent.Exception, exc, "An exception occurred while syncing new MP contacts to HubSpot.");
                throw;
            }
            finally // *** ALWAYS *** capture the HubSpot API request count, even if an exception occurs
            {
                activity.Execution.FinishUtc = _clock.UtcNow;
                _jobRepository.PersistHubSpotApiDailyRequestCount(activity.HubSpotApiRequestCount, activity.Execution.StartUtc);
            }
        }
예제 #8
0
        protected override async void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            string jsonData = Intent.GetStringExtra("JSON") ?? "";

            learningActivity = JsonConvert.DeserializeObject <LearningActivity>(jsonData,
                                                                                new JsonSerializerSettings {
                TypeNameHandling = TypeNameHandling.Auto
            });

            if (learningActivity == null)
            {
                using (var alert = new global::Android.Support.V7.App.AlertDialog.Builder(this))
                {
                    alert.SetTitle(Resource.String.ErrorTitle)
                    .SetMessage(Resource.String.ErrorTitle)
                    .SetOnDismissListener(new OnDismissListener(Finish));
                    alert.Show();
                }
                return;
            }

            dbManager = await Storage.GetDatabaseManager();

            // Load this activity's progress from the database if available
            ActivityProgress progress = dbManager.GetProgress(learningActivity);
            List <AppTask>   appTasks = null;

            try
            {
                if (progress != null)
                {
                    enteredName = progress.EnteredUsername;
                    appTasks    = JsonConvert.DeserializeObject <List <AppTask> >(progress.AppTaskJson);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                Toast.MakeText(this, Resource.String.errorCache, ToastLength.Long).Show();
                appTasks = null;
            }

            if (appTasks == null)
            {
                appTasks = learningActivity.LearningTasks.Select(t => new AppTask(t)).ToList();
            }

            bool curatorControls = learningActivity.IsPublic && !learningActivity.Approved && dbManager.CurrentUser.Trusted;

            adapter              = new TaskAdapter(this, learningActivity.Id, appTasks, learningActivity.Description, curatorControls, learningActivity.RequireUsername);
            adapter.ItemClick   += OnItemClick;
            adapter.TextEntered += Adapter_TextEntered;
            adapter.ShowMedia   += ShowMedia;
            adapter.Approved    += Adapter_Approved;
            adapter.SpeakText   += Adapter_SpeakText;
            adapter.ChangeName  += Adapter_EditName;

            SetContentView(Resource.Layout.RecyclerViewActivity);
            recyclerView = FindViewById <RecyclerView>(Resource.Id.recyclerView);
            toolbar      = FindViewById <global::Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
            SetSupportActionBar(toolbar);
            SupportActionBar.SetDisplayHomeAsUpEnabled(true);

            LoadHeaderImage(learningActivity.ImageUrl);

            SetupContent();

            if (!string.IsNullOrWhiteSpace(enteredName))
            {
                adapter.UpdateNames(enteredName);
            }
        }