Exemple #1
0
        /// <summary>
        /// Inserts a new customer record in database.
        /// </summary>
        public CreateCustomerResponse CreateCustomer(long hostId, CreateCustomerRequest value)
        {
            CreateCustomerResponse result = new CreateCustomerResponse();

            long newCustomerId = 0;

            //Generate address
            string customerAddress = HashUtility.GenerateHash();

            using (var context = new AnnoDBContext())
            {
                //Insert customer to database
                Customer customer = new Customer()
                {
                    host_id       = hostId,
                    ref_id        = value.ReferenceId,
                    address       = customerAddress,
                    record_status = RecordStatuses.Live,
                    created_date  = DateTime.UtcNow
                };
                context.Customer.Add(customer);
                context.SaveChanges();

                //Get the Id of the newly created customer
                newCustomerId = customer.customer_id;
            }

            //Create customer wallet
            WalletServices walletServices = new WalletServices();

            walletServices.CreateWallet(newCustomerId, WalletOwnerTypes.Customer, customerAddress);

            //Commit to blockchain
            IdentityServices   identityService    = new IdentityServices();
            BlockchainContract blockchainContract = new BlockchainContract();

            blockchainContract.CreateCustomer(identityService.AddressOf(IdentityServices.AddressTypes.Host, hostId), customerAddress, value.ReferenceId);

            //TODO: For demo purpose, give 1000 ANN tokens to new customers
            walletServices.Transfer(Config.OwnerScriptHash, customerAddress, 1000, null, "Demo");

            //Commit to blockchain
            blockchainContract.Transfer(Config.OwnerScriptHash, customerAddress, 1000);

            result.WalletAddress = customerAddress;
            result.WalletBalance = 1000;

            return(result);
        }
Exemple #2
0
        /// <summary>
        /// Inserts a new host record in database.
        /// </summary>
        public void CreateHost(CreateHostRequest value, out string newAPIKey)
        {
            long newHostId = 0;

            //Generate address
            WalletServices walletServices = new WalletServices();
            string         hostAddress    = walletServices.GenerateWalletAddress();

            using (var context = new AnnoDBContext())
            {
                //Insert host to database
                var newHost = new Host()
                {
                    name          = value.Name,
                    address       = hostAddress,
                    record_status = RecordStatuses.Live,
                    created_date  = DateTime.UtcNow
                };
                context.Host.Add(newHost);
                context.SaveChanges();

                //Get the ID of the newly created host
                newHostId = newHost.host_id;

                //Generate new API key
                newAPIKey = Guid.NewGuid().ToString().Replace("-", "");

                //Insert into api_keys table
                context.ApiKey.Add(new ApiKey()
                {
                    host_id       = newHostId,
                    api_key       = newAPIKey,
                    record_status = RecordStatuses.Live,
                    created_date  = DateTime.UtcNow
                });
                context.SaveChanges();

                //Create host wallet
                WalletServices walletService = new WalletServices();
                walletService.SaveWallet(newHostId, WalletOwnerTypes.Host, hostAddress);
            }

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

            blockchainContract.CreateHost(hostAddress, value.Name);
        }
        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);
        }
        //TODO: performance optimize this method to cancel tickets in bulk
        public CancelTicketResponse CancelAndRefundTicket(long hostId, long ticketId, out string status)
        {
            CancelTicketResponse result = null;

            AdmissionServices admissionServices = new AdmissionServices();

            //Get ticket info
            var ticket = admissionServices.GetTicketById(ticketId);

            if (ticket == null)
            {
                status = CancelTicketStatuses.TicketNotFound;
                return(null);
            }
            if (ticket.Status == TicketStatuses.Used)
            {
                status = CancelTicketStatuses.TicketAlreadyUsed;
                return(null);
            }
            if (ticket.Status == TicketStatuses.Cancelled)
            {
                status = CancelTicketStatuses.TicketAlreadyCancelled;
                return(null);
            }

            //Get event info
            var eventInfo = GetEventByRef(hostId, ticket.EventReferenceId);

            if (eventInfo == null)
            {
                status = CancelTicketStatuses.EventNotFound;
                return(null);
            }
            //Validate event status
            if (eventInfo.Status != EventStatuses.Active)
            {
                status = CancelTicketStatuses.EventNotActive;
                return(null);
            }
            //Validate if event start date is over
            if (DateTime.UtcNow >= eventInfo.StartDate)
            {
                status = CancelTicketStatuses.EventHasAlreadyStarted;
                return(null);
            }

            //Get event tier
            EventsServices eventsServices = new EventsServices();
            var            eventTier      = eventsServices.GetEventTiersByRef(hostId, ticket.TierReferenceId);

            if (eventTier == null)
            {
                status = CancelTicketStatuses.TierNotFound;
                return(null);
            }

            //Get customer info
            CustomerServices customerServices = new CustomerServices();
            var customer = customerServices.GetCustomerByRef(hostId, ticket.CustomerReferenceId);

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

            //Refund the customer using funds from the event address
            WalletServices walletServices = new WalletServices();

            walletServices.Transfer(eventInfo.WalletAddress, customer.WalletAddress, ticket.PaidPrice.Value, ticket.BookingId, "Refund");

            //Update ticket status to cancelled
            admissionServices.UpdateTicketStatus(ticketId, TicketStatuses.Cancelled);

            //Update ticket availability
            BookingServices bookingServices = new BookingServices();

            bookingServices.UpdateAvailableTickets(eventTier.TierId.Value, eventTier.AvailableTickets.Value + 1);

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

            blockchainContract.CancelTicket(ticket.TicketNo);

            status = CancelEventStatuses.Success;

            result                 = new CancelTicketResponse();
            result.EventTitle      = ticket.EventTitle;
            result.TierTitle       = ticket.TierTitle;
            result.PaidPrice       = ticket.PaidPrice;
            result.NewTicketStatus = TicketStatuses.Cancelled;

            return(result);
        }
        /// <summary>
        /// Inserts a new event record in the Events table.
        /// </summary>
        public void CreateEvent(long hostId, CreateEventsRequest value)
        {
            long          newEventId            = 0;
            List <string> eventTierUniqueIdList = new List <string>();

            //Generate address
            string eventUniqueId = HashUtility.GenerateHash();

            using (var context = new AnnoDBContext())
            {
                //Insert event to database
                var newEvent = new Events()
                {
                    host_id       = hostId,
                    ref_id        = value.ReferenceId,
                    title         = value.Title,
                    description   = value.Description,
                    start_date    = value.StartDate,
                    status        = "Active",
                    address       = eventUniqueId,
                    record_status = RecordStatuses.Pending,
                    created_date  = DateTime.UtcNow
                };
                context.Events.Add(newEvent);
                context.SaveChanges();

                //Get the ID of the newly created record
                newEventId = newEvent.event_id;

                //Insert event tiers to database
                foreach (var tier in value.Tiers)
                {
                    //Generate address
                    string eventTierUniqueId = HashUtility.GenerateHash();

                    //Insert event to database
                    var newEventTier = new EventsTier()
                    {
                        host_id           = hostId,
                        event_id          = newEventId,
                        ref_id            = tier.ReferenceId,
                        title             = tier.Title,
                        description       = tier.Description,
                        total_tickets     = tier.TotalTickets,
                        available_tickets = tier.TotalTickets, //available tickets is set to total tickets for initial insert
                        price             = Convert.ToDecimal(tier.Price),
                        status            = "Active",
                        address           = eventTierUniqueId,
                        record_status     = RecordStatuses.Live,
                        created_date      = DateTime.UtcNow
                    };
                    context.EventsTier.Add(newEventTier);
                    context.SaveChanges();

                    eventTierUniqueIdList.Add(eventTierUniqueId);
                }

                //Update event record status to live
                var record = context.Events.SingleOrDefault(x => x.event_id == newEventId);
                if (record != null)
                {
                    record.record_status = RecordStatuses.Live;
                    context.SaveChanges();
                }
            }

            //Create event wallet
            WalletServices walletServices = new WalletServices();

            walletServices.SaveWallet(newEventId, WalletOwnerTypes.Event, eventUniqueId);

            //Commit to blockchain
            IdentityServices identityServices = new IdentityServices();
            string           hostAddress      = identityServices.AddressOf(IdentityServices.AddressTypes.Host, hostId);

            ContractApi blockchainContract = new ContractApi();

            blockchainContract.CreateEvent(eventUniqueId, hostAddress, value.ReferenceId, value.Title, value.StartDate.Value, "Active");

            for (int i = 0; i < value.Tiers.Count; i++)
            {
                blockchainContract.CreateEventTier(
                    eventTierUniqueIdList[i], hostAddress, eventUniqueId, value.Tiers[i].ReferenceId, value.Tiers[i].Title,
                    value.Tiers[i].TotalTickets.Value, value.Tiers[i].TotalTickets.Value, value.Tiers[i].Price.Value);
            }
        }
        public ClaimEarningsResponse ClaimEarnings(long hostId, ClaimEarningsRequest value, out string status)
        {
            ClaimEarningsResponse result = null;

            //Get event
            var eventInfo = GetEventByRef(hostId, value.ReferenceId);

            if (eventInfo == null)
            {
                status = ClaimEarningsStatuses.EventNotFound;
                return(null);
            }

            //Check event status
            if (eventInfo.Status == EventStatuses.Cancelled)
            {
                status = ClaimEarningsStatuses.EventAlreadyCancelled;
                return(null);
            }
            if (eventInfo.Status == EventStatuses.Closed)
            {
                status = ClaimEarningsStatuses.EventAlreadyClaimed;
                return(null);
            }

            //Check if event has already started
            if (DateTime.UtcNow < eventInfo.StartDate.Value)
            {
                status = ClaimEarningsStatuses.EventNotStarted;
                return(null);
            }

            //Get host
            HostServices hostServices = new HostServices();
            var          host         = hostServices.GetHostInfoById(hostId);

            if (host == null)
            {
                status = ClaimEarningsStatuses.HostNotFound;
                return(null);
            }

            //Transfer event wallet balance to host wallet
            WalletServices walletServices = new WalletServices();

            walletServices.Transfer(eventInfo.WalletAddress, host.WalletAddress, eventInfo.WalletBalance.Value, null, "Claim");

            //Update event status
            UpdateEventStatusRequest req = new UpdateEventStatusRequest();

            req.ReferenceId = eventInfo.ReferenceId;
            req.NewStatus   = EventStatuses.Closed;
            UpdateEventStatus(hostId, req);

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

            blockchainContract.ClaimEarnings(eventInfo.EventUniqueId);

            status = ClaimEarningsStatuses.Success;

            result            = new ClaimEarningsResponse();
            result.EventTitle = eventInfo.Title;
            result.Earnings   = eventInfo.WalletBalance.Value;

            return(result);
        }