Exemple #1
0
        public HttpResponseMessage BookEvent(BookEventRequest request)
        {
            BookEventResponse responseData;

            try
            {
                //Authenticate API key
                long?hostId = HostServices.GetCallerHostId();
                if (!hostId.HasValue)
                {
                    Log.Warn(ResponseMessages.InvalidAPIKey);
                    return(Request.CreateResponse(new GenericResponse(null, ResponseCodes.InvalidAPIKey, ResponseMessages.InvalidAPIKey)));
                }

                //Validate input
                if (request == null ||
                    string.IsNullOrEmpty(request.EventReferenceId) ||
                    string.IsNullOrEmpty(request.CustomerReferenceId) ||
                    request.Tickets == null ||
                    request.Tickets.Count == 0)
                {
                    return(Request.CreateResponse(new GenericResponse(null, ResponseCodes.InvalidParam, ResponseMessages.InvalidParam)));
                }

                //Perform transaction
                BookingServices bookingService = new BookingServices();
                string          status         = null;
                responseData = bookingService.BookEvent(hostId.Value, request, out status);

                if (status == BookEventStatuses.CustomerNotFound)
                {
                    return(Request.CreateResponse(new GenericResponse(null, BookEventStatuses.CustomerNotFound, "CustomerNotFound")));
                }
                else if (status == BookEventStatuses.EventNotFound)
                {
                    return(Request.CreateResponse(new GenericResponse(null, BookEventStatuses.EventNotFound, "EventNotFound")));
                }
                else if (status == BookEventStatuses.TierNotFound)
                {
                    return(Request.CreateResponse(new GenericResponse(null, BookEventStatuses.TierNotFound, "TierNotFound")));
                }
                else if (status == BookEventStatuses.EventNotActive)
                {
                    return(Request.CreateResponse(new GenericResponse(null, BookEventStatuses.EventNotActive, "Event is already cancelled or closed.")));
                }
                else if (status == BookEventStatuses.EventHasAlreadyStarted)
                {
                    return(Request.CreateResponse(new GenericResponse(null, BookEventStatuses.EventHasAlreadyStarted, "EventHasAlreadyStarted")));
                }
                else if (status == BookEventStatuses.InsufficientTickets)
                {
                    return(Request.CreateResponse(new GenericResponse(null, BookEventStatuses.InsufficientTickets, "InsufficientTickets")));
                }
                else if (status == BookEventStatuses.CustomerInsufficientFunds)
                {
                    return(Request.CreateResponse(new GenericResponse(null, BookEventStatuses.CustomerInsufficientFunds, "CustomerInsufficientFunds")));
                }
                else if (status == BookEventStatuses.InvalidTicketQuantity)
                {
                    return(Request.CreateResponse(new GenericResponse(null, BookEventStatuses.InvalidTicketQuantity, "InvalidTicketQuantity")));
                }
                else if (status == BookEventStatuses.Success)
                {
                    return(Request.CreateResponse(new GenericResponse(responseData, ResponseCodes.Success, ResponseMessages.Success)));
                }
                else
                {
                    Log.Error("Unrecognized status: " + status);
                    return(Request.CreateResponse(new GenericResponse(null, ResponseCodes.Error, ResponseMessages.Error)));
                }
            }
            catch (Exception ex)
            {
                Log.Exception(ex);
                return(Request.CreateResponse(new GenericResponse(null, ResponseCodes.Error, ResponseMessages.Error)));
            }
        }
        public BookEventResponse BookEvent(long hostId, BookEventRequest value, out string status)
        {
            BookEventResponse result = null;

            //Validate if customer exist
            CustomerServices customerServices = new CustomerServices();
            var customer = customerServices.GetCustomerByRef(hostId, value.CustomerReferenceId);

            if (customer == null)
            {
                status = BookEventStatuses.CustomerNotFound;
                return(null);
            }

            //Validate if event and tier exist
            EventsServices eventsServices = new EventsServices();
            EventInfo      eventInfo      = eventsServices.GetEventByRef(hostId, value.EventReferenceId);

            if (eventInfo == null)
            {
                status = BookEventStatuses.EventNotFound;
                return(null);
            }
            List <EventTierInfo> eventTiers = eventsServices.GetEventTiersByEventId(eventInfo.EventId.Value);

            if (eventTiers == null && eventTiers.Count == 0)
            {
                status = BookEventStatuses.EventNotFound;
                return(null);
            }

            //Validate event status
            if (eventInfo.Status != "Active")
            {
                status = BookEventStatuses.EventNotActive;
                return(null);
            }

            //Validate if event has already started
            if (DateTime.UtcNow >= eventInfo.StartDate)
            {
                status = BookEventStatuses.EventHasAlreadyStarted;
                return(null);
            }

            //Validate if all requested tiers exist
            List <string> allAvailableEventTiers = eventTiers.Select(x => x.ReferenceId).ToList();
            List <string> requestedEventTiers    = value.Tickets.Select(x => x.EventTierReferenceId).ToList();
            bool          contained = !requestedEventTiers.Except(allAvailableEventTiers).Any();

            if (!contained)
            {
                status = BookEventStatuses.TierNotFound;
                return(null);
            }

            //Validate requested ticket quantities (must be more than zero)
            if (value.Tickets.Where(x => x.Quantity < 1).Count() > 0)
            {
                status = BookEventStatuses.InvalidTicketQuantity;
                return(null);
            }

            //Validate if tickets are still available for the requested quantities
            foreach (var ticket in value.Tickets)
            {
                var tier = eventTiers.Where(x => x.ReferenceId == ticket.EventTierReferenceId).ToList()[0];
                if (tier.AvailableTickets < ticket.Quantity)
                {
                    status = BookEventStatuses.InsufficientTickets;
                    return(null);
                }
            }

            //Calculate total cost
            decimal totalCost = 0;

            foreach (var ticket in value.Tickets)
            {
                var tier = eventTiers.Where(x => x.ReferenceId == ticket.EventTierReferenceId).ToList()[0];
                totalCost += (ticket.Quantity * tier.Price.Value);
            }

            //Check customer wallet balance
            if (customer.WalletBalance < totalCost)
            {
                status = BookEventStatuses.CustomerInsufficientFunds;
                return(null);
            }

            //TODO: Transaction lock for thread safety

            string bookingConfirmation = null;
            string ticketNumber        = null;
            string ticketUniqueId      = null;
            List <KeyValuePair <long, string> > tierTicketNumbers = new List <KeyValuePair <long, string> >();

            //Insert customer booking
            bookingConfirmation = GenerateBookingConfirmation(hostId);
            long bookingId = InsertUserBooking(customer.CustomerId.Value, eventInfo.EventId.Value, bookingConfirmation);

            //Perform transaction
            WalletServices walletService = new WalletServices();

            walletService.Transfer(customer.WalletAddress, eventInfo.WalletAddress, totalCost, bookingId, "Booking");

            //Insert customer tickets
            foreach (var ticketPurchase in value.Tickets)
            {
                var tier = eventTiers.Where(x => x.ReferenceId == ticketPurchase.EventTierReferenceId).ToList()[0];

                for (int i = 0; i < ticketPurchase.Quantity; i++)
                {
                    ticketNumber   = GenerateTicketNumber(eventInfo.EventId.Value);
                    ticketUniqueId = HashUtility.GenerateHash();

                    InsertUserTicket(customer.CustomerId.Value, bookingId, eventInfo.EventId.Value, tier.TierId.Value, ticketNumber, tier.Price.Value, "Active", ticketUniqueId);

                    tierTicketNumbers.Add(new KeyValuePair <long, string>(tier.TierId.Value, ticketNumber));
                }
            }

            //Update tickets availability
            foreach (var ticket in value.Tickets)
            {
                var tier = eventTiers.Where(x => x.ReferenceId == ticket.EventTierReferenceId).ToList()[0];
                UpdateAvailableTickets(tier.TierId.Value, tier.AvailableTickets.Value - ticket.Quantity);
            }

            //Commit to blockchain
            ContractApi blockchainContract = new ContractApi();

            for (int i = 0; i < value.Tickets.Count; i++)
            {
                var ticket = value.Tickets[i];
                var tier   = eventTiers
                             .Where(x => x.ReferenceId == ticket.EventTierReferenceId).ToList()[0];

                List <string> ticketNumbers = tierTicketNumbers
                                              .Where(x => x.Key == tier.TierId.Value)
                                              .Select(x => x.Value).ToList();

                // Update: Use BookEventV2 method on smart contract
                //blockchainContract.BookEvent(customer.CustomerAddress, eventInfo.EventUniqueId, tier.TierUniqueId, ticketNumbers);
                foreach (string number in ticketNumbers)
                {
                    blockchainContract.BookEventV2(customer.CustomerAddress, eventInfo.EventUniqueId, tier.TierUniqueId, number);
                }
            }

            result = new BookEventResponse();
            result.ConfirmationNumber = bookingConfirmation;
            result.TicketNumbers      = tierTicketNumbers.Select(x => x.Value).ToList();

            status = BookEventStatuses.Success;
            return(result);
        }
Exemple #3
0
        public EventResponse BookEvent(BookEventRequest model)
        {
            var response = new EventResponse();
            var member   = _memberProvider.GetLoggedInMember();

            if (member == null)
            {
                response.Error = "Unable to find logged in member record.";
                return(response);
            }

            var  membershipExpiry    = member.GetValue <DateTime>(MemberProperty.MembershipExpiry);
            bool isMembershipExpired = membershipExpiry < DateTime.Now;

            if (isMembershipExpired)
            {
                response.Error = "Your membership has expired, please renew your membership before booking any events.";
                return(response);
            }

            var memberType = member.GetValue <MembershipTypeEnum>(MemberProperty.membershipType);
            var isGuest    = memberType == MembershipTypeEnum.Guest;

            if (string.Equals(model.EventTypeName, "Open Water Swim", StringComparison.OrdinalIgnoreCase) && !isGuest && !member.GetValue <bool>(MemberProperty.OpenWaterIndemnityAcceptance))
            {
                response.Error = "You need to signup for open water swimming (on your member details page) before you can book onto open water swim sessions.";
                return(response);
            }

            if (string.Equals(model.EventTypeName, "Pool Swim", StringComparison.OrdinalIgnoreCase) && !CanBookPoolSwim(member, model.EventSlotId))
            {
                response.Error = "You need to signup for swim subs (on your member details page) before you can book onto pool swim sessions.";
                return(response);
            }

            if (member.GetValue <int>(MemberProperty.TrainingCredits) < model.Cost)
            {
                response.Error = "You do not have enough training credits to book that event.";
                return(response);
            }

            var eventSlot = _eventSlotRepository.GetById(model.EventSlotId);

            if (!eventSlot.HasSpace)
            {
                response.Error = "There is no space remaining on that training slot.";
                return(response);
            }

            if (eventSlot.EventParticipants.Any(ep => ep.MemberId == member.Id))
            {
                response.Error = "You are already booked onto that event.";
                return(response);
            }

            var eventParticipant = new EventParticipant()
            {
                EventSlotId  = model.EventSlotId,
                AmountPaid   = model.Cost,
                MemberId     = member.Id,
                RaceDistance = string.IsNullOrEmpty(model.RaceDistance) ? null : model.RaceDistance
            };

            //Debit cost from members credits
            var credits = member.GetValue <int>(MemberProperty.TrainingCredits);

            credits = credits - model.Cost;
            member.SetValue(MemberProperty.TrainingCredits, credits);
            Services.MemberService.Save(member);

            eventParticipant = _eventParticipantRepository.Create(eventParticipant);
            Logger.Info(typeof(EventController), $"New event slot booking - Member: {member.Name} , Event: {model.EventTypeName} on {eventSlot.Date.ToString("dd/MM/yyyy")} for £{model.Cost}.");

            return(response);
        }