private void ExecuteNavigateToLandingPageCheckSelectionCommand()
        {
            if (!ApplicationInstanceData.SelectedLocalization.Abbreviation.Equals(SelectedLocalization.Abbreviation))
            {
                ApplicationInstanceData.SetLocalization(SelectedLocalization.Abbreviation);
                SetLocalizationSelectionChanged();

                // save pref
                ApplicationInstanceData.SerializedApplicationInstanceData.Localization = SelectedLocalization.Abbreviation;
                ApplicationInstanceData.SaveSerializedApplicationInstanceData();
            }

            if (isFromMainMenu)
            {
                // this view localization refresh
                NotifyPropertyChange(nameof(ApplicationInstanceData));

                // menu model localization refresh
                var menuContentPageModel = (MenuContentPageModel)ApplicationInstanceData.RootPage.Master.BindingContext;
                menuContentPageModel.NotifyPropertyChange(nameof(menuContentPageModel.ApplicationInstanceData));

                return;
            }

            Application.Current.MainPage = new LandingContentPage
            {
                BindingContext = new LandingContentPageModel(ApplicationInstanceData)
            };
        }
        public App()
        {
            InitializeComponent();

            var databasePath             = System.IO.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), @"DATA.db");
            var localizationDatabasePath = System.IO.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), @"LOCAL.db");

            // Application Instance Data
            var applicationInstanceData = new ApplicationInstanceData
            {
                PlatformDataPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal),
                ApplicationInstanceDataFileName = @"AppData.json",
                DatabasePath                      = databasePath,
                LocalizationDatabasePath          = localizationDatabasePath,
                SerializedApplicationInstanceData = new SerializedApplicationInstanceData(),
                AvailableLocalizations            = new ObservableCollection <Localization>(),
                App = this
            };

            var applicationInstanceDataFilePath = System.IO.Path.Combine(applicationInstanceData.PlatformDataPath, applicationInstanceData.ApplicationInstanceDataFileName);

            if (!System.IO.File.Exists(applicationInstanceDataFilePath))
            {
                Helper.Json.JsonFileHelper.SaveDataToJsonFile(applicationInstanceData.SerializedApplicationInstanceData, applicationInstanceDataFilePath);
            }
            applicationInstanceData.SerializedApplicationInstanceData = Helper.Json.JsonFileHelper.GetDataFromJsonFile <SerializedApplicationInstanceData>(applicationInstanceDataFilePath);

            // Init db
            var db = new Database.Data.Database.MDPMSDatabaseContext(applicationInstanceData.DatabasePath);

            //db.Database.EnsureCreated();
            db.Database.Migrate();
            db.LoadRelatedData();
            Database.Data.Database.DatabaseSeed.SeedDatabase(db);
            applicationInstanceData.Data = db;

            // Init Language Database
            var localizationDb = new Database.Localization.Database.LocalizationDatabaseContext(applicationInstanceData.LocalizationDatabasePath);

            //localizationDb.Database.EnsureCreated();
            localizationDb.Database.Migrate();
            Database.Localization.Database.DatabaseSeed.SeedDatabase(localizationDb);
            applicationInstanceData.Localization = localizationDb;

            // Load Localizations
            applicationInstanceData.GetAvailableLocalizations();
            // Load saved localization preference
            try
            {
                applicationInstanceData.SetLocalization(applicationInstanceData.SerializedApplicationInstanceData.Localization);
            }
            catch
            {
                // revert to en on error
                applicationInstanceData.SerializedApplicationInstanceData.Localization = @"en";
                applicationInstanceData.SaveSerializedApplicationInstanceData();
                applicationInstanceData.SetLocalization(@"en");
            }

            // Load view
            applicationInstanceData.NavigateToLandingView();
        }
Ejemplo n.º 3
0
        /*
         *   SYNC STRATEGY
         *   =============
         * SUMMARY => Examine record existence and last update age
         * For now, mobile can not edit households after it is synced to parent
         * Use integer id from parent to identify records
         * Mobile will have internal and external (parent DPMS) ids
         * Record age will be determined by updated_at/LastUpdatedAt datetimes
         *
         *     Mobile                                               Parent_DPMS
         *     ======                                               ===========
         * GetRecordFromParent <------------------------------- Exists on parent but not on mobile
         * Exists on Mobile but not on parent ----------------> GetRecordFromMobile (if not previously synced, otherwise soft/hard delete from mobile)
         * Older on mobile than parent <--UpdateMobileRecord--- Newer on parent than mobile
         * Newer on mobile than parent ---NotYetSupported-----> Older on parent than mobile             (Currently invalid, would be supported by updating parent record)
         *
         *   REASONING =>
         *
         *   Exists
         *   ======
         *   Mobile | Parent
         *   ---------------
         *   0      |   0       * N/A
         *   0      |   1       * Exists only on parent, mobile get from parent
         *   1      |   0       * Exists only on mobile, send to parent         !!! NOTE check for internal id since it could have been deleted from parent
         *   1      |   1       * Exists on both, see Record_Age table ==>
         *
         *   Exists_Special_Case
         *   ===================
         *   1      |   0       * If no external id, send to parent
         *   1      |   0       * If has external id, delete or soft delete internally
         *
         *   Record_Age
         *   ==========
         *   Mobile | Parent
         *   ---------------
         *   0      |   0       * Same age, no action
         *   0      |   1       * Newer on parent, update mobile
         *   1      |   0       * Newer on mobile, update parent    (NOT_YET_SUPPORTED)
         *   1      |   1       * Same age, no action
         *
         *  NOTE on newer on mobile:
         *  For now we can send those to the parent and mark as NEEDS_TO_BE_MANUALLY_RESOLVED
         *
         *  ALSO, deleted from parent, if already synced but no longer on parent delete on mobile, use soft delete?
         *  this would require the parent to support deleting households
         */

        public static Tuple <bool, string> Sync(ApplicationInstanceData applicationInstanceData,
                                                bool allowAlreadySyncedUpdateToParent)
        {
            try
            {
                // Look Ups
                // PersonRelationship
                var personRelationshipResult = SyncObject(
                    applicationInstanceData,
                    false,
                    @"/api/relationships",
                    applicationInstanceData.Data.PersonRelationships);
                if (!personRelationshipResult.Item1)
                {
                    return(new Tuple <bool, string>(false, applicationInstanceData.SelectedLocalization.Translations[@"ErrorSyncError"]));
                }

                // Custom Fields
                var customFieldResult = SyncObject(
                    applicationInstanceData,
                    false,
                    @"/api/custom_fields",
                    applicationInstanceData.Data.CustomFields);
                if (!customFieldResult.Item1)
                {
                    return(new Tuple <bool, string>(false, applicationInstanceData.SelectedLocalization.Translations[@"ErrorSyncError"]));
                }

                // Status Customization Look Ups
                var statusCustomizationHazardousConditionsResult = SyncObject(
                    applicationInstanceData,
                    allowAlreadySyncedUpdateToParent,
                    @"/api/status_customization_hazardous_conditions",
                    applicationInstanceData.Data.StatusCustomizationHazardousConditions);
                if (!statusCustomizationHazardousConditionsResult.Item1)
                {
                    return(new Tuple <bool, string>(false, applicationInstanceData.SelectedLocalization.Translations[@"ErrorSyncError"]));
                }

                var statusCustomizationHouseholdTasksResult = SyncObject(
                    applicationInstanceData,
                    allowAlreadySyncedUpdateToParent,
                    @"/api/status_customization_household_tasks",
                    applicationInstanceData.Data.StatusCustomizationHouseholdTasks);
                if (!statusCustomizationHouseholdTasksResult.Item1)
                {
                    return(new Tuple <bool, string>(false, applicationInstanceData.SelectedLocalization.Translations[@"ErrorSyncError"]));
                }

                var statusCustomizationWorkActivitiesResult = SyncObject(
                    applicationInstanceData,
                    allowAlreadySyncedUpdateToParent,
                    @"/api/status_customization_work_activities",
                    applicationInstanceData.Data.StatusCustomizationWorkActivities);
                if (!statusCustomizationWorkActivitiesResult.Item1)
                {
                    return(new Tuple <bool, string>(false, applicationInstanceData.SelectedLocalization.Translations[@"ErrorSyncError"]));
                }

                // Service Type Categories
                // TODO: add new method for non datetime based sync for this table
                var serviceTypeCategoriesResult = SyncObject(
                    applicationInstanceData,
                    allowAlreadySyncedUpdateToParent,
                    @"/api/service_type_categories",
                    applicationInstanceData.Data.ServiceTypeCategories);
                if (!serviceTypeCategoriesResult.Item1)
                {
                    return(new Tuple <bool, string>(false, applicationInstanceData.SelectedLocalization.Translations[@"ErrorSyncError"]));
                }

                // Service Types
                var serviceTypesResult = SyncChildObject(
                    applicationInstanceData,
                    allowAlreadySyncedUpdateToParent,
                    @"/api/service_types",
                    applicationInstanceData.Data.ServiceTypes,
                    @"service_type_category_id",
                    applicationInstanceData.Data.ServiceTypeCategories);
                if (!serviceTypesResult.Item1)
                {
                    return(new Tuple <bool, string>(false, applicationInstanceData.SelectedLocalization.Translations[@"ErrorSyncError"]));
                }

                // set service type parent internal ids since not added through ui
                // TODO: alternate method for server only child records?
                foreach (var serviceTypeCategory in applicationInstanceData.Data.ServiceTypeCategories)
                {
                    serviceTypeCategory.SetParentIdsInChildObjects();
                }
                applicationInstanceData.Data.SaveChanges();

                // Services
                var servicesResult = SyncChildObject(
                    applicationInstanceData,
                    allowAlreadySyncedUpdateToParent,
                    @"/api/services",
                    applicationInstanceData.Data.Services,
                    @"service_type_id",
                    applicationInstanceData.Data.ServiceTypes);
                if (!servicesResult.Item1)
                {
                    return(new Tuple <bool, string>(false, applicationInstanceData.SelectedLocalization.Translations[@"ErrorSyncError"]));
                }

                foreach (var serviceType in applicationInstanceData.Data.ServiceTypes)
                {
                    serviceType.SetParentIdsInChildObjects();
                }
                applicationInstanceData.Data.SaveChanges();

                // Data
                var householdsResult = SyncObject(
                    applicationInstanceData,
                    allowAlreadySyncedUpdateToParent,
                    @"/api/households",
                    applicationInstanceData.Data.Households);
                if (!householdsResult.Item1)
                {
                    return(new Tuple <bool, string>(false, applicationInstanceData.SelectedLocalization.Translations[@"ErrorSyncError"]));
                }

                var householdsNewResult = SyncNewParentObjects(
                    applicationInstanceData,
                    @"/api/households",
                    applicationInstanceData.Data.Households);
                if (!householdsNewResult.Item1)
                {
                    return(new Tuple <bool, string>(false, applicationInstanceData.SelectedLocalization.Translations[@"ErrorSyncError"]));
                }

                //< IncomeSource, Household >
                var incomeSourcesResult = SyncChildObject(
                    applicationInstanceData,
                    allowAlreadySyncedUpdateToParent,
                    @"/api/income_sources",
                    applicationInstanceData.Data.IncomeSources,
                    @"household_id",
                    applicationInstanceData.Data.Households);
                if (!incomeSourcesResult.Item1)
                {
                    return(new Tuple <bool, string>(false, applicationInstanceData.SelectedLocalization.Translations[@"ErrorSyncError"]));
                }

                var incomeSourcesNewResult = SyncNewChildObjects(
                    applicationInstanceData,
                    @"/api/income_sources",
                    applicationInstanceData.Data.IncomeSources,
                    @"household_id",
                    applicationInstanceData.Data.Households);
                if (!incomeSourcesNewResult.Item1)
                {
                    return(new Tuple <bool, string>(false, applicationInstanceData.SelectedLocalization.Translations[@"ErrorSyncError"]));
                }

                //<Person, Household>
                var peopleResult = SyncChildObject(
                    applicationInstanceData,
                    allowAlreadySyncedUpdateToParent,
                    @"/api/people",
                    applicationInstanceData.Data.People,
                    @"household_id",
                    applicationInstanceData.Data.Households);
                if (!peopleResult.Item1)
                {
                    return(new Tuple <bool, string>(false, applicationInstanceData.SelectedLocalization.Translations[@"ErrorSyncError"]));
                }

                var peopleNewResult = SyncNewChildObjects(
                    applicationInstanceData,
                    @"/api/people",
                    applicationInstanceData.Data.People,
                    @"household_id",
                    applicationInstanceData.Data.Households);
                if (!peopleNewResult.Item1)
                {
                    return(new Tuple <bool, string>(false, applicationInstanceData.SelectedLocalization.Translations[@"ErrorSyncError"]));
                }

                // <PersonFollowUp, Person>
                var peopleFollowUpResult = SyncChildObject(
                    applicationInstanceData,
                    allowAlreadySyncedUpdateToParent,
                    @"/api/follow_ups",
                    applicationInstanceData.Data.PersonFollowUps,
                    @"person_id",
                    applicationInstanceData.Data.People);
                if (!peopleFollowUpResult.Item1)
                {
                    return(new Tuple <bool, string>(false, applicationInstanceData.SelectedLocalization.Translations[@"ErrorSyncError"]));
                }

                var peopleFollowUpNewResult = SyncNewChildObjects(
                    applicationInstanceData,
                    @"/api/follow_ups",
                    applicationInstanceData.Data.PersonFollowUps,
                    @"person_id",
                    applicationInstanceData.Data.People);
                if (!peopleFollowUpNewResult.Item1)
                {
                    return(new Tuple <bool, string>(false, applicationInstanceData.SelectedLocalization.Translations[@"ErrorSyncError"]));
                }

                // Service Instances
                var serviceInstancesResult = SyncChildObject(
                    applicationInstanceData,
                    allowAlreadySyncedUpdateToParent,
                    @"/api/service_instances",
                    applicationInstanceData.Data.ServiceInstances,
                    @"person_id",
                    applicationInstanceData.Data.People);
                if (!serviceInstancesResult.Item1)
                {
                    return(new Tuple <bool, string>(false, applicationInstanceData.SelectedLocalization.Translations[@"ErrorSyncError"]));
                }

                foreach (var person in applicationInstanceData.Data.People)
                {
                    person.SetParentIdsInChildObjects();
                }
                applicationInstanceData.Data.SaveChanges();

                // new
                var serviceInstancesNewResult = SyncNewChildObjects(
                    applicationInstanceData,
                    @"/api/service_instances",
                    applicationInstanceData.Data.ServiceInstances,
                    @"person_id",
                    applicationInstanceData.Data.People);
                if (!serviceInstancesNewResult.Item1)
                {
                    return(new Tuple <bool, string>(false, applicationInstanceData.SelectedLocalization.Translations[@"ErrorSyncError"]));
                }

                // Custom Household Values
                var customHouseholdValuesResult = SyncCustomValueObject(
                    applicationInstanceData,
                    allowAlreadySyncedUpdateToParent,
                    @"/api/custom_values",
                    applicationInstanceData.Data.CustomHouseholdValues,
                    applicationInstanceData.Data.CustomFields.Where(a => a.ModelType == @"Household").ToList());
                if (!customHouseholdValuesResult.Item1)
                {
                    return(new Tuple <bool, string>(false, applicationInstanceData.SelectedLocalization.Translations[@"ErrorSyncError"]));
                }
                var postNewCustomHouseholdValuesResult = PostCustomValues(
                    applicationInstanceData,
                    @"/api/custom_values",
                    applicationInstanceData.Data.CustomHouseholdValues);
                if (!postNewCustomHouseholdValuesResult.Item1)
                {
                    return(new Tuple <bool, string>(false, applicationInstanceData.SelectedLocalization.Translations[@"ErrorSyncError"]));
                }

                // Custom Person Values
                var customPersonValuesResult = SyncCustomValueObject(
                    applicationInstanceData,
                    allowAlreadySyncedUpdateToParent,
                    @"/api/custom_values",
                    applicationInstanceData.Data.CustomPersonValues,
                    applicationInstanceData.Data.CustomFields.Where(a => a.ModelType == @"Person").ToList());
                if (!customPersonValuesResult.Item1)
                {
                    return(new Tuple <bool, string>(false, applicationInstanceData.SelectedLocalization.Translations[@"ErrorSyncError"]));
                }
                var postNewCustomPersonValuesResult = PostCustomValues(
                    applicationInstanceData,
                    @"/api/custom_values",
                    applicationInstanceData.Data.CustomPersonValues);
                if (!postNewCustomPersonValuesResult.Item1)
                {
                    return(new Tuple <bool, string>(false, applicationInstanceData.SelectedLocalization.Translations[@"ErrorSyncError"]));
                }

                // Custom PersonFollowUp Values
                var customPersonFollowUpValuesResult = SyncCustomValueObject(
                    applicationInstanceData,
                    allowAlreadySyncedUpdateToParent,
                    @"/api/custom_values",
                    applicationInstanceData.Data.CustomPersonFollowUpValues,
                    applicationInstanceData.Data.CustomFields.Where(a => a.ModelType == @"FollowUp").ToList());
                if (!customPersonFollowUpValuesResult.Item1)
                {
                    return(new Tuple <bool, string>(false, applicationInstanceData.SelectedLocalization.Translations[@"ErrorSyncError"]));
                }
                var postNewCustomPersonFollowUpValuesResult = PostCustomValues(
                    applicationInstanceData,
                    @"/api/custom_values",
                    applicationInstanceData.Data.CustomPersonFollowUpValues);
                if (!postNewCustomPersonFollowUpValuesResult.Item1)
                {
                    return(new Tuple <bool, string>(false, applicationInstanceData.SelectedLocalization.Translations[@"ErrorSyncError"]));
                }
            }
            catch
            {
                // TODO: error log
                return(new Tuple <bool, string>(false, applicationInstanceData.SelectedLocalization.Translations[@"ErrorSyncError"]));
            }

            // successful sync
            applicationInstanceData.SerializedApplicationInstanceData.LastSync = DateTime.UtcNow;
            applicationInstanceData.SaveSerializedApplicationInstanceData();
            return(new Tuple <bool, string>(true, @""));
        }