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); }
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); }