Exemple #1
0
        private static async Task DeleteCollection(string appDataPath)
        {
            try
            {
                string settingsFile    = appDataPath + "\\" + FolderConstants.GIN_APP_DATA_FOLDER + "\\settings.txt";
                string encryptedString = System.IO.File.ReadAllText(settingsFile);
                string decryptedString = CottonDBMS.Helpers.EncryptionHelper.Decrypt(encryptedString);
                var    parms           = Newtonsoft.Json.JsonConvert.DeserializeObject <TruckAppInstallParams>(decryptedString);

                if (!string.IsNullOrEmpty(parms.EndPoint) &&
                    !string.IsNullOrEmpty(parms.Key))
                {
                    DocumentDBContext.Initialize(parms.EndPoint, parms.Key);

                    //remove document tracking lists this truck has downloaded
                    //this allows them to be released for delete etc at the gin
                    await DocumentDBContext.DeleteCollectionAsync();
                }
                else
                {
                    Console.WriteLine("One or more settings null.");
                }
            }
            catch (Exception exc)
            {
                Console.WriteLine(exc.Message);
                Console.WriteLine(exc.StackTrace);
                Console.WriteLine("Press enter to continue.");
                Console.ReadLine();
            }
        }
Exemple #2
0
        public async Task DoSync()
        {
            var newSyncTime = DateTime.UtcNow;

            try
            {
                if (!SyncHelper.HasConnection())
                {
                    return;
                }

                using (var uow = new UnitOfWork())
                {
                    var documentDbSetting = uow.SettingsRepository.FindSingle(x => x.Key == BridgeSettingKeys.DOCUMENT_DB_KEY);
                    var endpointSetting   = uow.SettingsRepository.FindSingle(x => x.Key == BridgeSettingKeys.DOCUMENTDB_ENDPOINT);
                    DocumentDBContext.Initialize(endpointSetting.Value, documentDbSetting.Value);
                    if (DocumentDBContext.Initialized)
                    {
                        try
                        {
                            var lastSyncTime = DateTime.Parse(uow.SettingsRepository.GetSettingWithDefault(BridgeSettingKeys.LAST_SYNC_TIME, "01/01/2019"));
                            lastSyncTime = lastSyncTime.AddMinutes(-1);

                            await ExecuteSteps(uow, lastSyncTime);

                            uow.SettingsRepository.UpsertSetting(BridgeSettingKeys.LAST_SYNC_TIME, newSyncTime.ToString());
                            uow.SaveChanges();
                        }
                        catch (Exception exc)
                        {
                            Logging.Logger.Log(exc);
                        }
                    }
                }
            }
            catch (Exception outerExc)
            {
                Logging.Logger.Log(outerExc);
            }
        }
Exemple #3
0
        private static async Task ClearDownloadedListsData(string appDataPath)
        {
            try
            {
                Console.WriteLine("Releasing downloaded lists...");
                string settingsFile    = appDataPath + "\\Truck\\settings.txt";
                string encryptedString = System.IO.File.ReadAllText(settingsFile);
                string decryptedString = CottonDBMS.Helpers.EncryptionHelper.Decrypt(encryptedString);
                var    parms           = Newtonsoft.Json.JsonConvert.DeserializeObject <TruckAppInstallParams>(decryptedString);

                if (!string.IsNullOrEmpty(parms.EndPoint) &&
                    !string.IsNullOrEmpty(parms.Key) &&
                    !string.IsNullOrEmpty(parms.TruckID))
                {
                    DocumentDBContext.Initialize(parms.EndPoint, parms.Key);

                    Console.WriteLine("Looking for downloaded lists...");
                    var docs = await DocumentDBContext.GetAllItemsAsync <TruckListsDownloaded>(p => p.Id == "TRUCKDOWNLOADS_" + parms.TruckID);

                    if (docs.Count() > 0)
                    {
                        Console.WriteLine("Releasing lists...");
                        //remove document tracking lists this truck has downloaded
                        //this allows them to be released for delete etc at the gin
                        await DocumentDBContext.DeleteItemAsync <TruckListsDownloaded>("TRUCKDOWNLOADS_" + parms.TruckID);
                    }
                }
                else
                {
                    Console.WriteLine("One or more settings null.");
                }
            }
            catch (Exception exc)
            {
                Console.WriteLine(exc.Message);
                Console.WriteLine(exc.StackTrace);
                Console.WriteLine("Press enter to continue.");
                Console.ReadLine();
            }
        }
        private async Task <bool> CreateDatabase()
        {
            DocumentDBContext.Initialize(tbAzureCosmosEndpoint.Text.Trim(), tbAzureKey.Text.Trim());
            bool exists = await DocumentDBContext.DatabaseExistsAsync();

            bool createSucceded = true;

            if (!exists)
            {
                try
                {
                    await DocumentDBContext.CreateDatabaseAsync();
                }
                catch (Exception exc)
                {
                    Logging.Logger.Log(exc);
                    createSucceded = false;
                }
            }

            return(createSucceded);
        }
Exemple #5
0
        public NavViewModel()
        {
            LockSettingsCommand        = new GalaSoft.MvvmLight.CommandWpf.RelayCommand(this.ExecuteLockSettings);
            SavePasswordCommand        = new GalaSoft.MvvmLight.CommandWpf.RelayCommand(this.ExecuteSavePasswordCommand);
            CancelCommand              = new GalaSoft.MvvmLight.CommandWpf.RelayCommand(this.ExecuteCancelCommand);
            UnlockCommand              = new GalaSoft.MvvmLight.CommandWpf.RelayCommand(this.ExecuteUnlockCommand);
            SaveUnlockCommand          = new GalaSoft.MvvmLight.CommandWpf.RelayCommand(this.ExecuteSaveUnlockCommand);
            Drivers                    = new ObservableCollection <ComboBoxItemViewModel>();
            PasswordModalVisible       = false;
            UnlockPasswordModalVisible = false;



            using (var dp = SimpleIoc.Default.GetInstance <IUnitOfWorkFactory>().CreateUnitOfWork())
            {
                var setting = dp.SettingsRepository.FindSingle(k => k.Key == TruckClientSettingKeys.ADMIN_PASSWORD);

                if (setting != null && !string.IsNullOrWhiteSpace(setting.Value))
                {
                    SettingsLocked = true;
                }
                else
                {
                    SettingsLocked = false;
                }

                var documentDbSetting   = dp.SettingsRepository.FindSingle(x => x.Key == TruckClientSettingKeys.DOCUMENT_DB_KEY);
                var syncIntervalSetting = dp.SettingsRepository.FindSingle(x => x.Key == TruckClientSettingKeys.DATA_SYNC_INTERVAL);
                var endpointSetting     = dp.SettingsRepository.FindSingle(x => x.Key == TruckClientSettingKeys.DOCUMENTDB_ENDPOINT);

                string key      = "";
                string endpoint = "";

                if (documentDbSetting != null)
                {
                    key = documentDbSetting.Value;
                }

                if (endpointSetting != null)
                {
                    endpoint = endpointSetting.Value;
                }

                if (string.IsNullOrWhiteSpace(key) || string.IsNullOrWhiteSpace(endpoint))
                {
                    CloudDBInitialized = false;
                    HasCloudSettings   = false;
                }
                else
                {
                    HasCloudSettings = true;
                    try
                    {
                        Task.Run(async() => {
                            DocumentDBContext.Initialize(endpoint, key);
                            if (!await DocumentDBContext.DatabaseExistsAsync())
                            {
                                CloudDBInitialized = true;
                            }
                        });
                    }
                    catch (Exception exc)
                    {
                        Logging.Logger.Log(exc);
                    }
                }
            }
            Messenger.Default.Register <BusyMessage>(this, (action) => ReceiveBusyMessage(action));
            Messenger.Default.Register <DialogClosedMessage>(this, (action => ReceiveDialogClosed(action)));
            Messenger.Default.Register <DialogOpenedMessage>(this, (action => ReceiveDialogOpened(action)));

            refresh();
            Timer timer = new Timer(25000);

            timer.Elapsed += (sender, e) => refresh();
            timer.Start();
        }
        private async Task InitializeDataSourcesAsync()
        {
            using (IUnitOfWork uow = UnitOfWorkFactory.CreateUnitOfWork())
            {
                BusyMessage.Show("Checking for Azure database.", this);
                var    settingsRepo = uow.SettingsRepository;
                string endpoint     = settingsRepo.FindSingle(t => t.Key == GinAppSettingKeys.AZURE_DOCUMENTDB_ENDPOINT).Value;
                string key          = settingsRepo.FindSingle(t => t.Key == GinAppSettingKeys.AZURE_DOCUMENTDB_KEY).Value;

                if (endpoint.ToLower().IndexOf("azure.com") >= 0 && !string.IsNullOrEmpty(key))
                {
                    DocumentDBContext.Initialize(endpoint, key);
                    bool exists = await DocumentDBContext.DatabaseExistsAsync();

                    bool createSucceded = true;
                    if (!exists)
                    {
                        BusyMessage.UpdateMessage("Creating Azure document database..");
                        try
                        {
                            await DocumentDBContext.CreateDatabaseAsync();
                        }
                        catch (Exception exc)
                        {
                            Logging.Logger.Log(exc);
                            createSucceded = false;
                            BusyMessage.UpdateMessage("Creating Azure document database failed.");
                            System.Threading.Thread.Sleep(2000);
                        }
                    }

                    if (createSucceded)
                    {
                        exists = await DocumentDBContext.CollectionExistsAsync();

                        if (!exists)
                        {
                            try
                            {
                                BusyMessage.UpdateMessage("Creating Azure document database collections..");
                                await DocumentDBContext.CreateCollectionAsync();

                                createSucceded = true;
                            }
                            catch (Exception exc)
                            {
                                BusyMessage.UpdateMessage("Creating Azure document database collections failed.");
                                System.Threading.Thread.Sleep(2000);
                                Logging.Logger.Log(exc);
                                createSucceded = false;
                            }
                        }
                    }

                    if (createSucceded)
                    {
                        try
                        {
                            await DocumentDBContext.CreateStoredProceduresAsync();
                        }
                        catch (Exception exc)
                        {
                            BusyMessage.UpdateMessage("Creating database stored procedures failed.");
                            System.Threading.Thread.Sleep(2000);
                            Logging.Logger.Log(exc);
                            createSucceded = false;
                        }
                    }

                    DbIntitialized = true;
                    BusyMessage.Close();
                }
                else
                {
                    BusyMessage.Close();
                    DbIntitialized = false;
                    appTabs.TabPages.Remove(tabHome);
                    appTabs.TabPages.Remove(tabFields);
                    appTabs.TabPages.Remove(tabModules);
                    appTabs.TabPages.Remove(tabPickupLists);
                    appTabs.TabPages.Remove(tabClients);
                    appTabs.TabPages.Remove(tabFarms);
                    appTabs.TabPages.Remove(tabTrucks);
                    appTabs.TabPages.Remove(tabDrivers);
                    appTabs.TabPages.Remove(tabReports);
                    appTabs.TabIndex = 0;
                    MessageBox.Show("Azure Document DB connection settings are missing or incorrect.  Please update Azure information in the Settings tab then restart the application.");
                }
            }
        }
Exemple #7
0
        private async Task <bool> ValidateForm()
        {
            bool isValid = true;

            clearErrors();
            if (string.IsNullOrWhiteSpace(_documentDbConnection))
            {
                isValid = false;
                HasDocumentDbConnectionErrorMessage = true;
                DocumentDbConnectionErrorMessage    = "required";
            }

            if (string.IsNullOrWhiteSpace(DocumentDbEndpoint))
            {
                isValid = false;
                HasDocumentDbEndpointErrorMessage = true;
                DocumentDbEndpointErrorMessage    = "required";
            }
            else if (!ValidationHelper.ValidUrl(DocumentDbEndpoint))
            {
                isValid = false;
                HasDocumentDbEndpointErrorMessage = true;
                DocumentDbEndpointErrorMessage    = "Invalid URL";
            }


            if (!HasDocumentDbConnectionErrorMessage && !HasDocumentDbEndpointErrorMessage)
            {
                try
                {
                    DocumentDBContext.Initialize(_documentDbEndpoint, _documentDbConnection);
                    var trucks = await DocumentDBContext.GetAllItemsAsync <TruckEntity>(p => p.EntityType == EntityType.TRUCK);
                }
                catch (Exception exc)
                {
                    isValid = false;
                    HasDocumentDbEndpointErrorMessage = true;
                    DocumentDbEndpointErrorMessage    = "Unable to connect.";
                    Logging.Logger.Log(exc);
                }
            }

            if (string.IsNullOrWhiteSpace(TareWeight))
            {
                isValid = false;
                HasTareWeightErrorMessage = true;
                TareWeightErrorMessage    = "required";
            }
            else if (!ValidationHelper.ValidDecimal(TareWeight))
            {
                isValid = false;
                HasTareWeightErrorMessage = true;
                TareWeightErrorMessage    = "Invalid decimal number.";
            }


            if (BarcodePortName != "NONE" && BarcodePortName == PortName)
            {
                isValid = false;
                HasBarcodePortErrorMessage = true;
            }

            return(isValid);
        }
        public static async Task DoSync()
        {
            try
            {
                if (!hasConnection())
                {
                    return;
                }

                using (var uow = new UnitOfWork())
                {
                    var documentDbSetting = uow.SettingsRepository.FindSingle(x => x.Key == TruckClientSettingKeys.DOCUMENT_DB_KEY);
                    var endpointSetting   = uow.SettingsRepository.FindSingle(x => x.Key == TruckClientSettingKeys.DOCUMENTDB_ENDPOINT);
                    DocumentDBContext.Initialize(endpointSetting.Value, documentDbSetting.Value);

                    //return;
                    if (DocumentDBContext.Initialized)
                    {
                        try
                        {
                            var truck = uow.SettingsRepository.GetCurrentTruck();

                            List <PickupListEntity> pickupLists = new List <PickupListEntity>();

                            Logging.Logger.Log("INFO", "Fetching pickuplists.");
                            if (truck != null)
                            {
                                //process deleted documents - this mainly cleans out the Docs to process table
                                //except for PickupLists if the truck deleted a pickup list a Release request doc is put in the cloud
                                //so the gin can remove the truck assignment
                                List <TruckPickupListRelease> releaseDocs = new List <TruckPickupListRelease>();

                                //get all lists that have been released by this truck previously
                                await processDeletedDocuments(uow, token, truck.Id, releaseDocs);

                                var cloudReleaseDocs = await DocumentDBContext.GetAllItemsAsync <TruckPickupListRelease>(x => x.TruckID == truck.Id);

                                releaseDocs.AddRange(cloudReleaseDocs);
                                var tempLists = await DocumentDBContext.GetAllItemsAsync <PickupListEntity>(p => p.EntityType == EntityType.PICKUPLIST && p.Source == InputSource.GIN && p.AssignedTruckIDs.Contains(truck.Id), 100);

                                foreach (var list in tempLists)  //only add lists that have not been released by truck
                                {
                                    if (!releaseDocs.Any(x => x.PickupListID == list.Id))
                                    {
                                        pickupLists.Add(list);
                                    }
                                }
                            }

                            //immediately mark lists that have been downloaded
                            TruckListsDownloaded document = new TruckListsDownloaded();
                            document.Id                    = "TRUCKDOWNLOADS_" + truck.Id;
                            document.Name                  = truck.Id;
                            document.Source                = InputSource.TRUCK;
                            document.SyncedToCloud         = true;
                            document.Created               = DateTime.UtcNow;
                            document.PickupListsDownloaded = new List <string>();
                            document.PickupListsDownloaded.AddRange(pickupLists.Select(x => x.Id).ToArray());
                            await DocumentDBContext.UpsertItemAsync <TruckListsDownloaded>(document);


                            var driver = uow.SettingsRepository.GetCurrentDriver();

                            if (truck == null || driver == null)
                            {
                                return;                                   //only sync if a truck and driver is configured
                            }
                            //pull down clients/farms/fields/trucks and pickuplists
                            Logging.Logger.Log("INFO", "Downloading  data.");
                            var clients = await DocumentDBContext.GetAllItemsAsync <ClientEntity>(p => p.EntityType == EntityType.CLIENT && p.Source == InputSource.GIN, 500);

                            var farms = await DocumentDBContext.GetAllItemsAsync <FarmEntity>(p => p.EntityType == EntityType.FARM && p.Source == InputSource.GIN, 500);

                            var fields = await DocumentDBContext.GetAllItemsAsync <FieldEntity>(p => p.EntityType == EntityType.FIELD && p.Source == InputSource.GIN, 500);

                            var trucks = await DocumentDBContext.GetAllItemsAsync <TruckEntity>(p => p.EntityType == EntityType.TRUCK);

                            var drivers = await DocumentDBContext.GetAllItemsAsync <DriverEntity>(p => p.EntityType == EntityType.DRIVER);

                            var syncedSettings = await DocumentDBContext.GetAllItemsAsync <SyncedSettings>(p => p.EntityType == EntityType.SETTING_SUMMARY);

                            var clientIdsToIgnore = new List <string>();
                            clientIdsToIgnore.Add(GUIDS.UNASSIGNED_CLIENT_ID);

                            var farmIdsToIgnore = new List <string>();
                            farmIdsToIgnore.Add(GUIDS.UNASSIGNED_FARM_ID);

                            var fieldIdsToIgnore = new List <string>();
                            fieldIdsToIgnore.Add(GUIDS.UNASSIGNED_FIELD_ID);

                            var listIdsToIgnore = new List <string>();
                            listIdsToIgnore.Add(GUIDS.UNASSIGNED_LIST_ID);


                            Logging.Logger.Log("INFO", "Fetching local  data.");
                            var localClients        = uow.ClientRepository.GetAll().Where(c => c.Id != GUIDS.UNASSIGNED_CLIENT_ID);
                            var localFarms          = uow.FarmRepository.GetAll().Where(c => c.Id != GUIDS.UNASSIGNED_FARM_ID);
                            var localFields         = uow.FieldRepository.GetAll().Where(c => c.Id != GUIDS.UNASSIGNED_FIELD_ID);
                            var localSyncedSettings = uow.SyncedSettingsRepo.GetAll();
                            var localPickupLists    = uow.PickupListRepository.GetAll(new string[] { "DownloadedToTrucks", "AssignedTrucks", "Field.Farm.Client" }).Where(c => c.Id != GUIDS.UNASSIGNED_LIST_ID);
                            var localModules        = uow.ModuleRepository.GetAll(new string[] { "Field.Farm.Client", "PickupList" });
                            var localDrivers        = uow.DriverRepository.GetAll();
                            var localTrucks         = uow.TruckRepository.GetAll();

                            var pickUpListIds = pickupLists.Select(t => t.Id).Distinct().ToArray();

                            Logging.Logger.Log("INFO", "Fetching modules");

                            //TODO PICKUPLIST ID
                            var modules = await DocumentDBContext.GetAllItemsAsync <ModuleEntity>(p => p.PickupListId != null && pickUpListIds.Contains(p.PickupListId) && p.EntityType == EntityType.MODULE, 50000);

                            Logging.Logger.Log("INFO", "Computing records to delete.");
                            var fieldsToRemove  = localFields.Where(f => !fields.Any(x => x.Id == f.Id)).ToList();
                            var farmsToRemove   = localFarms.Where(f => !farms.Any(x => x.Id == f.Id)).ToList();
                            var clientsToRemove = localClients.Where(f => !clients.Any(x => x.Id == f.Id)).ToList();
                            var trucksToRemove  = localTrucks.Where(t => !trucks.Any(x => x.Id == t.Id)).ToList();
                            var driversToRemove = localDrivers.Where(d => !drivers.Any(x => x.Id == d.Id)).ToList();
                            var listsToRemove   = localPickupLists.Where(p => !pickupLists.Any(x => x.Id == p.Id)).ToList();

                            if (token.IsCancellationRequested)
                            {
                                return;
                            }

                            //if there are items that were deleted at gin but got linked to truck entered data before
                            //truck data was synced then mark records to be sent to gin again to preserve
                            //data integrity
                            if (truck != null && trucksToRemove.Any(t => t.Id == truck.Id))
                            {
                                truck.Source  = InputSource.TRUCK;
                                truck.Updated = DateTime.UtcNow;
                                uow.TruckRepository.Update(truck);
                                uow.SaveChanges();
                            }

                            if (token.IsCancellationRequested)
                            {
                                return;
                            }

                            if (driver != null && driversToRemove.Any(d => d.Id == driver.Id))
                            {
                                driver.Source  = InputSource.TRUCK;
                                driver.Updated = DateTime.UtcNow;
                                uow.DriverRepository.Update(driver);
                                uow.SaveChanges();
                            }

                            ///////////// THIS SECTION COULD PROBABLY BE REMOVED SINCE WE ARE PREVENTING DELETE OF LISTS ONCE DOWNLOADED //////////////////////
                            foreach (var list in listsToRemove) //if list was removed at gin but had modules added, force it to be re-added
                            {
                                bool canDelete     = true;
                                var  cloudDocument = await DocumentDBContext.GetItemAsync <PickupListEntity>(list.Id);

                                //make sure modules get put back in cloud for reassignment
                                //TODO PICKUPLISTID
                                foreach (var m in localModules.Where(m => m.PickupListId == list.Id))
                                {
                                    var eventsWithSerial = uow.AggregateEventRepository.FindMatching(evt => evt.SerialNumber == m.Name).ToList();
                                    if (eventsWithSerial.Count() > 0)
                                    {
                                        canDelete = false;
                                        m.Source  = InputSource.TRUCK;
                                        m.Updated = DateTime.UtcNow;
                                        uow.ModuleRepository.Update(m);
                                    }
                                }

                                //TODO PICKUPLISTID
                                if (localModules.Any(m => m.PickupListId == list.Id) && !canDelete)
                                {
                                    list.Source  = InputSource.TRUCK;
                                    list.Updated = DateTime.UtcNow;
                                    uow.PickupListRepository.Update(list);

                                    if (cloudDocument != null) //list is in cloud but this truck was removed - add to ignored list to prevent overwriting
                                    {
                                        listIdsToIgnore.Add(list.Id);
                                    }
                                }
                            }
                            uow.SaveChanges();

                            foreach (var list in localPickupLists.Where(p => p.Source == InputSource.TRUCK))
                            {
                                if (token.IsCancellationRequested)
                                {
                                    return;
                                }

                                var field = localFields.SingleOrDefault(x => x.Id == list.FieldId);
                                if (field != null && fieldsToRemove.Any(x => x.Id == field.Id))
                                {
                                    field.Source  = InputSource.TRUCK;
                                    field.Updated = DateTime.UtcNow;
                                    uow.FieldRepository.Update(field);

                                    if (farmsToRemove.Any(x => x.Id == field.FarmId))
                                    {
                                        field.Farm.Source = InputSource.TRUCK;
                                        field.Updated     = DateTime.UtcNow;
                                        uow.FarmRepository.Update(field.Farm);
                                    }

                                    if (clientsToRemove.Any(x => x.Id == field.Farm.Client.Id))
                                    {
                                        field.Farm.Client.Source  = InputSource.TRUCK;
                                        field.Farm.Client.Updated = DateTime.UtcNow;
                                    }
                                }
                            }
                            uow.SaveChanges();

                            ///////////// THE ABOVE SECTION COULD PROBABLY BE REMOVED SINCE WE ARE PREVENTING DELETE OF LISTS ONCE DOWNLOADED //////////////////////

                            if (token.IsCancellationRequested)
                            {
                                return;
                            }

                            await pushEntitiesOfType <DriverEntity>(uow, uow.DriverRepository, token, drivers, new List <string>());
                            await pushEntitiesOfType <TruckEntity>(uow, uow.TruckRepository, token, trucks, new List <string>());

                            await pushEntitiesOfType <ClientEntity>(uow, uow.ClientRepository, token, clients, clientIdsToIgnore);
                            await pushEntitiesOfType <FarmEntity>(uow, uow.FarmRepository, token, farms, farmIdsToIgnore);
                            await pushEntitiesOfType <FieldEntity>(uow, uow.FieldRepository, token, fields, fieldIdsToIgnore);
                            await pushEntitiesOfType <PickupListEntity>(uow, uow.PickupListRepository, token, pickupLists, listIdsToIgnore);

                            await pushModules(uow, uow.ModuleRepository, token, modules);

                            if (token.IsCancellationRequested)
                            {
                                return;
                            }

                            using (var addWork = new UnitOfWork())
                            {
                                addWork.DisableChangeTracking();
                                addEntitiesOfType <DriverEntity>(addWork, addWork.DriverRepository, token, drivers, localDrivers);
                                addEntitiesOfType <TruckEntity>(addWork, addWork.TruckRepository, token, trucks, localTrucks);
                                addEntitiesOfType <ClientEntity>(addWork, addWork.ClientRepository, token, clients, localClients);
                                addEntitiesOfType <FarmEntity>(addWork, addWork.FarmRepository, token, farms, localFarms);
                                addEntitiesOfType <FieldEntity>(addWork, addWork.FieldRepository, token, fields, localFields);
                                addEntitiesOfType <PickupListEntity>(addWork, addWork.PickupListRepository, token, pickupLists, localPickupLists);
                                addEntitiesOfType <SyncedSettings>(addWork, addWork.SyncedSettingsRepo, token, syncedSettings, localSyncedSettings);
                                addEntitiesOfType <ModuleEntity>(addWork, addWork.ModuleRepository, token, modules, localModules);
                            }

                            if (token.IsCancellationRequested)
                            {
                                return;
                            }

                            using (var updateWork = new UnitOfWork())
                            {
                                updateWork.DisableChangeTracking();
                                updateEntitiesOfType <DriverEntity>(updateWork, updateWork.DriverRepository, token, drivers, localDrivers, false);
                                updateEntitiesOfType <TruckEntity>(updateWork, updateWork.TruckRepository, token, trucks, localTrucks, true);
                                updateEntitiesOfType <ClientEntity>(updateWork, updateWork.ClientRepository, token, clients, localClients, false);
                                updateEntitiesOfType <FarmEntity>(updateWork, updateWork.FarmRepository, token, farms, localFarms, false);
                                updateEntitiesOfType <FieldEntity>(updateWork, updateWork.FieldRepository, token, fields, localFields, false);
                                updateEntitiesOfType <PickupListEntity>(updateWork, updateWork.PickupListRepository, token, pickupLists, localPickupLists, false);
                                updateEntitiesOfTypeIfNewer <ModuleEntity>(updateWork, updateWork.ModuleRepository, token, modules, localModules, false);
                                updateEntitiesOfType <SyncedSettings>(updateWork, updateWork.SyncedSettingsRepo, token, syncedSettings, localSyncedSettings, false);
                            }

                            if (token.IsCancellationRequested)
                            {
                                return;
                            }

                            deleteEntitiesOfType <DriverEntity>(uow, uow.DriverRepository, token, drivers);
                            deleteEntitiesOfType <TruckEntity>(uow, uow.TruckRepository, token, trucks);
                            deleteEntitiesOfType <ModuleEntity>(uow, uow.ModuleRepository, token, modules);
                            deleteEntitiesOfType <PickupListEntity>(uow, uow.PickupListRepository, token, pickupLists);
                            deleteEntitiesOfType <FieldEntity>(uow, uow.FieldRepository, token, fields);
                            deleteEntitiesOfType <FarmEntity>(uow, uow.FarmRepository, token, farms);
                            deleteEntitiesOfType <ClientEntity>(uow, uow.ClientRepository, token, clients);

                            cleanDupedModules(uow, uow.ModuleRepository, token);


                            if (truck != null)
                            {
                                //send aggregate events to cloud
                                Logging.Logger.Log("INFO", "Send aggregate events");
                                foreach (var moduleEvent in uow.AggregateEventRepository.GetDirtyOrderedByTime())
                                {
                                    if (token.IsCancellationRequested)
                                    {
                                        return;
                                    }
                                    if (truck != null)
                                    {
                                        moduleEvent.TruckID = truck.Id;
                                    }
                                    if (driver != null)
                                    {
                                        moduleEvent.DriverID = driver.Id;
                                    }
                                    moduleEvent.Source = InputSource.TRUCK;

                                    //lookup module
                                    var module = uow.ModuleRepository.FindSingle(m => m.Name == moduleEvent.SerialNumber, "Field.Farm.Client", "PickupList");

                                    //add on field/farm/client/pickup list info it may be needed to re-create list at gin
                                    if (module != null)
                                    {
                                        moduleEvent.PickupListId   = module.PickupListId;
                                        moduleEvent.PickupListName = module.ListName;

                                        if (module.Field != null)
                                        {
                                            moduleEvent.FarmId = module.Field.FarmId;
                                        }

                                        moduleEvent.FarmName  = module.FarmName;
                                        moduleEvent.FieldId   = module.FieldId;
                                        moduleEvent.FieldName = module.FieldName;
                                        moduleEvent.ModuleId  = module.Id;

                                        if (module.Field.Farm != null)
                                        {
                                            moduleEvent.ClientId = module.Field.Farm.ClientId;
                                        }

                                        moduleEvent.ClientName = module.ClientName;
                                    }

                                    await DocumentDBContext.UpsertItemAsync <AggregateEvent>(moduleEvent);

                                    uow.AggregateEventRepository.Update(moduleEvent, true);
                                    uow.SaveChanges();
                                }

                                if (token.IsCancellationRequested)
                                {
                                    return;
                                }

                                //send list of pickup lists this truck has
                                Logging.Logger.Log("INFO", "Send list of pickup lists this truck has downloaded.");
                                var lists = uow.PickupListRepository.FindMatching(t => t.AssignedTrucks.Any(x => x.Id == truck.Id), new string[] { "AssignedTrucks" });
                                TruckListsDownloaded document2 = new TruckListsDownloaded();
                                document2.Id                    = "TRUCKDOWNLOADS_" + truck.Id;
                                document2.Name                  = truck.Id;
                                document2.Source                = InputSource.TRUCK;
                                document2.SyncedToCloud         = true;
                                document2.Created               = DateTime.UtcNow;
                                document2.PickupListsDownloaded = new List <string>();
                                document2.PickupListsDownloaded.AddRange(lists.Select(x => x.Id).ToArray());
                                await DocumentDBContext.UpsertItemAsync <TruckListsDownloaded>(document2);
                            }
                        }
                        catch (Exception exc)
                        {
                            Logging.Logger.Log(exc);
                        }
                    }
                }
            }
            catch (Exception outerExc)
            {
                Logging.Logger.Log(outerExc);
            }
        }