/// <summary>
        /// Invokes the subscriber.
        /// </summary>
        /// <param name="msg">A reference to the subscribed message.</param>
        /// <param name="session">The current <see cref="VocollectSession"/> object.</param>
        /// <exception cref="WarehouseAdapterException">
        /// </exception>
        /// <exception cref="MessageEngineException">
        /// </exception>
        public override void Invoke(MultiPartMessage msg, VocollectSession session)
        {
            MultiPartMessage responseMsg = CreateResponseMessage(msg);

            responseMsg.Properties.Write("DeliveryLocation", "");
            responseMsg.Properties.Write("DeliveryLocationCheckDigits", 0);
            responseMsg.Properties.Write("ContainerId", 0);
            responseMsg.Properties.Write("ErrorCode", VocollectErrorCodeNoError);
            responseMsg.Properties.Write("Message", "");

            try
            {
                using (TransactionScope transactionScope = new TransactionScope())
                {
                    /* Execute drop of previous container if not already dropped using the alternate delivery command */
                    if (!string.IsNullOrEmpty(session.ReadAsString("DROPSEQNUM")))
                    {
                        PrTaskLUTAltDeliveryLocations.DropLoadCarrier(session.ReadAsString("DROPSEQNUM"), session.ReadAsString("DROPWSID"), session.ReadAsString("DROPWPADR"), session);
                    }

                    MultiPartMessage whMsg = CreateRequestMessage("wlvoicepick", "get_drop_location", session);
                    whMsg.Properties.Write("TERID_I", session.ReadAsString("TERID"));
                    whMsg.Properties.Write("PBHEADID_I", session.ReadAsString("PBHEADID"));
                    whMsg.Properties.Write("SEQNUM_I", TrimContainerId(msg.Properties.ReadAsString("ContainerId")));
                    whMsg.Properties.Write("DROPWSID_O", "");
                    whMsg.Properties.Write("DROPWPADR_O", "");
                    whMsg.Properties.Write("WPCOD_O", "");
                    whMsg.Properties.Write("SLOT_O", "");
                    whMsg.Properties.Write("ALMID_O", "");

                    CorrelationContext context;

                    MessageEngine.Instance.TransmitRequestMessage(whMsg, whMsg.MessageId, out context);

                    PropertyCollection properties = context.ResponseMessages[0].Properties;

                    if (!string.IsNullOrEmpty(properties.ReadAsString("SLOT_O")))
                    {
                        /* VOICEPICK015 = 'slot' */
                        string slot = GetCachedAlarmText("VOICEPICK015", session);

                        responseMsg.Properties.Write("DeliveryLocation", properties.Read("DROPWSID_O") + " , " + properties.Read("DROPWPADR_O") + " , " + slot + " , " + properties.Read("SLOT_O"));
                    }
                    else
                    {
                        responseMsg.Properties.Write("DeliveryLocation", properties.Read("DROPWSID_O") + " , " + properties.Read("DROPWPADR_O"));
                    }

                    if (session.ReadAsString("VERIFY_DROPWPADR") == "1")
                    {
                        string checkDigits = properties.ReadAsString("WPCOD_O");

                        if (!string.IsNullOrEmpty(checkDigits))
                        {
                            long temp;

                            if (!long.TryParse(checkDigits, out temp))
                            {
                                checkDigits = "";
                            }

                            if (checkDigits.Length > session.ReadAsInt("VOICE_MIN_DIGITS_PPCODE"))
                            {
                                checkDigits = checkDigits.Substring(checkDigits.Length - session.ReadAsInt("VOICE_MIN_DIGITS_PPCODE"), session.ReadAsInt("VOICE_MIN_DIGITS_PPCODE"));
                            }
                        }

                        responseMsg.Properties.Write("DeliveryLocationCheckDigits", checkDigits);
                    }
                    else
                    {
                        responseMsg.Properties.Write("DeliveryLocationCheckDigits", "");
                    }

                    responseMsg.Properties.Write("ContainerId", msg.Properties.ReadAsString("ContainerId"));

                    session.Write("DROPSEQNUM", TrimContainerId(msg.Properties.ReadAsString("ContainerId")));
                    session.Write("DROPWSID", properties.Read("DROPWSID_O"));
                    session.Write("DROPWPADR", properties.Read("DROPWPADR_O"));

                    transactionScope.Complete();
                }
            }
            catch (WarehouseAdapterException ex)
            {
                responseMsg.Properties.Write("ErrorCode", WarehouseAlarm);
                responseMsg.Properties.Write("Message", ex.Message);

                throw;
            }
            catch (Exception)
            {
                responseMsg.Properties.Write("ErrorCode", VocollectErrorCodeCritialError);
                responseMsg.Properties.Write("Message", GetCriticalErrorMessageText(msg));

                throw;
            }
            finally
            {
                TransmitResponseMessage(responseMsg, session);
            }
        }
        /// <summary>
        /// Invokes the subscriber.
        /// </summary>
        /// <param name="msg">A reference to the subscribed message.</param>
        /// <param name="session">The current <see cref="VocollectSession"/> object.</param>
        /// <exception cref="WarehouseAdapterException">
        /// </exception>
        /// <exception cref="MessageEngineException">
        /// </exception>
        public override void Invoke(MultiPartMessage msg, VocollectSession session)
        {
            MultiPartMessage responseMsg = CreateResponseMessage(msg);

            responseMsg.Properties.Write("RegionNumber", 0);
            responseMsg.Properties.Write("Description", "");
            responseMsg.Properties.Write("AutoAssign", 1);
            responseMsg.Properties.Write("NumberAssignmentsAllowed", 1);
            responseMsg.Properties.Write("SkipAisleAllowed", 0);
            responseMsg.Properties.Write("SkipSlotAllowed", 0);
            responseMsg.Properties.Write("RepickSkips", 0);
            responseMsg.Properties.Write("CpSpeakWorkIdentifier", 0);
            responseMsg.Properties.Write("PrintLabels", 0);
            responseMsg.Properties.Write("PrintChaseLabels", 0);
            responseMsg.Properties.Write("SpeakSlotDescription", 0);
            responseMsg.Properties.Write("PickPrompt", 2);
            responseMsg.Properties.Write("SpeakWorkId", 0);
            responseMsg.Properties.Write("SignOffAllowed", 0);
            responseMsg.Properties.Write("ContainerType", 1);
            responseMsg.Properties.Write("DeliverContainerAtClose", 0);
            responseMsg.Properties.Write("PassAssignment", 0);
            responseMsg.Properties.Write("Delivery", 1);
            responseMsg.Properties.Write("QuantityVerification", 1);
            responseMsg.Properties.Write("WorkIdLength", 0);
            responseMsg.Properties.Write("GoBackForShorts", 0);
            responseMsg.Properties.Write("AllowReversePicking", 0);
            responseMsg.Properties.Write("UseLut", 2);
            responseMsg.Properties.Write("CurrentPreAisle", "".PadRight(string.Format(GetCachedAlarmText("VOICEPICK013", session), "").Length + 35, 'X'));
            responseMsg.Properties.Write("CurrentAisle", "".PadRight(3, 'X'));
            responseMsg.Properties.Write("CurrentPostAisle", "");
            responseMsg.Properties.Write("CurrentSlot", "".PadRight(64, 'X'));
            responseMsg.Properties.Write("PrintMultipleLabels", 0);
            responseMsg.Properties.Write("PromptOperatorForContainerId", 0);
            responseMsg.Properties.Write("AllowMultipleOpenContainersPerWorkId", 1);
            responseMsg.Properties.Write("SpokenContainerValidationLength", 1);
            responseMsg.Properties.Write("StopLineNumber", 0);
            responseMsg.Properties.Write("AllowAlternateDelivery", 0);
            responseMsg.Properties.Write("ErrorCode", VocollectErrorCodeNoError);
            responseMsg.Properties.Write("Message", "");

            try
            {
                MultiPartMessage whMsg = CreateRequestMessage("wlvoicepick", "get_mt_pz", session);
                whMsg.Properties.Write("TERID_I", session.ReadAsString("TERID"));
                whMsg.Properties.Write("EMPID_I", session.ReadAsString("EMPID"));
                whMsg.Properties.Write("PZID_I", session.ReadAsString("PZID"));
                whMsg.Properties.Write("WHID_I", session.ReadAsString("WHID"));
                whMsg.Properties.Write("PZ_Cur_O", new object());
                whMsg.Properties.Write("ALMID_O", "");

                CorrelationContext context;

                MessageEngine.Instance.TransmitRequestMessage(whMsg, whMsg.MessageId, out context);

                PropertyCollection properties = context.ResponseMessages[0].Parts[0].Properties;

                responseMsg.Properties.Write("RegionNumber", msg.Properties.Read("RegionNumber"));
                responseMsg.Properties.Write("Description", properties.Read("PZNAME"));
                responseMsg.Properties.Write("SkipAisleAllowed", properties.Read("VOICE_ALLOW_SKIP_AISLE"));
                responseMsg.Properties.Write("SkipSlotAllowed", properties.Read("VOICE_ALLOW_SKIP_PP"));
                responseMsg.Properties.Write("RepickSkips", properties.Read("VOICE_ALLOW_REPICK_PP"));
                responseMsg.Properties.Write("QuantityVerification", properties.Read("VOICE_VERIFY_QTY"));
                responseMsg.Properties.Write("GoBackForShorts", properties.Read("VOICE_REPICK_SHORTED_PBROW"));
                responseMsg.Properties.Write("SpokenContainerValidationLength", properties.Read("VOICE_MIN_DIGITS_CARCODE"));

                #region Print Label Config

                PrintLabelConfig labelConfig = PrintLabelConfig.Never;

                string CPL_PRINTCOD  = properties.ReadAsString("CPL_PRINTCOD");
                string PLCP_PRINTCOD = properties.ReadAsString("PLCP_PRINTCOD");

                if ((CPL_PRINTCOD == "AP") || (PLCP_PRINTCOD == "AP"))
                {
                    labelConfig = PrintLabelConfig.AfterPick;
                }

                if ((CPL_PRINTCOD == "BP") || (PLCP_PRINTCOD == "BP"))
                {
                    if (labelConfig == PrintLabelConfig.AfterPick)
                    {
                        labelConfig = PrintLabelConfig.BeforeAndAfterPick;
                    }
                    else
                    {
                        labelConfig = PrintLabelConfig.BeforePick;
                    }
                }

                responseMsg.Properties.Write("PrintLabels", (int)labelConfig);

                #endregion

                if (string.IsNullOrEmpty(properties.ReadAsString("NO_OF_PBROWS")))
                {
                    responseMsg.Properties.Write("StopLineNumber", 0);
                }
                else
                {
                    responseMsg.Properties.Write("StopLineNumber", properties.Read("NO_OF_PBROWS"));
                }

                responseMsg.Properties.Write("AllowAlternateDelivery", properties.Read("ALLOW_CHANGE_ON_DROPWPADR"));
                responseMsg.Properties.Write("PickPrompt", properties.Read("VOICE_PICK_PROMPT"));
                responseMsg.Properties.Write("Delivery", properties.Read("VERIFY_DROPWPADR"));

                session.Write("VOICE_VERIFY_PP_BALANCE", properties.Read("VOICE_VERIFY_PP_BALANCE"));
                session.Write("VERIFY_DROPWPADR", properties.Read("VERIFY_DROPWPADR"));
                session.Write("VOICE_MIN_DIGITS_PPCODE", properties.Read("VOICE_MIN_DIGITS_PPCODE"));
                session.Write("VOICE_MIN_DIGITS_CARCODE", properties.Read("VOICE_MIN_DIGITS_CARCODE"));
                session.Write("VOICE_DIGITS_ITEID", properties.Read("VOICE_DIGITS_ITEID"));
                session.Write("VOICE_MIN_DIGITS_ITEVERIFY", properties.Read("VOICE_MIN_DIGITS_ITEVERIFY"));
                session.Write("VOICE_CHARS_PRODLOT", properties.Read("VOICE_CHARS_PRODLOT"));
                session.Write("VOICE_MIN_CHARS_PRODLOTVERIFY", properties.Read("VOICE_MIN_CHARS_PRODLOTVERIFY"));
                session.Write("ITESWAP", properties.Read("ITESWAP"));
                session.Write("CPL_PRINTCOD", properties.ReadAsString("CPL_PRINTCOD"));
                session.Write("PLCP_PRINTCOD", properties.ReadAsString("PLCP_PRINTCOD"));
            }
            catch (WarehouseAdapterException ex)
            {
                responseMsg.Properties.Write("ErrorCode", WarehouseAlarm);
                responseMsg.Properties.Write("Message", ex.Message);

                throw;
            }
            catch (Exception)
            {
                responseMsg.Properties.Write("ErrorCode", VocollectErrorCodeCritialError);
                responseMsg.Properties.Write("Message", GetCriticalErrorMessageText(msg));

                throw;
            }
            finally
            {
                TransmitResponseMessage(responseMsg, session);
            }
        }
        /// <summary>
        /// Invokes the subscriber.
        /// </summary>
        /// <param name="msg">A reference to the subscribed message.</param>
        /// <param name="session">The current <see cref="VocollectSession"/> object.</param>
        /// <exception cref="WarehouseAdapterException">
        /// </exception>
        /// <exception cref="MessageEngineException">
        /// </exception>
        public override void Invoke(MultiPartMessage msg, VocollectSession session)
        {
            MultiPartMessage responseMsg = CreateResponseMessage(msg);

            responseMsg.Properties.Write("AssignmentId", 0);
            responseMsg.Properties.Write("IsChase", 0);
            responseMsg.Properties.Write("WorkId", "1");
            responseMsg.Properties.Write("Position", "1");
            responseMsg.Properties.Write("TotalItems", 0);
            responseMsg.Properties.Write("ItemsNotPicked", 0);
            responseMsg.Properties.Write("BaseItemsNotPicked", 0);
            responseMsg.Properties.Write("Cube", 0);
            responseMsg.Properties.Write("GoalTime", 0);
            responseMsg.Properties.Write("Route", "");
            responseMsg.Properties.Write("ActiveContainer", "00");
            responseMsg.Properties.Write("PassAssignment", "0");
            responseMsg.Properties.Write("PreviousWork", "0");
            responseMsg.Properties.Write("PickLines", 0);
            responseMsg.Properties.Write("PickedLines", 0);
            responseMsg.Properties.Write("CustomerNumber", "");
            responseMsg.Properties.Write("PreviousWorkVehicle", "");
            responseMsg.Properties.Write("AllowPackaging", "1");
            responseMsg.Properties.Write("ErrorCode", VocollectErrorCodeNoError);
            responseMsg.Properties.Write("Message", "");

            try
            {
                using (TransactionScope transactionScope = new TransactionScope())
                {
                    PropertyCollection properties = null;

                    /* Check if pick order is already fetched */
                    if (session.ReadAsString("PBHEADID").Length == 0)
                    {
                        CorrelationContext context = RequestPickOrder(PickOrderHoldType.None, session);
                        properties = context.ResponseMessages[0].Parts[0].Properties;
                    }
                    else /* Use data from session */
                    {
                        properties = session.CurrentAssignmentData;
                    }


                    responseMsg.Properties.Write("AssignmentId", session.ReadAsString("PBHEADID"));
                    responseMsg.Properties.Write("TotalItems", 0);
                    responseMsg.Properties.Write("ItemsNotPicked", properties.ReadAsDouble("TOTQTY") - properties.ReadAsDouble("PIKQTY"));

                    responseMsg.Properties.Write("GoalTime", ((TimeSpan)session.Read("PICKTIME")).Minutes);

                    if (string.IsNullOrEmpty(session.ReadAsString("HOLD_TYPE")))
                    {
                        responseMsg.Properties.Write("PreviousWork", 0);
                    }
                    else
                    {
                        if (string.IsNullOrEmpty(properties.ReadAsString("TUID")))
                        {
                            responseMsg.Properties.Write("PreviousWork", 1);
                        }
                        else
                        {
                            responseMsg.Properties.Write("PreviousWork", 2);
                        }
                    }

                    responseMsg.Properties.Write("PickLines", properties.Read("NOROWS"));
                    responseMsg.Properties.Write("PickedLines", properties.Read("NOPIKROW"));


                    //responseMsg.Properties.Write("AllowPackaging", properties.Read("CONFIRM_PM"));
                    responseMsg.Properties.Write("PreviousWorkVehicle", properties.Read("TUID"));

                    transactionScope.Complete();
                }
            }
            catch (WarehouseAdapterException ex)
            {
                responseMsg.Properties.Write("ErrorCode", WarehouseAlarm);
                responseMsg.Properties.Write("Message", ex.Message);

                throw;
            }
            catch (Exception)
            {
                responseMsg.Properties.Write("ErrorCode", VocollectErrorCodeCritialError);
                responseMsg.Properties.Write("Message", GetCriticalErrorMessageText(msg));

                throw;
            }
            finally
            {
                TransmitResponseMessage(responseMsg, session);
            }
        }
        /// <summary>
        /// Invokes the subscriber.
        /// </summary>
        /// <param name="msg">A reference to the subscribed message.</param>
        /// <param name="session">The current <see cref="VocollectSession"/> object.</param>
        /// <exception cref="WarehouseAdapterException">
        /// </exception>
        /// <exception cref="MessageEngineException">
        /// </exception>
        public override void Invoke(MultiPartMessage msg, VocollectSession session)
        {
            MultiPartMessage responseMsg = CreateResponseMessage(msg);

            responseMsg.Properties.Write("DeliveryLocation", "");
            responseMsg.Properties.Write("DeliveryLocationCheckDigits", "");
            responseMsg.Properties.Write("ErrorCode", VocollectErrorCodeNoError);
            responseMsg.Properties.Write("Message", "");

            try
            {
                MultiPartMessage whMsg = CreateRequestMessage("wlvoicepick", "verify_loc", session);
                whMsg.Properties.Write("TERID_I", session.ReadAsString("TERID"));
                whMsg.Properties.Write("WSID_IO", msg.Properties.ReadAsString("AlternateDeliveryArea"));
                whMsg.Properties.Write("WPADR_I", msg.Properties.ReadAsString("AlternateDeliveryLocation"));
                whMsg.Properties.Write("WHID_I", session.ReadAsString("WHID"));
                whMsg.Properties.Write("ALMID_O", "");

                CorrelationContext context;

                MessageEngine.Instance.TransmitRequestMessage(whMsg, whMsg.MessageId, out context);

                PropertyCollection properties = context.ResponseMessages[0].Properties;

                responseMsg.Properties.Write("DeliveryLocation", properties.Read("WSID_IO") + " " + msg.Properties.ReadAsString("AlternateDeliveryLocation"));

                DropLoadCarrier(TrimContainerId(msg.Properties.ReadAsString("ContainerId")), properties.ReadAsString("WSID_IO"), msg.Properties.ReadAsString("AlternateDeliveryLocation"), session);

                /* Clear drop variables so the container won't be dropped in next call to PrTaskGetDeliveryLocations */
                session.Write("DROPSEQNUM", "");
                session.Write("DROPWSID", "");
                session.Write("DROPWPADR", "");
            }
            catch (WarehouseAdapterException ex)
            {
                if (ex.AlarmId == "WS001")
                {
                    responseMsg.Properties.Write("ErrorCode", VocollectErrorCodeAddressNotUnique);
                }
                else
                {
                    responseMsg.Properties.Write("ErrorCode", VocollectErrorCodeInvalidLocation);
                }

                responseMsg.Properties.Write("Message", ex.Message);
            }
            catch (Exception)
            {
                responseMsg.Properties.Write("ErrorCode", VocollectErrorCodeCritialError);
                responseMsg.Properties.Write("Message", GetCriticalErrorMessageText(msg));

                throw;
            }
            finally
            {
                TransmitResponseMessage(responseMsg, session);
            }
        }
        /// <summary>
        /// Requests a pick order from the WMS.
        /// </summary>
        /// <param name="holdType">The desired hold type of the pick order.</param>
        /// <param name="session">The current session.</param>
        /// <returns></returns>
        public static CorrelationContext RequestPickOrder(PickOrderHoldType holdType, VocollectSession session)
        {
            MultiPartMessage whMsg = CreateRequestMessage("wlvoicepick", "get_mt_pbhead", session);

            whMsg.Properties.Write("TERID_I", session.ReadAsString("TERID"));
            whMsg.Properties.Write("TUID_I", session.ReadAsString("TUID"));
            whMsg.Properties.Write("WHID_I", session.ReadAsString("WHID"));

            if (holdType == PickOrderHoldType.Temporarily)
            {
                whMsg.Properties.Write("PZID_I", "");
                whMsg.Properties.Write("PZGRPID_I", "");
            }
            else
            {
                whMsg.Properties.Write("PZID_I", session.ReadAsString("PZID"));
                whMsg.Properties.Write("PZGRPID_I", session.ReadAsString("PZGRPID"));
            }

            whMsg.Properties.Write("NLANGCOD_I", session.ReadAsString("NLANGCOD"));
            whMsg.Properties.Write("PBHEAD_Cur_O", new object());
            whMsg.Properties.Write("HOLD_TYPE_O", "");
            whMsg.Properties.Write("LOCATION_O", "");
            whMsg.Properties.Write("ALMID_O", "");

            if (holdType == PickOrderHoldType.Definitely)
            {
                whMsg.Properties.Write("DEF_ON_HOLD_I", "1");
            }
            else
            {
                whMsg.Properties.Write("DEF_ON_HOLD_I", "0");
            }

            CorrelationContext context;

            MessageEngine.Instance.TransmitRequestMessage(whMsg, whMsg.MessageId, out context);

            //Get properties from cursor
            PropertyCollection properties = context.ResponseMessages[0].Parts[0].Properties;

            if ((!string.IsNullOrEmpty(context.ResponseMessages[0].Properties.ReadAsString("HOLD_TYPE_O"))) &&
                (!string.IsNullOrEmpty(properties.ReadAsString("TUID"))))
            {
                VerifyAndConnectPickTruck(session, properties.ReadAsString("PBHEADID"), session.ReadAsString("TUID"), properties.ReadAsString("TUID"));
            }

            //Write data to session
            session.Write("PBHEADID", properties.ReadAsString("PBHEADID"));
            session.Write("PZID", properties.ReadAsString("PZID"));
            session.Write("HOLD_TYPE", context.ResponseMessages[0].Properties.ReadAsString("HOLD_TYPE_O"));
            session.Write("CARCODE_TYPE", properties.ReadAsString("CARCODE_TYPE"));
            session.Write("PBROWID", "");
            session.Write("DROPSEQNUM", "");
            session.Write("DROPWSID", "");
            session.Write("DROPWPADR", "");
            session.Write("UPDATE_PBCAR", "0");
            session.Write("NOCARS", properties.ReadAsInt("NOCARS"));
            session.Write("PRINTED", "0");
            session.Write("PRINTERNUMBER", "");
            session.CurrentAssignmentData = properties;

            TimeSpan pickTime = new TimeSpan(0, 0,
                                             Convert.ToInt32(properties.ReadAsInt("ESTPICKTME")
                                                             + properties.ReadAsInt("ESTMOVTIMEPICK")
                                                             + properties.ReadAsInt("ESTDRVTME")
                                                             + properties.ReadAsInt("ESTPACKTME")));

            session.Write("PICKTIME", pickTime);
            session.Write("LPDTM_SHIPWS", properties.Read("LPDTM_SHIPWS"));

            return(context);
        }