/*Returns the total cost of all items in the supplied order.*/ public double getOrderCost(Order order) { double totalCost = 0; try { List <OrderLine> orderLines = new OrderLineService().getByOrder(order); //Throws NoRecordException //set order total cost foreach (OrderLine orderLine in orderLines) { if (orderLine.orderLineType.id == 1) //rent { TimeSpan duration = orderLine.enddate - orderLine.startdate; totalCost += orderLine.dvdInfo.rent_price * duration.Days; } else if (orderLine.orderLineType.id == 2) //buy { totalCost += orderLine.dvdInfo.buy_price; } } } catch (NoRecordException) { } return(Math.Round(totalCost, 2)); }
/*Returns a dictionary of (dvd_info_id, number_of_times_bought).*/ public Dictionary <String, int> getItemsBoughtByCustomer(Customer customer) { Dictionary <String, int> dvdAmount = new Dictionary <String, int>(); try { List <OrderLine> orderLines = new OrderLineService().getByCustomer(customer); foreach (OrderLine orderLine in orderLines) { if (!dvdAmount.ContainsKey(orderLine.dvdInfo.dvd_info_id)) { dvdAmount.Add(orderLine.dvdInfo.dvd_info_id, 1); } else { dvdAmount[orderLine.dvdInfo.dvd_info_id] = dvdAmount[orderLine.dvdInfo.dvd_info_id] + 1; } } } catch (NoRecordException ex) { //user has never purchased anything } return(dvdAmount); }
/*Returns the number of items the user has purchased.*/ public int getNumberOfOrderLinesForCustomer(Customer customer) { List <OrderLine> orderLines; try { orderLines = new OrderLineService().getByCustomer(customer); } catch (NoRecordException ex) { //user has never purchased anything orderLines = new List <OrderLine>(); } return(orderLines.Count); }
/*Converts the customer's shopping cart to an order and returns it*/ public Order createOrder(Customer user) { try { //get all items currently in cart List <ShoppingcartItem> cartContent = new ShoppingCartService().getCartContentForCustomer(user); //Throws NoRecordException //create new order for this user int orderID = new OrderService().addOrderForCustomer(user); //Throws NoRecordException Order thisOrder = new OrderService().getByID(orderID.ToString()); OrderLineService orderLineService = new OrderLineService(); //add cart items to newly created order foreach (ShoppingcartItem item in cartContent) { OrderLine orderline = new OrderLine { order = new OrderService().getByID(orderID.ToString()), //Throws NoRecordException dvdInfo = new DvdInfoService().getByID(item.dvdInfo.dvd_info_id.ToString()), //Throws NoRecordException //dvd_copy_id = copy.dvd_copy_id, //don't add a copy_id yet, only do this when a user has paid (id will be set in admin module) startdate = item.startdate, enddate = item.enddate, //order_line_type_id is verhuur/verkoop? dan kunnen we dat eigenlijk via join ophalen via dvd_copy tabel orderLineType = new OrderLineTypeService().getByID(item.dvdCopyType.id.ToString()) //Throws NoRecordException }; if (orderLineService.add(orderline)) { //succes } } //clear cart if (new ShoppingCartService().deleteByCustomer(user)) { //success } return(thisOrder); } catch (NoRecordException) { return(null); } }
/*Returns the number of items currently being rented by the user.*/ public int getNumberOfActiveRentOrdersCopiesForCustomer(Customer customer) { int numberOfCurrentlyRentedItems = 0; try { List <OrderLine> orderLines = new OrderLineService().getActiveRentOrderLinesByCustomer(customer); //Throws NoRecordException foreach (OrderLine orderLine in orderLines) { numberOfCurrentlyRentedItems++; } } catch (NoRecordException ex) { //user has no active rent orders } return(numberOfCurrentlyRentedItems); }
/*Deletes the supplied orderLine from its order. Also deletes the order itself if it no longer contains any orderLines after deleting the supplied one.*/ public bool deleteItemFromOrder(OrderLine orderLine) { Order order = orderLine.order; if (new OrderLineService().delete(orderLine)) { try { List <OrderLine> orderLines = new OrderLineService().getByOrder(order); } catch (NoRecordException ex) { //this order no longer contains any orderlines, delete the entire order new OrderService().delete(order); } return(true); } else { return(false); } }
/*Sets the supplied order as paid and assigns a dvd copy to each orderLine (if possible).*/ public void payOrder(Order selectedOrder) { //set the order status to PAID selectedOrder.orderstatus = new OrderStatusService().getByID("2"); //Throws NoRecordException new OrderService().updateOrder(selectedOrder); //assign copies to the orderlines List <OrderLine> orderLines = new OrderLineService().getByOrder(selectedOrder); //Throws NoRecordException foreach (OrderLine orderLine in orderLines) { if (orderLine.orderLineType.id == 1) //rent copy { DvdInfo thisDVD = orderLine.dvdInfo; //get all unavailable dates starting from TODAY Dictionary <int, List <DateTime> > dicCopyUnavailableDates = new AvailabilityModel().getAllUnavailableDaysPerCopyForDvdInfo(thisDVD, DateTime.Today); //Throws NoRecordException Dictionary <int, int> dicDaysFreeForCopy = new Dictionary <int, int>(); //contains the number of free days for the dvdCopy (copy-id, freedays) int selectedCopyId = -1; //id of the copy that will be assigned to this orderLine //loop over the list of occupied dates per copy, check how many free dates exist around the chosen period, store that amount in dicDaysFreeForCopy foreach (KeyValuePair <int, List <DateTime> > entry in dicCopyUnavailableDates) { //determine how many days the copy will be rented int rentPeriodDays = (orderLine.enddate - orderLine.startdate).Days; bool copyIsAvailable = true; for (int i = 0; i <= rentPeriodDays; i++) { //loop over the occupied days, check if the copy is available on all of the requested dates if (entry.Value.Contains(orderLine.startdate.AddDays(i))) { //one of the requested days is not free, this copy can not be used copyIsAvailable = false; } } if (copyIsAvailable) { //we now know this copy has the needed time available, now to determine the size of this free period dicDaysFreeForCopy.Add(entry.Key, 0); //check the amount of free days between start date and the first unavailable date (going backwards) bool unavailableFound = false; int offset = 0; do { if (entry.Value.Contains(orderLine.startdate.AddDays(-offset)) || orderLine.startdate.AddDays(-offset) == DateTime.Today) { //the copy is reserved on this date, break out of loop unavailableFound = true; } else { dicDaysFreeForCopy[entry.Key]++; offset++; } } while (!unavailableFound); //check the amount of free days between end date and the first unavailable date (going forward) unavailableFound = false; offset = 0; do { if (entry.Value.Contains(orderLine.enddate.AddDays(offset)) || orderLine.enddate.AddDays(offset) >= DateTime.Today.AddDays(14)) { //the copy is reserved on this date, break out of loop unavailableFound = true; } else { dicDaysFreeForCopy[entry.Key]++; offset++; } } while (!unavailableFound); } } int daysFree = 1000; //loop over all copies, select the one with the smallest free window foreach (KeyValuePair <int, int> entryDays in dicDaysFreeForCopy) { if (entryDays.Value < daysFree) { daysFree = entryDays.Value; selectedCopyId = entryDays.Key; } } //assign the copy if it has been found if (selectedCopyId > 0) { try { orderLine.dvdCopy = new DvdCopyService().getByID(selectedCopyId.ToString()); //Throws NoRecordException || DALException } catch (NoRecordException) { //No dvd's were found } new OrderLineService().updateOrderLine(orderLine); //update the amount_sold field of the dvdInfo record orderLine.dvdInfo.amount_sold = orderLine.dvdInfo.amount_sold + 1; new DvdInfoService().update(orderLine.dvdInfo); //Throws NoRecordException } else { //no copies with future orderLines are available for this reservation/rent order //get all fully available copies (=copies with no orderLines in the future) to assign to this orderline try { List <DvdCopy> dvdCopies = new DvdCopyService().getAllFullyAvailableCopies(thisDVD, orderLine.startdate); //Throws NoRecordException || DALException //set the first available copy as the copy for this orderline orderLine.dvdCopy = dvdCopies[0]; //update database new OrderLineService().updateOrderLine(orderLine); //update the amount_sold field of the dvdInfo record dvdCopies[0].dvdinfo.amount_sold += 1; new DvdInfoService().update(dvdCopies[0].dvdinfo); } catch (Exception ex) { //no copy can be assigned at this time, this means someone else received the last copy between the time where //this user added the item to his cart and when he payed for the order. } } } else if (orderLine.orderLineType.id == 2) //sale copy { //get all available copies //get this list again for every item so you can add a new, available copy to the order List <DvdCopy> availableCopies = new DvdCopyService().getAllInStockBuyCopiesForDvdInfo(orderLine.dvdInfo); //Throws NoRecordException || DALException //get the first available copy //set the found copy as the copy for this orderline orderLine.dvdCopy = availableCopies[0]; new OrderLineService().updateOrderLine(orderLine); //update the amount_sold field of the dvdInfo record DvdInfo dvdInfo = availableCopies[0].dvdinfo; dvdInfo.amount_sold = dvdInfo.amount_sold + 1; new DvdInfoService().update(dvdInfo); //Throws NoRecordException //mark the found copy as NOT in_stock availableCopies[0].in_stock = false; if (new DvdCopyService().updateCopy(availableCopies[0])) //Throws NoRecordException || DALException { //Success, record updated } } } }
/**Returns a list of recommendations based on the user's order history. * 1) Gets all past orders and determines the user's 3 favourite genres. * 2) Gets a list of DVDs that have the most matches with the user's favourites. * A dvd that contains all 3 favourite genres will rank higher than a dvd that only matches 1 favourite genre. * 3) Removes dvds that the user has already rented or bought before. * 4) If no dvd's are left (or if the user had no orderlines), a list of DVDs is generated based on the pages the user has visited. */ public List <DvdInfo> getRecommendations(Customer customer, int amount) { List <DvdInfo> dvdList = new List <DvdInfo>(); List <Genre> genres = new List <Genre>(); List <OrderLine> orderLines; try { orderLines = new OrderLineService().getByCustomer(customer); //Throws NoRecordException } catch (Exception error) { orderLines = new List <OrderLine>(); } orderLinesDvdIds = new List <String>(); //list that contains the DVDids of the orderlines (=movies that the user has rented before) GenreService genreService = new GenreService(); DvdInfoService dvdInfoService = new DvdInfoService(); //customer has at least 1 order, base recommendations on orderLines if (orderLines.Count > 0) { foreach (OrderLine line in orderLines) { String dvdID = line.dvdInfo.dvd_info_id; genres.AddRange(genreService.getGenresForDvd(dvdID)); //Throws NoRecordException //fill orderLinesDvdIds if (!orderLinesDvdIds.Contains(dvdID)) { orderLinesDvdIds.Add(dvdID); } } //put genres in a dictionary (genreID, numberOfOccurrances) Dictionary <int, int> genreCountMap = new Dictionary <int, int>(); foreach (Genre genre in genres) { if (genreCountMap.ContainsKey(genre.genre_id)) { genreCountMap[genre.genre_id]++; } else { genreCountMap.Add(genre.genre_id, 1); } } //loop over dictionary and find the 3 most occuring genres int[] maxGenres = { 0, 0, 0 }; int[] maxCounts = { 0, 0, 0 }; foreach (KeyValuePair <int, int> pair in genreCountMap) { if (maxCounts[0] < pair.Value) { maxCounts[2] = maxCounts[1]; maxCounts[1] = maxCounts[0]; maxCounts[0] = pair.Value; maxGenres[2] = maxGenres[1]; maxGenres[1] = maxGenres[0]; maxGenres[0] = pair.Key; } else if (maxCounts[1] < pair.Value) { maxCounts[2] = maxCounts[1]; maxCounts[1] = pair.Value; maxGenres[2] = maxGenres[1]; maxGenres[1] = pair.Key; } else if (maxCounts[2] < pair.Value) { maxCounts[2] = pair.Value; maxGenres[2] = pair.Key; } } //we now have the user's 3 favourite genres in maxGenres, use that info to get the dvds that match those 3 genres the most //get max 16 dvds. Index will always show maximum 4, but catalog can show up to 16 List <String> dvdIds = dvdInfoService.getRecommendations(maxGenres, 16); //Throws NoRecordException List <String> dvdTempIds = new List <String>(); //only accept dvd's that the user had not watched yet foreach (String id in dvdIds) { if (!orderLinesDvdIds.Contains(id)) { dvdTempIds.Add(id); } } if (dvdTempIds.Count > 0) { foreach (String id in dvdTempIds) { dvdList.Add(dvdInfoService.getByID(id.ToString())); //Throws NoRecordException } } else { //customer has already bought or rented every suggestion, recommend the movies whose pages the user has viewed most often dvdList = getMostViewedDvdInfos(customer); //Throws NoRecordException } } else { //customer has no orderlines, recommend the movies whose pages the user has viewed the most dvdList = getMostViewedDvdInfos(customer); //Throws NoRecordException } //remove elements until the list size is the requested size (4 for index row, 16 for catalog page) //loop deletes a random item until the size is ok so the user gets different recommendations on every visit/refresh Random rnd = new Random(); while (dvdList.Count > amount) { dvdList.RemoveAt(rnd.Next(dvdList.Count)); } return(dvdList); }