Пример #1
0
        /// <summary>
        /// Authenticate the subscriber
        /// </summary>
        /// <returns>The authenticate.</returns>
        /// <param name="username">Subscriber identifier.</param>
        /// <param name="password">Password.</param>
        async public static Task <AuthenticationResult> Authenticate(Repository repository, string username, string password)
        {
            var syncResult = new SyncResult();

            var logger = ServiceLocator.Current.GetInstance <IDeviceManager>();

            var currentProfile = repository.Profiles.FirstOrDefault();

            // no profile or different profile - perform an initial sync
            if (currentProfile == null || !currentProfile.SubscriberID.Equals(username, StringComparison.OrdinalIgnoreCase))
            {
                // perform an initial sync
                logger.LogEvent("Perform initial sync");
                syncResult = await ApiClient.Instance.PerfomInitialSyncAsync(username, password);

                if (syncResult.IsSuccessStatusCode)
                {
                    return(AuthenticationResult.Authenticated);
                }

                return(syncResult.StatusCode == System.Net.HttpStatusCode.RequestTimeout ? AuthenticationResult.Timeout :
                       AuthenticationResult.RemoteAuthenticationFailed);
            }


            return(!currentProfile.Password.Equals(password, StringComparison.OrdinalIgnoreCase) ? AuthenticationResult.InvalidPassword :
                   AuthenticationResult.Authenticated);
        }
Пример #2
0
        /// <summary>
        /// Sync the Current Subscription
        /// </summary>
        /// <returns>The current subscription async.</returns>
        public async Task <SyncResult> SyncCurrentSubscriptionAsync()
        {
            SyncResult syncResult = null;

            using (var repository = new Repository())
            {
                var profile = repository.Profiles.FirstOrDefault();

                if (profile == null)
                {
                    syncResult = new SyncResult {
                        StatusCode = HttpStatusCode.OK
                    };
                    return(syncResult);
                }

                var device = repository.MobileDevices.FirstOrDefault();

                _createProfile = false;

                var url = string.Format("{0}/{1}", BaseUrl, device.Timestamp);
                syncResult = await SynchroniseAsync(repository, profile.SubscriberID,
                                                    profile.Password, url, device).ConfigureAwait(false);

                return(syncResult);
            }
        }
Пример #3
0
        void Merge(SyncResult response)
        {
            using (var repository = new Repository())
            {
                var tasks = new List <Task>();

                // get all syncing pending dockets
                var dockets = repository.DeliveryDockets
                              .Where(x => _syncedDockets.Contains(x.DocketID))
                              .ToList();

                // update the status to synced
                dockets.ForEach(docket =>
                {
                    docket.Synced = true;
                });

                // remove dockets older than 24 hours ago that have been
                // committed and synced
                var oldDockets = dockets.Where(x =>
                {
                    var timespan = DateTimeOffset.UtcNow.ToLocalTime().Subtract(x.DateModifiedDate);
                    return(timespan.Hours > 36 && x.Committed && x.Synced);
                }).ToList();

                // remove the old dockets
                oldDockets.ForEach(docket =>
                {
                    var docketItems = repository.DeliveryDocketItems
                                      .Where(x => x.DeliveryDocketID == docket.DocketID)
                                      .ToList();

                    repository.RemoveRange(docketItems);

                    if (File.Exists(docket.SignaturePath))
                    {
                        File.Delete(docket.SignaturePath);
                    }

                    repository.Remove(docket);
                });


                // remove non deliveries
                var nonDeliveries = repository.NonDeliveries
                                    .Where(x => _syncedNonDeliveries.Contains(x.Id))
                                    .ToList();

                repository.RemoveRange(nonDeliveries);


                Merge(response.DownloadResponse.Runs, repository, false);
                Merge(response.DownloadResponse.Calls, repository, false);
                Merge(response.DownloadResponse.LendingStatus, repository, true);
                Merge(response.DownloadResponse.Orders, repository, true);
                Merge(response.DownloadResponse.OrderItems, repository, true);
                Merge(response.DownloadResponse.Products, repository, true);
                Merge(response.DownloadResponse.NonDeliveryReasons, repository, true);
                Merge(response.DownloadResponse.Trailers, repository, true);
                Merge(response.DownloadResponse.History, repository, true);
                Merge(response.DownloadResponse.DriverStock, repository, true);
                Merge(response.DownloadResponse.Customers, repository, true);

                // if the call has an order, then it is not visited
                var calls = repository.Calls.Where(x => x.OrderNumber != null).ToList();

                calls.ForEach(call =>
                {
                    call.SetVisited(false);
                });

                // sort calls - there is no guarantee that the seq. we get is going to be
                // unique. This causes problems when moving calls with the same seq.
                // to prevent this we order calls by seq. but then set the seq. to the index
                var runs = repository.Runs.ToList();

                runs.ForEach((run) =>
                {
                    // order by sequence initially
                    calls = repository.Calls.Where(x => x.RunNumber == run.RunNumber)
                            .OrderBy(x => x.VisitedDate)
                            .ThenBy(x => x.Sequence)
                            .ToList();

                    // then by array index so we have a unique sort order
                    for (var i = 0; i < calls.Count; i++)
                    {
                        var call      = calls[i];
                        call.Sequence = i;
                    }
                });


                var modifiedDevice = response.DownloadResponse.MobileDevice;
                var existingDevice = repository.MobileDevices.FirstOrDefault(x => x.UniqueDeviceID == modifiedDevice.UniqueDeviceID);

                if (existingDevice == null)
                {
                    repository.MobileDevices.Add(modifiedDevice);
                }
                else
                {
                    repository.Entry(existingDevice).CurrentValues.SetValues(modifiedDevice);
                }

                var modifiedSubscriber = response.DownloadResponse.Subscriber;
                var existingSubscriber = repository.Subscribers.FirstOrDefault(x => x.ID == modifiedSubscriber.ID);

                if (existingSubscriber == null)
                {
                    var subscribers = repository.Subscribers;
                    repository.RemoveRange(subscribers);

                    repository.Subscribers.Add(modifiedSubscriber);
                }
                else
                {
                    repository.Entry(existingSubscriber).CurrentValues.SetValues(modifiedSubscriber);
                }


                Profile profile;

                if (_createProfile)
                {
                    var profiles = repository.Profiles;
                    repository.RemoveRange(profiles);

                    profile = new Profile
                    {
                        ParentSubscriberID = modifiedSubscriber.ParentSubscriberID,
                        Password           = response.Password,
                        SubscriberID       = modifiedSubscriber.ID,
                        DriverID           = modifiedSubscriber.DriverID,
                        TimeStamp          = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
                        LastSyncDate       = DateTimeOffset.UtcNow,
                        EditRuns           = modifiedSubscriber.EditRuns
                    };

                    repository.Add(profile);
                }

                // update the profile timestamp if it exists
                profile = repository.Profiles.FirstOrDefault();

                if (profile != null)
                {
                    profile.TimeStamp    = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
                    profile.LastSyncDate = DateTimeOffset.UtcNow;
                }

                repository.SaveChanges();
            }
        }
Пример #4
0
        /// <summary>
        /// Synchronise Async
        /// </summary>
        /// <returns>The async.</returns>
        /// <param name="subscriberId">Username.</param>
        /// <param name="password">Password.</param>
        /// <param name="url">URL.</param>
        async Task <SyncResult> SynchroniseAsync(Repository repository, string subscriberId, string password, string url, MobileDevice device)
        {
            var deviceManager = ServiceLocator.Current.GetInstance <IDeviceManager>();

            device.UniqueDeviceID = deviceManager.GetUniqueDeviceId();

            deviceManager.LogEvent($"Sync In Progress At: {DateTime.Now}");

            // clear sync logs
            _syncedDockets.Clear();
            _syncedNonDeliveries.Clear();

            var profile = repository.Profiles.FirstOrDefault();

            var syncLog = new SyncLog
            {
                SubscriberID = subscriberId,
                AppVersion   = AppInfo.VersionString,
                Build        = AppInfo.BuildString,
                DeviceID     = device.UniqueDeviceID,
                Model        = DeviceInfo.Model,
                Version      = DeviceInfo.VersionString,
                Manufacturer = DeviceInfo.Manufacturer
            };

            var request = new UploadRequest
            {
                MobileDevice = device,
                SyncLog      = syncLog
            };

            // get profile data
            if (profile != null)
            {
                // get runs
                request.Runs = repository.Runs
                               .Where(x => x.Timestamp >= profile.TimeStamp).ToList();

                // get calls
                request.Calls = repository.Calls
                                .Where(x => x.Timestamp >= profile.TimeStamp).ToList();

                var dockets = repository.DeliveryDockets
                              .Where(x => x.Committed && !x.Synced)
                              .ToList();

                dockets.ForEach(docket =>
                {
                    docket.DeliveryDocketItems = repository.DeliveryDocketItems
                                                 .Where(x => x.DeliveryDocketID == docket.DocketID)
                                                 .ToList();
                });

                // get dockets
                request.DeliveryDockets = dockets;

                _syncedDockets = request.DeliveryDockets
                                 .Select(x => x.DocketID)
                                 .ToList();

                // get non deliveries
                request.NonDeliveries = repository.NonDeliveries
                                        .ToList();

                _syncedNonDeliveries = request.NonDeliveries
                                       .Select(x => x.Id)
                                       .ToList();

                // get driver stock
                request.DriverStock = repository.DriverStock
                                      .ToList();

                // get completed orders
                request.CompletedOrders = repository.Orders
                                          .Where(x => x.Completed)
                                          .Select(x => x.OrderNumber)
                                          .ToList();

                request.Orders = repository.Orders
                                 .Where(x => x.Completed).ToList();

                if (request.DeliveryDockets.Any())
                {
                    request.MobileDevice.LatestDocketID = request.DeliveryDockets
                                                          .OrderByDescending(x => x.DateModifiedDate)
                                                          .First().DocketID;
                }

                request.MobileDevice.SyncDate = DateTime.Now.ToLocalTime();
            }

            // serialize sync request
            var content = SerializeSyncRequest(request);

            // set the authorization header
            SetAuthorizationHeader(subscriberId, password);

            SyncResult syncResult;

            try
            {
                using (var response = await _client.PostAsync(url, content).ConfigureAwait(false))
                    using (var stream = await response.Content.ReadAsStreamAsync())
                        using (var reader = new StreamReader(stream))
                            using (var json = new JsonTextReader(reader))
                            {
                                var dict = new Dictionary <string, string>
                                {
                                    { "User", subscriberId },
                                    { "Url", url },
                                    { "Status Code", response.StatusCode.ToString() },
                                    { "Reason Phrase", response.ReasonPhrase }
                                };

                                syncResult = new SyncResult
                                {
                                    IsSuccessStatusCode = response.IsSuccessStatusCode,
                                    ReasonPhrase        = response.ReasonPhrase,
                                    StatusCode          = response.StatusCode
                                };

                                deviceManager.LogEvent($"Sync Completed At: {DateTime.Now} With Status: {response.StatusCode}");

                                if (syncResult.IsSuccessStatusCode)
                                {
                                    syncResult.DownloadResponse = _serializer
                                                                  .Deserialize <DownloadResponse>(json);

                                    // store the password
                                    syncResult.Password = password;

                                    Merge(syncResult);
                                }
                            }


                //var response = await _client.PostAsync(url, content).ConfigureAwait(false);

                //var dict = new Dictionary<string, string>
                //{
                //    { "User", subscriberId },
                //    { "Url", url },
                //    { "Status Code", response.StatusCode.ToString() },
                //    { "Reason Phrase", response.ReasonPhrase }
                //};

                //deviceManager.LogEvent("SynchroniseAsync", dict);

                //syncResult = new SyncResult
                //{
                //    IsSuccessStatusCode = response.IsSuccessStatusCode,
                //    ReasonPhrase = response.ReasonPhrase,
                //    StatusCode = response.StatusCode
                //};

                //if (syncResult.IsSuccessStatusCode)
                //{
                //    using (var stream = await response.Content.ReadAsStreamAsync())
                //    using (var reader = new StreamReader(stream))
                //    using (var json = new JsonTextReader(reader))
                //    {
                //        syncResult.DownloadResponse = _serializer
                //            .Deserialize<DownloadResponse>(json);

                //        // store the password
                //        syncResult.Password = password;

                //        Merge(syncResult);

                //    }
                //}

                return(syncResult);
            }
            catch (Exception exception)
            {
                if (exception.InnerException != null)
                {
                    System.Diagnostics.Debug.WriteLine($"EXCEPTION: {exception.InnerException.Message}");
                }
                else
                {
                    System.Diagnostics.Debug.WriteLine($"EXCEPTION: {exception.Message}");
                }

                deviceManager.LogException(exception);

                syncResult = new SyncResult()
                {
                    IsSuccessStatusCode = false,
                    StatusCode          = HttpStatusCode.RequestTimeout
                };

                return(syncResult);
            }
        }