/// <summary>
        /// Executes the application workflow.
        /// </summary>
        private async Task Execute()
        {
            Console.ForegroundColor = ConsoleColor.White;
            ConsoleUtility.LogUtilityStartup(UtilityName);

            // Get configurtaion information.
            configItems = GeotabSdkUtility.GetConfigItems("configuration");

            string resellerName, resellerErpAccountId, customerCompanyName, customerAccountAdminFirstName, customerAccountAdminLastName, customerAccountAdminEmail, customerPhoneNumber, customerFleetSize, customerSignUpForNews, customerDesiredDatabaseName, customerTimeZoneId, customerDeviceListPath;

            resellerName                  = configItems.Where(configItem => configItem.Key == ArgNameResellerName).FirstOrDefault().Value;
            resellerErpAccountId          = configItems.Where(configItem => configItem.Key == ArgNameResellerErpAccountId).FirstOrDefault().Value;
            customerCompanyName           = configItems.Where(configItem => configItem.Key == ArgNameCustomerCompanyName).FirstOrDefault().Value;
            customerAccountAdminFirstName = configItems.Where(configItem => configItem.Key == ArgNameCustomerAccountAdminFirstName).FirstOrDefault().Value;
            customerAccountAdminLastName  = configItems.Where(configItem => configItem.Key == ArgNameCustomerAccountAdminLastName).FirstOrDefault().Value;
            customerAccountAdminEmail     = configItems.Where(configItem => configItem.Key == ArgNameCustomerAccountAdminEmail).FirstOrDefault().Value;
            customerPhoneNumber           = configItems.Where(configItem => configItem.Key == ArgNameCustomerPhoneNumber).FirstOrDefault().Value;
            customerFleetSize             = configItems.Where(configItem => configItem.Key == ArgNameCustomerFleetSize).FirstOrDefault().Value;
            customerSignUpForNews         = configItems.Where(configItem => configItem.Key == ArgNameCustomerSignUpForNews).FirstOrDefault().Value;
            customerDesiredDatabaseName   = configItems.Where(configItem => configItem.Key == ArgNameCustomerDesiredDatabaseName).FirstOrDefault().Value;
            customerTimeZoneId            = configItems.Where(configItem => configItem.Key == ArgNameCustomerTimeZoneId).FirstOrDefault().Value;
            customerDeviceListPath        = configItems.Where(configItem => configItem.Key == ArgNameCustomerDeviceListPath).FirstOrDefault().Value;

            // Validate input values.
            ConsoleUtility.LogInfoStart("Validating input parameter values...");
            // OPTIONAL: Validate email address if enforcing the use of email addresses for usernames.
            // customerAccountAdminEmail = ValidationUtility.ValidateEmailAddress(customerAccountAdminEmail);
            customerFleetSize             = ValidationUtility.ValidateStringIsInt32(customerFleetSize, "customer fleet size");
            customerSignUpForNews         = ValidationUtility.ValidateStringIsBoolean(customerSignUpForNews, "customer's desire to sign-up for news");
            resellerName                  = ValidationUtility.ValidateStringLength(resellerName, 3, ArgNameResellerName);
            resellerErpAccountId          = ValidationUtility.ValidateStringLength(resellerErpAccountId, 6, ArgNameResellerErpAccountId);
            customerCompanyName           = ValidationUtility.ValidateStringLength(customerCompanyName, 3, ArgNameCustomerCompanyName);
            customerAccountAdminFirstName = ValidationUtility.ValidateStringLength(customerAccountAdminFirstName, 1, ArgNameCustomerAccountAdminFirstName);
            customerAccountAdminLastName  = ValidationUtility.ValidateStringLength(customerAccountAdminLastName, 1, ArgNameCustomerAccountAdminLastName);
            customerPhoneNumber           = ValidationUtility.ValidateStringLength(customerPhoneNumber, 10, ArgNameCustomerPhoneNumber);
            customerDesiredDatabaseName   = ValidationUtility.ValidateStringLength(customerDesiredDatabaseName, 3, ArgNameCustomerDesiredDatabaseName);
            customerTimeZoneId            = ValidationUtility.ValidateStringLength(customerTimeZoneId, 3, ArgNameCustomerTimeZoneId);
            customerDeviceListPath        = ValidationUtility.ValidateStringLength(customerDeviceListPath, 3, ArgNameCustomerDeviceListPath);
            ConsoleUtility.LogComplete();

            // Ensure customer device list file exists.
            ConsoleUtility.LogInfoStart("Checking if customer device list file exists...");
            if (!File.Exists(customerDeviceListPath))
            {
                ConsoleUtility.LogInfo($"The file path '{customerDeviceListPath}' entered for '{ArgNameCustomerDeviceListPath}' is not valid.");
                return;
            }
            ConsoleUtility.LogComplete();

            // Authenticate MyAdmin API.
            try
            {
                (myAdminApi, myAdminApiUser, myAdminApiUsername, myAdminApiPassword) = await AdminSdkUtility.AuthenticateMyAdminApi();
            }
            catch (Exception e)
            {
                ConsoleUtility.LogError(e);
                // Provide user with a second authentication attempt.
                (myAdminApi, myAdminApiUser, myAdminApiUsername, myAdminApiPassword) = await AdminSdkUtility.AuthenticateMyAdminApi();
            }

            // Authenticate MyGeotab API.
            myGeotabApi = await GeotabSdkUtility.AuthenticateMyGeotabApiAsync(GeotabServer, "", myAdminApiUsername, myAdminApiPassword);

            // Check whether customer desired database name is already used.  If so, prompt user for
            // alternates until an unused database name is found.
            ConsoleUtility.LogInfoStart($"Checking whether database name '{customerDesiredDatabaseName}' is available...");
            if (await GeotabSdkUtility.DatabaseExistsAsync(myGeotabApi, customerDesiredDatabaseName))
            {
                bool   tryAnotherDatabaseName = true;
                string proposedDatabaseName   = string.Empty;
                while (tryAnotherDatabaseName)
                {
                    customerDesiredDatabaseName = ConsoleUtility.GetUserInput($"a different database name ('{customerDesiredDatabaseName}' is already used)");
                    tryAnotherDatabaseName      = await GeotabSdkUtility.DatabaseExistsAsync(myGeotabApi, customerDesiredDatabaseName);
                }
            }
            else
            {
                ConsoleUtility.LogComplete();
            }

            // Get the password to be used for the customer's administrative user account which will be created in the customer dataabse.
            string customerAccountAdminPassword = ConsoleUtility.GetVerifiedUserInputMasked($"Desired MyGeotab password for '{customerAccountAdminEmail}' to access '{customerDesiredDatabaseName}' database", $"[RE-ENTER] desired MyGeotab password for '{customerAccountAdminEmail}' to access '{customerDesiredDatabaseName}' database");

            customerAccountAdminPassword = ValidationUtility.ValidatePassword(customerAccountAdminPassword);

            // Validate input parameters that require API access.
            customerTimeZoneId = await GeotabSdkUtility.ValidateTimeZoneIdAsync(myGeotabApi, customerTimeZoneId);

            // Create customer database.
            string createDatabaseResult = await GeotabSdkUtility.CreateDatabaseAsync(myGeotabApi, customerDesiredDatabaseName, myAdminApiUsername
                                                                                     , myAdminApiPassword, customerCompanyName, customerAccountAdminFirstName
                                                                                     , customerAccountAdminLastName, customerPhoneNumber, resellerName, Int32.Parse(customerFleetSize)
                                                                                     , bool.Parse(customerSignUpForNews), customerTimeZoneId);

            // Get the server and database information for the new database.
            string[] serverAndDatabase      = (createDatabaseResult).Split('/');
            string   customerDatabaseServer = serverAndDatabase.First();
            string   customerDatabase       = serverAndDatabase.Last();

            // Authenticate MyGeotab API against the newly-created database:
            myGeotabApi = await GeotabSdkUtility.AuthenticateMyGeotabApiAsync(customerDatabaseServer, customerDatabase, myAdminApiUsername, myAdminApiPassword);

            // Create administrative user in customer database for customer administrator to use.
            IList <User>  existingUsers = new List <User>();
            IList <Group> companyGroups = await GeotabSdkUtility.GetCompanyGroupsAsync(myGeotabApi);

            IList <Group> securityGroups = await GeotabSdkUtility.GetSecurityGroupsAsync(myGeotabApi);

            IList <Group> adminSecurityGroup = GeotabSdkUtility.GetSecurityGroupAsList(GeotabSdkUtility.SecurityGroupName.Administrator, securityGroups);
            IList <Group> companyGroup       = GeotabSdkUtility.GetGroupAsList(GeotabSdkUtility.CompanyGroupName, companyGroups);

            User user = User.CreateBasicUser(null, null, customerAccountAdminEmail, customerAccountAdminFirstName, customerAccountAdminLastName, customerAccountAdminPassword, null, null, null, DateTime.MinValue, DateTime.MaxValue, companyGroup, null, adminSecurityGroup, null);

            user.ChangePassword = true;
            if (GeotabSdkUtility.ValidateUser(user, existingUsers))
            {
                try
                {
                    ConsoleUtility.LogInfoStart($"Adding user '{user.Name}' to database '{myGeotabApi.Database}'...");
                    await GeotabSdkUtility.AddUserAsync(myGeotabApi, user);

                    ConsoleUtility.LogComplete();
                    existingUsers.Add(user);
                }
                catch (Exception exception)
                {
                    ConsoleUtility.LogError($"Error adding user '{user.Name}' to database '{myGeotabApi.Database}'\n{exception.Message}");
                }
            }
            else
            {
                return;
            }

            // Load the list of devices to be imported from the CSV file.
            ConsoleUtility.LogInfoStart($"Loading the list of devices to be imported into the '{customerDesiredDatabaseName}' database from file '{customerDeviceListPath}'...");
            IList <DeviceDetails> deviceCandidates = null;

            using (FileStream devicesToImportFile = File.OpenRead(customerDeviceListPath))
            {
                deviceCandidates = devicesToImportFile.CsvToList <DeviceDetails>();
            }
            ConsoleUtility.LogComplete();
            if (!deviceCandidates.Any())
            {
                ConsoleUtility.LogInfo($"No devices were loaded from the CSV file.");
                return;
            }

            // Get existing devices.
            ConsoleUtility.LogInfoStart($"Retrieving device and device database lists...");
            IList <Device> existingDevices = await myGeotabApi.CallAsync <IList <Device> >("Get", typeof(Device));

            var currentDeviceDatabases = await AdminSdkUtility.GetCurrentDeviceDatabases(myAdminApi, myAdminApiUser, resellerErpAccountId);

            ConsoleUtility.LogComplete();

            // Add devices into the MyGeotab database.
            ConsoleUtility.LogInfo($"Processing {deviceCandidates.Count} device(s) - attempting to add to MyGeotab database '{customerDesiredDatabaseName}'.");
            foreach (DeviceDetails deviceCandidate in deviceCandidates)
            {
                IList <Group> deviceGroups = new List <Group>();

                // Use the serial number for the description since it won't likely be known at this point which vehicle the device will be installed into.
                deviceCandidate.Name = deviceCandidate.SerialNumber;
                string deviceCandidateSerialNumber = deviceCandidate.SerialNumber.Replace("-", "");

                // Check if the device is already in any database.
                if (currentDeviceDatabases.Where(database => database.SerialNumber == deviceCandidateSerialNumber).Any())
                {
                    IList <ApiDeviceDatabaseExtended> existingDatabases = currentDeviceDatabases.Where(database => database.SerialNumber == deviceCandidateSerialNumber).ToList();

                    StringBuilder existingDatabaseNames = new();
                    foreach (ApiDeviceDatabaseExtended database in existingDatabases)
                    {
                        if (existingDatabaseNames.Length > 0)
                        {
                            existingDatabaseNames.Append($", '{database.DatabaseName}'");
                        }
                        else
                        {
                            existingDatabaseNames.Append($"'{database.DatabaseName}'");
                        }
                    }
                    ConsoleUtility.LogListItemWithResult($"{deviceCandidate.Name}", $"NOT ADDED: Device already exists in MyGeotab database(s) {existingDatabaseNames}.", ConsoleColor.Red);
                    continue;
                }

                // Assign the device to the Company group.
                deviceGroups.Add(new CompanyGroup());

                // Add the device to the MyGeotab database.
                try
                {
                    // Create the device object.
                    Device newDevice = Device.FromSerialNumber(deviceCandidate.SerialNumber);
                    newDevice.PopulateDefaults();
                    newDevice.Name     = deviceCandidate.Name;
                    newDevice.Groups   = deviceGroups;
                    newDevice.WorkTime = new WorkTimeStandardHours();

                    // Add the device.
                    await myGeotabApi.CallAsync <Id>("Add", typeof(Device), new { entity = newDevice });

                    ConsoleUtility.LogListItemWithResult($"{deviceCandidate.Name}", $"ADDED", ConsoleColor.Green);
                }
                catch (Exception ex)
                {
                    ConsoleUtility.LogListItemWithResult($"{deviceCandidate.Name}", $"NOT ADDED: ERROR adding device: {ex.Message}\n{ex.StackTrace}", ConsoleColor.Red);
                }
            }
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine("Completed processing.");
            Console.ForegroundColor = ConsoleColor.White;
        }
Esempio n. 2
0
        /// <summary>
        /// Executes the application workflow.
        /// </summary>
        private async Task Execute()
        {
            Console.ForegroundColor = ConsoleColor.White;
            ConsoleUtility.LogUtilityStartup(UtilityName);

            // Get configurtaion information.
            configItems = GeotabSdkUtility.GetConfigItems("configuration");

            string resellerErpAccountId, databaseName, devicesToUpdateFilePath;

            resellerErpAccountId    = configItems.Where(configItem => configItem.Key == ArgNameResellerErpAccountId).FirstOrDefault().Value;
            databaseName            = configItems.Where(configItem => configItem.Key == ArgNameDatabaseName).FirstOrDefault().Value;
            devicesToUpdateFilePath = configItems.Where(configItem => configItem.Key == ArgNameDevicesToUpdateFilePath).FirstOrDefault().Value;

            // Validate input values.
            ConsoleUtility.LogInfoStart("Validating input parameter values...");
            resellerErpAccountId    = ValidationUtility.ValidateStringLength(resellerErpAccountId, 6, ArgNameResellerErpAccountId);
            databaseName            = ValidationUtility.ValidateStringLength(databaseName, 3, ArgNameDatabaseName);
            devicesToUpdateFilePath = ValidationUtility.ValidateStringLength(devicesToUpdateFilePath, 3, ArgNameDevicesToUpdateFilePath);
            ConsoleUtility.LogComplete();

            // Ensure devices to update file exists.
            ConsoleUtility.LogInfoStart("Checking if devices to update file exists...");
            if (!File.Exists(devicesToUpdateFilePath))
            {
                ConsoleUtility.LogInfo($"The file path '{devicesToUpdateFilePath}' entered for '{ArgNameDevicesToUpdateFilePath}' is not valid.");
                return;
            }
            ConsoleUtility.LogComplete();

            // Authenticate MyAdmin API.
            try
            {
                (myAdminApi, myAdminApiUser, myAdminApiUsername, myAdminApiPassword) = await AdminSdkUtility.AuthenticateMyAdminApi();
            }
            catch (Exception e)
            {
                ConsoleUtility.LogError(e);
                // Provide user with a second authentication attempt.
                (myAdminApi, myAdminApiUser, myAdminApiUsername, myAdminApiPassword) = await AdminSdkUtility.AuthenticateMyAdminApi();
            }

            // Authenticate MyGeotab API.
            myGeotabApi = await GeotabSdkUtility.AuthenticateMyGeotabApiAsync(GeotabServer, databaseName, myAdminApiUsername, myAdminApiPassword);

            // Load the devices to update from the CSV file.
            ConsoleUtility.LogInfoStart($"Loading the device information that will be used to update devices in the '{databaseName}' database from file '{devicesToUpdateFilePath}'...");
            IList <DeviceDetails> deviceCandidates = null;

            using (FileStream devicesToImportFile = File.OpenRead(devicesToUpdateFilePath))
            {
                deviceCandidates = devicesToImportFile.CsvToList <DeviceDetails>();
            }
            ConsoleUtility.LogComplete();
            if (!deviceCandidates.Any())
            {
                ConsoleUtility.LogInfo($"No devices were loaded from the CSV file.");
                return;
            }

            // Get existing devices.
            ConsoleUtility.LogInfoStart($"Retrieving device and device database lists...");
            IList <Device> existingDevices = await myGeotabApi.CallAsync <IList <Device> >("Get", typeof(Device)) ?? new List <Device>();

            var currentDeviceDatabases = await AdminSdkUtility.GetCurrentDeviceDatabases(myAdminApi, myAdminApiUser, resellerErpAccountId);

            ConsoleUtility.LogComplete();

            // Process device list, adding new devices to the database and updating existing devices.
            ConsoleUtility.LogInfo($"Processing {deviceCandidates.Count} device(s) - attempting to update devices in MyGeotab database '{databaseName}'.");
            foreach (DeviceDetails deviceCandidate in deviceCandidates)
            {
                // Update device if it already exists in the current database.
                if (GeotabSdkUtility.DeviceExists(deviceCandidate.SerialNumber, existingDevices))
                {
                    try
                    {
                        Device deviceToUpdate = existingDevices.Where(device => device.SerialNumber == deviceCandidate.SerialNumber).First();
                        await GeotabSdkUtility.UpdateDeviceAsync(myGeotabApi, deviceToUpdate, deviceCandidate.Name, deviceCandidate.EnableDeviceBeeping, deviceCandidate.EnableDriverIdentificationReminder, deviceCandidate.DriverIdentificationReminderImmobilizeSeconds, deviceCandidate.EnableBeepOnEngineRpm, deviceCandidate.EngineRpmBeepValue, deviceCandidate.EnableBeepOnIdle, deviceCandidate.IdleMinutesBeepValue, deviceCandidate.EnableBeepOnSpeeding, deviceCandidate.SpeedingStartBeepingSpeed, deviceCandidate.SpeedingStopBeepingSpeed, deviceCandidate.EnableBeepBrieflyWhenApprocahingWarningSpeed, deviceCandidate.EnableBeepOnDangerousDriving, deviceCandidate.AccelerationWarningThreshold, deviceCandidate.BrakingWarningThreshold, deviceCandidate.CorneringWarningThreshold, deviceCandidate.EnableBeepWhenSeatbeltNotUsed, deviceCandidate.SeatbeltNotUsedWarningSpeed, deviceCandidate.EnableBeepWhenPassengerSeatbeltNotUsed, deviceCandidate.BeepWhenReversing);

                        ConsoleUtility.LogListItemWithResult($"{deviceCandidate.SerialNumber} ({deviceCandidate.Name})", $"UPDATED", ConsoleColor.Green);
                    }
                    catch (Exception ex)
                    {
                        ConsoleUtility.LogListItemWithResult($"{deviceCandidate.Name}", $"NOT UPDATED: ERROR updating device: {ex.Message}\n{ex.StackTrace}", ConsoleColor.Red);
                    }
                    continue;
                }

                // Device does not exist in the current database.  Instead of updating, try to add the device to the database instead.
                IList <Group> deviceGroups = new List <Group>();

                // Use the serial number for the name if a name is not provided.
                if (string.IsNullOrEmpty(deviceCandidate.Name))
                {
                    deviceCandidate.Name = deviceCandidate.SerialNumber;
                }

                string deviceCandidateSerialNumber = deviceCandidate.SerialNumber.Replace("-", "");

                // Check if the device is already in any database.
                if (currentDeviceDatabases.Where(database => database.SerialNumber == deviceCandidateSerialNumber).Any())
                {
                    IList <ApiDeviceDatabaseExtended> exitstingDatabases = currentDeviceDatabases.Where(database => database.SerialNumber == deviceCandidateSerialNumber).ToList();

                    StringBuilder existingDatabaseNames = new();
                    foreach (ApiDeviceDatabaseExtended database in exitstingDatabases)
                    {
                        if (existingDatabaseNames.Length > 0)
                        {
                            existingDatabaseNames.Append($", '{database.DatabaseName}'");
                        }
                        else
                        {
                            existingDatabaseNames.Append($"'{database.DatabaseName}'");
                        }
                    }
                    ConsoleUtility.LogListItemWithResult($"{deviceCandidate.Name}", $"NOT UPDATED OR ADDED: Device does not exist in '{databaseName}' database, but already exists in MyGeotab database(s) {existingDatabaseNames}.", ConsoleColor.Red);
                    continue;
                }

                // Assign the device to the Company group.
                deviceGroups.Add(new CompanyGroup());

                // Add the device to the MyGeotab database.
                try
                {
                    // Create the device object.
                    Device newDevice = Device.FromSerialNumber(deviceCandidate.SerialNumber);
                    newDevice.PopulateDefaults();
                    newDevice.Name     = deviceCandidate.Name;
                    newDevice.Groups   = deviceGroups;
                    newDevice.WorkTime = new WorkTimeStandardHours();

                    // Add the device.
                    var addedDevice = await GeotabSdkUtility.AddDeviceAsync(myGeotabApi, newDevice);

                    ConsoleUtility.LogListItemWithResult($"{deviceCandidate.SerialNumber}", $"ADDED: Device did not previously exist in '{databaseName}' database", ConsoleColor.Green);

                    // Update the device properties.
                    await GeotabSdkUtility.UpdateDeviceAsync(myGeotabApi, addedDevice, deviceCandidate.Name, deviceCandidate.EnableDeviceBeeping, deviceCandidate.EnableDriverIdentificationReminder, deviceCandidate.DriverIdentificationReminderImmobilizeSeconds, deviceCandidate.EnableBeepOnEngineRpm, deviceCandidate.EngineRpmBeepValue, deviceCandidate.EnableBeepOnIdle, deviceCandidate.IdleMinutesBeepValue, deviceCandidate.EnableBeepOnSpeeding, deviceCandidate.SpeedingStartBeepingSpeed, deviceCandidate.SpeedingStopBeepingSpeed, deviceCandidate.EnableBeepBrieflyWhenApprocahingWarningSpeed, deviceCandidate.EnableBeepOnDangerousDriving, deviceCandidate.AccelerationWarningThreshold, deviceCandidate.BrakingWarningThreshold, deviceCandidate.CorneringWarningThreshold, deviceCandidate.EnableBeepWhenSeatbeltNotUsed, deviceCandidate.SeatbeltNotUsedWarningSpeed, deviceCandidate.EnableBeepWhenPassengerSeatbeltNotUsed, deviceCandidate.BeepWhenReversing);

                    ConsoleUtility.LogListItemWithResult($"{deviceCandidate.SerialNumber} ({deviceCandidate.Name})", $"UPDATED", ConsoleColor.Green);
                }
                catch (Exception ex)
                {
                    ConsoleUtility.LogListItemWithResult($"{deviceCandidate.Name}", $"NOT UPDATED OR ADDED: Device did not previously exist in '{databaseName}' database, but an error was encountered while attempting to add the device. ERROR adding device: {ex.Message}\n{ex.StackTrace}", ConsoleColor.Red);
                }
            }

            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine("Completed processing.");
            Console.ForegroundColor = ConsoleColor.White;
        }