public object Json()
 {
     return(new
     {
         Id,
         BookingId,
         BookingUser = BookingUser?.Json(),
         ServerReference,
         EcoCashReference,
         Amount,
         StatusId,
         Status,
         Error,
         DateCreated
     });
 }
        public void RequestEcoCashStatus()
        {
            var previousStatusId = StatusId;

            if (LivePayments)
            {
                var resourceUri = $"{EcoCashUrl}{SanitiseMobileNumber(BookingUser.Telephone)}/transactions/amount/{ClientCorrelator}";

                var client = new RestClient(resourceUri)
                {
                    Authenticator = new HttpBasicAuthenticator(EcoCashUsername, EcoCashPassword)
                };

                var request = new RestRequest(Method.GET);
                request.AddHeader("Cache-Control", "no-cache");
                request.AddHeader("Content-Type", "application/json");
                var response = client.Execute <dynamic>(request);

                if (response.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    try
                    {
                        Error = response.Data["text"];
                    }
                    catch { }

                    try
                    {
                        var status = response.Data["transactionOperationStatus"];
                        if (status == "COMPLETED")
                        {
                            StatusId = TransactionStatus.Completed;
                        }
                        else if (status == "PENDING SUBSCRIBER VALIDATION")
                        {
                            StatusId = TransactionStatus.PendingSubscriberValidation;
                        }
                        else if (status == "TRANSACTION TIMEDOUT")
                        {
                            StatusId = TransactionStatus.TransactionTimedout;
                        }
                        else
                        {
                            StatusId = TransactionStatus.Failed;
                        }

                        if (StatusId == TransactionStatus.Completed)
                        {
                            if (EcoCashLog)
                            {
                                Log += Environment.NewLine + JsonConvert.SerializeObject(response);
                            }

                            ServerReference  = response.Data["serverReferenceCode"];
                            EcoCashReference = response.Data["ecocashReference"];
                        }
                    }
                    catch
                    {
                        StatusId = TransactionStatus.Error;
                        Save();
                        return;
                    }
                }
                else
                {
                    StatusId = TransactionStatus.Error;
                }
            }
            else
            {
                StatusId         = TransactionStatus.Completed;
                EcoCashReference = "ECO-" + Guid.NewGuid().ToString();
            }

            Save();

            if (previousStatusId != TransactionStatus.Completed && StatusId == TransactionStatus.Completed)
            {
                BookingUser.StatusId = BookingUserStatus.Paid;
                BookingUser.Save();

                new Journal
                {
                    Amount           = Amount,
                    BookingId        = BookingId,
                    EcoCashReference = EcoCashReference,
                    Reconciled       = false,
                    Title            = $"Payment received from {BookingUser.Name} {BookingUser.Telephone}",
                    TypeId           = JournalType.Payment,
                    UserId           = BookingUser.UserId ?? Booking.UserId
                }.Save();

                var bookingUsers = BookingUser.List(BookingId: BookingId);
                if (bookingUsers.Count(e => e.StatusId != BookingUserStatus.Paid) == 0)
                {
                    var booking = Booking.Find(BookingId);
                    booking.StatusId = BookingStatus.InProgress;
                    booking.Save();

                    var notifications = Notification.List(BookingId: booking.Id, Type: NotificationType.BookingConfirmed);
                    foreach (var notification in notifications)
                    {
                        notification.StatusId = NotificationStatus.Complete;
                        notification.Save();
                    }

                    new Notification
                    {
                        Booking = booking,
                        GroupId = NotificationGroup.Offering,
                        TypeId  = NotificationType.PaymentReceived,
                        User    = User.Find(Id: booking.Listing.UserId)
                    }.Save(Notify: true);

                    new Notification
                    {
                        Booking = booking,
                        GroupId = NotificationGroup.Seeking,
                        TypeId  = NotificationType.PaymentReceived,
                        User    = User.Find(Id: booking.UserId)
                    }.Save(Notify: false);

                    Counter.Hit(BookingUser.UserId ?? 0, Counters.CompletePayment, booking.Service.CategoryId);
                    SendPaymentNotification();
                }
            }
        }
        public object CreateTransaction(TransactionModel Model)
        {
            if (!ModelState.IsValid)
            {
                return(Error(ModelState));
            }

            var booking = Entities.Booking.Find(Id: Model.BookingId);

            if (booking == null || booking.UserId != CurrentUser.Id)
            {
                return(Error("Booking not found"));
            }

            booking.BookingUsers = Entities.BookingUser.List(BookingId: booking.Id);

            var bookingUsers = new List <Core.Entities.BookingUser>();

            foreach (var user in Model.Users)
            {
                if (user == null)
                {
                    continue;
                }

                if (user.Quantity == 0)
                {
                    user.Quantity = 1;
                }
                if (booking.Quantity == 0)
                {
                    booking.Quantity = 1;
                }

                var bookingUser = booking.BookingUsers.FirstOrDefault(o => o.Telephone == user.Telephone);
                if (bookingUser == null)
                {
                    bookingUser = new Entities.BookingUser
                    {
                        Booking   = booking,
                        Name      = user.Name,
                        Ratio     = user.Quantity / booking.Quantity,
                        StatusId  = Entities.BookingUserStatus.Pending,
                        Telephone = user.Telephone
                    };

                    var registeredUser = Entities.User.Find(Telephone: user.Telephone);
                    if (registeredUser.Id > 0)
                    {
                        bookingUser.User = registeredUser;
                    }

                    bookingUser.Save();
                    booking.BookingUsers.Add(bookingUser);
                }
                else
                {
                    bookingUser.Ratio = user.Quantity / booking.Quantity;

                    var registeredUser = Entities.User.Find(Telephone: user.Telephone);
                    if (registeredUser.Id > 0)
                    {
                        bookingUser.User = registeredUser;
                    }

                    bookingUser.Save();
                }

                bookingUsers.Add(bookingUser);
            }

            foreach (var bookingUser in booking.BookingUsers)
            {
                if (bookingUsers.Count(e => e.Id == bookingUser.Id) == 0)
                {
                    bookingUser.Delete();
                }
            }

            var success      = true;
            var errorMessage = string.Empty;
            var transactions = Entities.Transaction.List(BookingId: booking.Id);

            foreach (var transaction in transactions.Where(e => e.StatusId == Entities.TransactionStatus.Failed))
            {
                transaction.StatusId = Entities.TransactionStatus.Error;
                transaction.Save();
            }

            foreach (var bookingUser in bookingUsers)
            {
                var transaction = transactions.FirstOrDefault(o =>
                                                              o.BookingUserId == bookingUser.Id &&
                                                              o.StatusId != Entities.TransactionStatus.Error &&
                                                              o.StatusId != Entities.TransactionStatus.Failed);

                if (transaction == null)
                {
                    transaction = new Entities.Transaction
                    {
                        Amount      = booking.Price * bookingUser.Ratio,
                        Booking     = booking,
                        BookingUser = bookingUser,
                        StatusId    = Entities.TransactionStatus.Pending
                    };

                    transaction.Save();
                    transaction.RequestEcoCashPayment();
                    transactions.Add(transaction);

                    Entities.Counter.Hit(bookingUser.UserId ?? 0, Entities.Counters.InitiatePayment, booking.Service.CategoryId);

                    if (transaction.StatusId != Entities.TransactionStatus.PendingSubscriberValidation)
                    {
                        success      = false;
                        errorMessage = $"{bookingUser.Telephone}: {transaction.Error}";
                    }
                }
            }

            if (success && transactions.Count > 0)
            {
                return(Success(new
                {
                    Transactions = transactions.Select(e => e.Json())
                }));
            }
            else
            {
                return(Error(errorMessage.Coalesce("No transactions were created")));
            }
        }