/// <summary>
            /// Creates the device given the data collection return by AX.
            /// </summary>
            /// <param name="data">The data.</param>
            /// <returns>The device.</returns>
            private Microsoft.Dynamics.Commerce.Runtime.DataModel.Device CreateDevice(ReadOnlyCollection <object> data)
            {
                var device = new Microsoft.Dynamics.Commerce.Runtime.DataModel.Device();

                device.TerminalRecordId             = (long)data[0];
                device.ChannelId                    = (long)data[1];
                device.TerminalId                   = (string)data[2];
                device.ChannelName                  = (string)data[3];
                device.DeviceTypeRecordId           = (long)data[4];
                device.TokenData                    = (string)data[5];
                device.TokenSalt                    = (string)data[6];
                device.TokenAlgorithm               = (string)data[7];
                device.ActivatedDateTime            = new DateTimeOffset((DateTime)data[8]);
                device.ActivationStatus             = (DeviceActivationStatus)data[9];
                device.DeactivateComments           = (string)data[10];
                device.DeactivatedDateTime          = new DateTimeOffset((DateTime)data[11]);
                device.Description                  = (string)data[12];
                device.TokenIssueTime               = new DateTimeOffset((DateTime)data[13]);
                device.UseInMemoryDeviceDataStorage = Convert.ToBoolean((int)data[14]);
                device.DeviceId     = (string)data[15];
                device.DeviceNumber = (string)data[16];
                device.RecordId     = (long)data[17];
                device.Token        = (string)data[18];

                return(device);
            }
            /// <summary>
            /// Deactivate a device in AX.
            /// </summary>
            /// <param name="deviceNumber">The device number.</param>
            /// <param name="terminalId">The terminal identifier.</param>
            /// <param name="staffId">The staff identifier.</param>
            /// <param name="deviceToken">The device token.</param>
            /// <returns>The deactivated device.</returns>
            internal DeviceDeactivationResult DeactivateDevice(string deviceNumber, string terminalId, string staffId, string deviceToken)
            {
                const int InvalidTokenError = 1;

                ThrowIf.Null(deviceNumber, "deviceNumber");
                ThrowIf.Null(terminalId, "terminalId");
                ThrowIf.Null(staffId, "staffId");
                ReadOnlyCollection <object>            data;
                HeadquarterTransactionServiceException deactivationException = null;

                try
                {
                    data = this.InvokeMethod(DeactivateDeviceMethodName, new object[] { deviceNumber, terminalId, staffId, deviceToken });
                }
                catch (HeadquarterTransactionServiceException exception)
                {
                    data = exception.HeadquartersErrorData;

                    if (data.Count == DeviceDeactivationInvalidTokenResponseSize)
                    {
                        int errorCode = (int)data[DeviceDeactivationInvalidTokenResponseSize - 1];
                        if (errorCode == InvalidTokenError)
                        {
                            RetailLogger.Log.CrtServicesDeactiveDeviceFailedDueToInvalidToken(staffId, deviceNumber, terminalId);
                            deactivationException = exception;
                        }
                        else
                        {
                            throw;
                        }
                    }
                    else
                    {
                        throw;
                    }
                }

                if (data == null || data.Count < DeviceDeactivationResponseSize)
                {
                    throw new Microsoft.Dynamics.Commerce.Runtime.CommunicationException(CommunicationErrors.Microsoft_Dynamics_Commerce_Runtime_HeadquarterResponseParsingError);
                }

                Microsoft.Dynamics.Commerce.Runtime.DataModel.Device device = this.CreateDevice(data);

                return(new DeviceDeactivationResult()
                {
                    Device = device, ErrorMessage = deactivationException == null ? null : deactivationException.Message
                });
            }
            /// <summary>
            /// Activate a device in AX.
            /// </summary>
            /// <param name="deviceNumber">The device number.</param>
            /// <param name="terminalId">The terminal identifier.</param>
            /// <param name="staffId">The staff identifier.</param>
            /// <param name="deviceId">The physical device identifier.</param>
            /// <param name="forceActivate">The value indicating whether to force the Activation of a device when the physical device identifiers are different.</param>
            /// <param name="deviceType">The device type (optional).</param>
            /// <returns>The device activation result object.</returns>
            internal DeviceActivationResult ActivateDevice(string deviceNumber, string terminalId, string staffId, string deviceId, bool forceActivate, int?deviceType)
            {
                ThrowIf.Null(deviceNumber, "deviceNumber");
                ThrowIf.Null(staffId, "staffId");

                // transform the customer to parameters
                object[] parameters = new object[] { deviceNumber, terminalId, staffId, deviceId, forceActivate, deviceType.GetValueOrDefault(TransactionServiceClient.DefaultDeviceType) };
                ReadOnlyCollection <object> data = null;

                try
                {
                    data = this.InvokeMethod(ActivateDeviceMethodName, parameters);
                }
                catch (HeadquarterTransactionServiceException exception)
                {
                    string errorCode = (string)exception.HeadquartersErrorData.FirstOrDefault();
                    if (AttemptToActivateFromDifferencePhysicalDeviceErrorCode.Equals(errorCode, StringComparison.OrdinalIgnoreCase))
                    {
                        RetailLogger.Log.CrtServicesAttemptToActivateFromDifferentPhysicalDevice(staffId, deviceNumber, deviceId, terminalId);

                        throw new CommerceException(
                                  SecurityErrors.Microsoft_Dynamics_Commerce_Runtime_AttemptToActivateFromDifferentPhysicalDevice.ToString(),
                                  exception,
                                  string.Format("Attempt to activate an activated device '{0}' from another physical device.", deviceNumber));
                    }
                    else
                    {
                        throw;
                    }
                }

                if (data == null || data.Count < DeviceActivationResponseSize)
                {
                    throw new Microsoft.Dynamics.Commerce.Runtime.CommunicationException(CommunicationErrors.Microsoft_Dynamics_Commerce_Runtime_HeadquarterResponseParsingError);
                }

                // Parse response data
                Microsoft.Dynamics.Commerce.Runtime.DataModel.Device device = this.CreateDevice(data);
                var result = new DeviceActivationResult {
                    Device = device
                };

                return(result);
            }