public static SendReceipt GetSendReceiptCommand(OrderDetail order, AccountDetail account, int?orderId, string vehicleNumber, DriverInfos driverInfos,
                                                        double?fare, double?toll, double?extra, double?surcharge, double?bookingFees, double?tip, double?tax, OrderPaymentDetail orderPayment = null, double?amountSavedByPromotion = null,
                                                        PromotionUsageDetail promotionUsed = null, CreditCardDetails creditCard = null, SendReceipt.CmtRideLinqReceiptFields cmtRideLinqFields = null)
        {
            var command = new SendReceipt
            {
                Id                 = Guid.NewGuid(),
                OrderId            = order.Id,
                EmailAddress       = account.Email,
                IBSOrderId         = orderId ?? 0,
                PickupDate         = order.PickupDate,
                UtcDropOffDate     = order.DropOffDate,
                VehicleNumber      = vehicleNumber,
                DriverInfos        = driverInfos,
                Fare               = fare.GetValueOrDefault(),
                Extra              = extra.GetValueOrDefault(),
                Tip                = tip.GetValueOrDefault(),
                Tax                = tax.GetValueOrDefault(),
                Toll               = toll.GetValueOrDefault(),
                Surcharge          = surcharge.GetValueOrDefault(),
                BookingFees        = bookingFees.GetValueOrDefault(),
                PickupAddress      = order.PickupAddress,
                DropOffAddress     = order.DropOffAddress,
                ClientLanguageCode = order.ClientLanguageCode,
                CmtRideLinqFields  = cmtRideLinqFields
            };

            if (promotionUsed != null)
            {
                command.AmountSavedByPromotion = amountSavedByPromotion.GetValueOrDefault();
                command.PromoCode          = promotionUsed.Code;
                command.PromoDiscountType  = promotionUsed.DiscountType;
                command.PromoDiscountValue = promotionUsed.DiscountValue;
            }

            if (orderPayment != null)
            {
                command.PaymentInfo = new SendReceipt.Payment(
                    orderPayment.Amount,
                    orderPayment.TransactionId,
                    orderPayment.AuthorizationCode,
                    orderPayment.Type == PaymentType.CreditCard ? "Credit Card" : orderPayment.Type.ToString());

                if ((orderPayment.CardToken.HasValue()) && (creditCard != null))
                {
                    command.PaymentInfo.Last4Digits     = creditCard.Last4Digits;
                    command.PaymentInfo.Company         = creditCard.CreditCardCompany;
                    command.PaymentInfo.NameOnCard      = creditCard.NameOnCard;
                    command.PaymentInfo.ExpirationMonth = creditCard.ExpirationMonth;
                    command.PaymentInfo.ExpirationYear  = creditCard.ExpirationYear;
                }
            }
            return(command);
        }
        public object Post(SendReceiptAdmin request)
        {
            var order = _orderDao.FindById(request.OrderId);

            if (order == null || !(order.IsManualRideLinq || order.IBSOrderId.HasValue))
            {
                throw new HttpError(HttpStatusCode.BadRequest, ErrorCode.OrderNotInIbs.ToString());
            }

            AccountDetail account;

            // if the admin is requesting the receipt then it won't be for the logged in user
            if (!request.RecipientEmail.IsNullOrEmpty())
            {
                account = _accountDao.FindById(order.AccountId);
            }
            else
            {
                account = _accountDao.FindById(new Guid(this.GetSession().UserAuthId));
                if (account.Id != order.AccountId)
                {
                    throw new HttpError(HttpStatusCode.Unauthorized, "Not your order");
                }
            }

            // If the order was created in another company, need to fetch the correct IBS account
            var ibsAccountId = _accountDao.GetIbsAccountId(account.Id, order.CompanyKey);

            if (!(ibsAccountId.HasValue || order.IsManualRideLinq))
            {
                throw new HttpError(HttpStatusCode.BadRequest, ErrorCode.IBSAccountNotFound.ToString());
            }

            var ibsOrder = !order.IsManualRideLinq
                ? _ibsServiceProvider.Booking(order.CompanyKey).GetOrderDetails(order.IBSOrderId.Value, ibsAccountId.Value, order.Settings.Phone)
                : null;

            var orderPayment = _orderPaymentDao.FindByOrderId(order.Id, order.CompanyKey);
            var pairingInfo  = _orderDao.FindOrderPairingById(order.Id);
            var orderStatus  = _orderDao.FindOrderStatusById(request.OrderId);

            double?fareAmount;
            double?tollAmount = null;
            double?tipAmount;
            double?taxAmount;
            double?surcharge;
            double?bookingFees = null;
            double?extraAmount = null;
            PromotionUsageDetail promotionUsed = null;

            ReadModel.CreditCardDetails creditCard = null;

            var ibsOrderId = orderStatus.IBSOrderId;

            Commands.SendReceipt.CmtRideLinqReceiptFields cmtRideLinqFields = null;

            if (orderPayment != null && orderPayment.IsCompleted)
            {
                fareAmount  = Convert.ToDouble(orderPayment.Meter);
                tipAmount   = Convert.ToDouble(orderPayment.Tip);
                taxAmount   = Convert.ToDouble(orderPayment.Tax);
                surcharge   = Convert.ToDouble(orderPayment.Surcharge);
                bookingFees = Convert.ToDouble(orderPayment.BookingFees);

                // promotion can only be used with in app payment
                promotionUsed = _promotionDao.FindByOrderId(request.OrderId);

                creditCard = orderPayment.CardToken.HasValue()
                    ? _creditCardDao.FindByToken(orderPayment.CardToken)
                    : null;
            }
            else if (order.IsManualRideLinq)
            {
                var manualRideLinqDetail = _orderDao.GetManualRideLinqById(order.Id);
                fareAmount  = manualRideLinqDetail.Fare;
                ibsOrderId  = manualRideLinqDetail.TripId;
                tollAmount  = manualRideLinqDetail.Toll;
                extraAmount = manualRideLinqDetail.Extra;
                tipAmount   = manualRideLinqDetail.Tip;
                taxAmount   = manualRideLinqDetail.Tax;
                surcharge   = manualRideLinqDetail.Surcharge;
                orderStatus.DriverInfos.DriverId = manualRideLinqDetail.DriverId.ToString();
                order.DropOffAddress             = _geocoding.TryToGetExactDropOffAddress(orderStatus, manualRideLinqDetail.LastLatitudeOfVehicle, manualRideLinqDetail.LastLongitudeOfVehicle, order.DropOffAddress, order.ClientLanguageCode);

                cmtRideLinqFields = new Commands.SendReceipt.CmtRideLinqReceiptFields
                {
                    TripId                 = manualRideLinqDetail.TripId,
                    DriverId               = manualRideLinqDetail.DriverId.ToString(),
                    Distance               = manualRideLinqDetail.Distance,
                    AccessFee              = manualRideLinqDetail.AccessFee,
                    PickUpDateTime         = manualRideLinqDetail.StartTime,
                    DropOffDateTime        = manualRideLinqDetail.EndTime,
                    LastFour               = manualRideLinqDetail.LastFour,
                    FareAtAlternateRate    = manualRideLinqDetail.FareAtAlternateRate,
                    RateAtTripEnd          = (int)(manualRideLinqDetail.RateAtTripEnd.GetValueOrDefault()),
                    RateAtTripStart        = (int)(manualRideLinqDetail.RateAtTripStart.GetValueOrDefault()),
                    LastLatitudeOfVehicle  = order.DropOffAddress.Latitude,
                    LastLongitudeOfVehicle = order.DropOffAddress.Longitude,
                    TipIncentive           = order.TipIncentive ?? 0
                };
            }
            else if (pairingInfo != null && pairingInfo.AutoTipPercentage.HasValue)
            {
                var tripInfo = GetTripInfo(pairingInfo.PairingToken);
                if (tripInfo != null && !tripInfo.ErrorCode.HasValue && tripInfo.EndTime.HasValue)
                {
                    // this is for CMT RideLinq only, no VAT

                    fareAmount = Math.Round(((double)tripInfo.Fare / 100), 2);
                    var tollHistory = tripInfo.TollHistory != null
                        ? tripInfo.TollHistory.Sum(p => p.TollAmount)
                        : 0;

                    tollAmount  = Math.Round(((double)tollHistory / 100), 2);
                    extraAmount = Math.Round(((double)tripInfo.Extra / 100), 2);
                    tipAmount   = Math.Round(((double)tripInfo.Tip / 100), 2);
                    taxAmount   = Math.Round(((double)tripInfo.Tax / 100), 2);
                    surcharge   = Math.Round(((double)tripInfo.Surcharge / 100), 2);
                    orderStatus.DriverInfos.DriverId = tripInfo.DriverId.ToString();

                    cmtRideLinqFields = new Commands.SendReceipt.CmtRideLinqReceiptFields
                    {
                        TripId              = tripInfo.TripId,
                        DriverId            = tripInfo.DriverId.ToString(),
                        Distance            = tripInfo.Distance,
                        AccessFee           = Math.Round(((double)tripInfo.AccessFee / 100), 2),
                        PickUpDateTime      = tripInfo.StartTime,
                        DropOffDateTime     = tripInfo.EndTime,
                        LastFour            = tripInfo.LastFour,
                        FareAtAlternateRate = Math.Round(((double)tripInfo.FareAtAlternateRate / 100), 2),
                        RateAtTripEnd       = tripInfo.RateAtTripEnd,
                        RateAtTripStart     = tripInfo.RateAtTripStart,
                        Tolls        = tripInfo.TollHistory,
                        TipIncentive = (order.TipIncentive.HasValue) ? order.TipIncentive.Value : 0
                    };
                }
                else
                {
                    fareAmount = ibsOrder.Fare;
                    tollAmount = ibsOrder.Toll;
                    tipAmount  = FareHelper.CalculateTipAmount(ibsOrder.Fare.GetValueOrDefault(0),
                                                               pairingInfo.AutoTipPercentage.Value);
                    taxAmount = ibsOrder.VAT;
                    surcharge = order.Surcharge;
                }

                orderPayment = null;
                creditCard   = pairingInfo.TokenOfCardToBeUsedForPayment.HasValue()
                    ? _creditCardDao.FindByToken(pairingInfo.TokenOfCardToBeUsedForPayment)
                    : null;
            }
            else
            {
                fareAmount = ibsOrder.Fare;
                tollAmount = ibsOrder.Toll;
                tipAmount  = ibsOrder.Tip;
                taxAmount  = ibsOrder.VAT;
                surcharge  = order.Surcharge;

                orderPayment = null;
            }

            var orderReport = _reportDao.GetOrderReportWithOrderId(order.Id);

            var sendReceiptCommand = SendReceiptCommandBuilder.GetSendReceiptCommand(
                order,
                account,
                ibsOrderId,
                (orderReport != null ? orderReport.VehicleInfos.Number : ibsOrder.VehicleNumber),
                orderStatus.DriverInfos,
                fareAmount,
                tollAmount,
                extraAmount,
                surcharge,
                bookingFees,
                tipAmount,
                taxAmount,
                orderPayment,
                promotionUsed != null
                        ? Convert.ToDouble(promotionUsed.AmountSaved)
                        : (double?)null,
                promotionUsed,
                creditCard,
                cmtRideLinqFields);

            // Since the user or an admin requested the receipt, we should bypass the normal notification settings.
            sendReceiptCommand.BypassNotificationSettings = true;

            if (!request.RecipientEmail.IsNullOrEmpty())
            {
                sendReceiptCommand.EmailAddress = request.RecipientEmail;
            }
            _commandBus.Send(sendReceiptCommand);

            return(new HttpResult(HttpStatusCode.OK, "OK"));
        }