From c49c2ca8d8d4ca8e7110b682dec183d152053cc9 Mon Sep 17 00:00:00 2001 From: Mary Tran Date: Sat, 24 Nov 2018 14:23:17 -0500 Subject: [PATCH] Changed fetch service providers to include first and last name --- .../olympus/olympusservices/DBHelper.java | 754 ++++++++++++------ .../olympusservices/DBIntegrationTest.java | 161 ++-- 2 files changed, 612 insertions(+), 303 deletions(-) diff --git a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/DBHelper.java b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/DBHelper.java index bd369d6..2423793 100644 --- a/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/DBHelper.java +++ b/OlympusServices/app/src/main/java/com/uottawa/olympus/olympusservices/DBHelper.java @@ -675,7 +675,7 @@ public class DBHelper extends SQLiteOpenHelper { null, null, null, "1"); //If cursor has 1+ elements in it, username/service combination already exists in table - if (cursor != null && cursor.getCount() > 0){ + if (cursor.moveToFirst()){ if (cursor.getString(0).equals("active")){ cursor.close(); return false; @@ -711,11 +711,27 @@ public class DBHelper extends SQLiteOpenHelper { return deleteServiceProvidedByUser(serviceProvider.getUsername(), service.getName()); } + /** + * Removes service from service provider. Provider no longer offers this service. + * + * @param serviceProvider service provider who once offered service + * @param serviceName service to be removed + * + * @return true if service provider's status for this service is now inactive + */ public boolean deleteServiceProvidedByUser(ServiceProvider serviceProvider, String serviceName){ if (serviceProvider == null || serviceName == null) return false; return deleteServiceProvidedByUser(serviceProvider.getUsername(), serviceName); } + /** + * Removes service from service provider. Provider no longer offers this service. + * + * @param serviceProviderUsername service provider who once offered service + * @param serviceName service to be removed + * + * @return true if service provider's status for this service is now inactive + */ public boolean deleteServiceProvidedByUser(String serviceProviderUsername, String serviceName){ if (serviceProviderUsername == null || serviceName == null) return false; serviceName = serviceName.toLowerCase().trim(); @@ -729,19 +745,30 @@ public class DBHelper extends SQLiteOpenHelper { new String[]{serviceProviderUsername, serviceName}) > 0; } + /** + * Fetches all services provided by a service provider + * + * @param serviceProvider + * @return a list of [service, rate] + */ public List getAllServicesProvidedByUser(ServiceProvider serviceProvider){ if (serviceProvider == null) return new ArrayList<>(); return getAllServicesProvidedByUser(serviceProvider.getUsername()); } + /** + * Fetches all services provided by a service provider + * + * @param serviceProviderName + * @return a list of [service, rate] + */ public List getAllServicesProvidedByUser(String serviceProviderName){ if (serviceProviderName == null) return new ArrayList<>(); return getAll("SELECT " + TABLE_SERVICES + "." + COLUMN_SERVICE + ", " + TABLE_SERVICES + "." + COLUMN_RATE - + " FROM " + TABLE_SERVICES - + " JOIN " + TABLE_SERVICEPROVIDERS + + " FROM " + TABLE_SERVICES + " JOIN " + TABLE_SERVICEPROVIDERS + " ON " + TABLE_SERVICEPROVIDERS + "." + COLUMN_SERVICEPROVIDERSERVICE + " = " + TABLE_SERVICES + "." + COLUMN_SERVICE + " AND " + TABLE_SERVICEPROVIDERS + "." + COLUMN_SERVICEPROVIDERNAME @@ -749,29 +776,47 @@ public class DBHelper extends SQLiteOpenHelper { + " AND " + TABLE_SERVICEPROVIDERS + "." + COLUMN_ACTIVE + " = 'active'"); } - public List getAllProvidersByService(Service service){ + /** + * Fetches all service providers who provide a specified service + * + * @param service name of service + * @return a list of [username, first name, last name, average rating] sorted by rating + */ + public List getAllProvidersByService(Service service){ if (service == null) return new ArrayList<>(); return getAllProvidersByService(service.getName()); } - public List getAllProvidersByService(String serviceName){ + /** + * Fetches all service providers who provide a specified service + * + * @param serviceName name of service + * @return a list of [username, first name, last name, average rating] sorted by rating + */ + public List getAllProvidersByService(String serviceName){ if (serviceName == null) return new ArrayList<>(); serviceName = serviceName.toLowerCase().trim(); - List providers = getAll("SELECT " + COLUMN_SERVICEPROVIDERNAME - + " FROM " + TABLE_SERVICEPROVIDERS - + " WHERE " + COLUMN_SERVICEPROVIDERSERVICE + " = '" - + serviceName + "'" - + " AND " + TABLE_SERVICEPROVIDERS + "." + COLUMN_ACTIVE + " = 'active'"); - - List providerList = new ArrayList<>(); - for (String[] provider : providers){ - providerList.add(provider[0]); - } - return providerList; + return getAll( + "SELECT " + TABLE_SERVICEPROVIDERS + "." + COLUMN_SERVICEPROVIDERNAME + ", " + + TABLE_LOGIN + "." + COLUMN_FIRSTNAME + ", " + + TABLE_LOGIN + "." + COLUMN_LASTNAME + ", " + + TABLE_SERVICEPROVIDERS + "." + COLUMN_AVERAGERATING + + " FROM " + TABLE_SERVICEPROVIDERS + " JOIN " + TABLE_LOGIN + + " ON " + TABLE_SERVICEPROVIDERS + "." + COLUMN_SERVICEPROVIDERNAME + " = " + + TABLE_LOGIN + "." + COLUMN_USERNAME + + " AND " + COLUMN_SERVICEPROVIDERSERVICE + " = '" + serviceName + "'" + + " AND " + TABLE_SERVICEPROVIDERS + "." + COLUMN_ACTIVE + " = 'active'" + + " ORDER BY " + TABLE_SERVICEPROVIDERS + "." + COLUMN_AVERAGERATING + " DESC"); } + /** + * Updates a service provider's availabilities based on ServiceProvider object provided + * + * @param serviceProvider + * @return true if availability was updated successfully + */ public boolean updateAvailability(ServiceProvider serviceProvider){ //availability is stored as number of minutes from 00:00 if (serviceProvider == null) return false; @@ -801,27 +846,6 @@ public class DBHelper extends SQLiteOpenHelper { return true; } - private void addAvailabilityToContentValues(ContentValues contentValues, - String startColumn, String endColumn, - int[] startAndEndTimes){ - if (startAndEndTimes == null){ - contentValues.put(startColumn, 0); - contentValues.put(endColumn, 0); - } else { - int startTime = startAndEndTimes[0]*60+startAndEndTimes[1]; - int endTime = startAndEndTimes[2]*60+startAndEndTimes[3]; - if (endTime - startTime <=0 || startTime > 1439 || startTime < 0 - || endTime > 1439 || endTime <= 0) { - contentValues.put(startColumn, 0); - contentValues.put(endColumn, 0); - } else { - contentValues.put(startColumn, startTime); - contentValues.put(endColumn, endTime); - } - } - - } - //note that this method overwrites serviceProvider's availability if it exists public int[][] getAvailabilities(ServiceProvider serviceProvider){ @@ -860,6 +884,53 @@ public class DBHelper extends SQLiteOpenHelper { } + public List getAvailabilityByDate(ServiceProvider serviceProvider, int year, int month, int day){ + return getAvailabilityByDate(serviceProvider.getUsername(), year, month, day); + } + + public List getAvailabilityByDate(String serviceProvider, int year, int month, int day){ + + List availabilities = new ArrayList<>(); + + Cursor bookings = writeDB.query(TABLE_BOOKINGS, new String[] {COLUMN_BOOKINGSTART, COLUMN_BOOKINGEND}, + COLUMN_BOOKINGSERVICEPROVIDER+ " = ?" + + " AND " + COLUMN_BOOKINGYEAR + " = ?" + + " AND " + COLUMN_BOOKINGMONTH + " = ?" + + " AND " + COLUMN_BOOKINGDATE + " = ?", + new String[]{serviceProvider, String.valueOf(year), + String.valueOf(month),String.valueOf(day)}, + null, null, COLUMN_BOOKINGSTART, null); + + Cursor availability = getAvailabilityByDayOfWeek(serviceProvider, year, month, day); + if (availability.moveToFirst()) { + int previousEnd = availability.getInt(0); + int currentStart; + int currentEnd; + if (bookings.moveToFirst()) { + for (int i = 0; i < bookings.getCount(); i++) { + currentStart = bookings.getInt(0); + if (currentStart - previousEnd >= 30){ + availabilities.add(new int[]{previousEnd/60, previousEnd%60, + currentStart/60, currentStart%60}); + } + previousEnd = bookings.getInt(1); + bookings.moveToNext(); + } + currentStart = availability.getInt(1); + if (currentStart - previousEnd >= 30){ + availabilities.add(new int[]{previousEnd/60, previousEnd%60, + currentStart/60, currentStart%60}); + } + } else { + currentStart = availability.getInt(0); + currentEnd = availability.getInt(1); + availabilities.add(new int[]{currentStart/60, currentStart%60, + currentEnd/60, currentEnd%60}); + } + } + return availabilities; + } + public boolean addBooking(Booking booking){ if (booking == null) return false; @@ -879,17 +950,44 @@ public class DBHelper extends SQLiteOpenHelper { starth, startmin, endh, endmin); } + /** + * + * @param serviceProvider + * @param homeOwner + * @param service + * @param year + * @param month + * @param day + * @param starth + * @param startmin + * @param endh + * @param endmin + * @return true if booking was successfully added + */ public boolean addBooking(String serviceProvider, String homeOwner, String service, int year, int month, int day, int starth, int startmin, int endh, int endmin){ GregorianCalendar current = new GregorianCalendar(); current.setTimeInMillis(System.currentTimeMillis()); - GregorianCalendar bookDate = new GregorianCalendar(year, month, day, starth, startmin); + GregorianCalendar bookDate = new GregorianCalendar(year, month-1, day, starth, startmin); //check if time of booking is after this time if (current.compareTo(bookDate) > 0) return false; + service = service.trim().toLowerCase(); + + Cursor cursor = writeDB.query(TABLE_SERVICEPROVIDERS, new String[]{COLUMN_SERVICEPROVIDERNAME}, + COLUMN_SERVICEPROVIDERNAME + " = ? AND " + + COLUMN_SERVICEPROVIDERSERVICE + " = ?", + new String[] {serviceProvider, service}, + null, null, null, "1"); + if (!cursor.moveToFirst()) { + cursor.close(); + return false; + } + cursor.close(); + if (isProviderAvailable(serviceProvider, year, month, day, starth, startmin, endh, endmin)){ @@ -912,6 +1010,11 @@ public class DBHelper extends SQLiteOpenHelper { return false; } + /** + * + * @param username + * @return list of booking objects related to specified user + */ public List findBookings(String username){ List bookingList = new ArrayList<>(); ServiceProvider serviceProvider = null; @@ -924,13 +1027,13 @@ public class DBHelper extends SQLiteOpenHelper { if (cursor.getString(5).equals("ServiceProvider")) { serviceProvider = (ServiceProvider)findUserByUsername(username); cursor = writeDB.rawQuery("SELECT * FROM " + TABLE_BOOKINGS + " WHERE " - + COLUMN_BOOKINGSERVICEPROVIDER + " = ? AND " - + COLUMN_BOOKINGSTATUS + " != ?", new String[]{username, Status.CANCELLED.toString()}); + + COLUMN_BOOKINGSERVICEPROVIDER + " = ?", + new String[]{username}); } else { homeOwner = (HomeOwner)findUserByUsername(username); cursor = writeDB.rawQuery("SELECT * FROM " + TABLE_BOOKINGS + " WHERE " - + COLUMN_BOOKINGHOMEOWNER + " = ? AND " - + COLUMN_BOOKINGSTATUS + " != ?", new String[]{username, Status.CANCELLED.toString()}); + + COLUMN_BOOKINGHOMEOWNER + " = ?", + new String[]{username}); } if (cursor.moveToFirst()){ @@ -945,7 +1048,8 @@ public class DBHelper extends SQLiteOpenHelper { int month = cursor.getInt(4); int year = cursor.getInt(3); String stat = cursor.getString(8); - Status status = (stat.equals("Pending")? Status.PENDING : Status.CONFIRMED); + Status status = (stat.equals("Pending")? Status.PENDING : + stat.equals("Confirmed")? Status.CONFIRMED : Status.CANCELLED); ServiceProvider serviceprovider = (serviceProvider == null? (ServiceProvider)findUserByUsername(cursor.getString(0)):serviceProvider); HomeOwner homeowner = (homeOwner == null? @@ -963,185 +1067,44 @@ public class DBHelper extends SQLiteOpenHelper { } - public boolean isProviderAvailable(String serviceProvider, String monthDayYear, - int starth, int startmin, int endh, int endmin) { - String[] date = monthDayYear.split("/"); - return isProviderAvailable(serviceProvider, Integer.parseInt(date[2]), - Integer.parseInt(date[0]), Integer.parseInt(date[1]), - starth, startmin, endh, endmin); + /** + * Sets status of specified booking to cancelled. Returns false if booking + * does not exist in database, or date of booking has already passed. + * + * @param booking + * @return true if booking was successfully cancelled + */ + public boolean confirmBooking(Booking booking){ + return modifyBookingStatus(booking, Status.CONFIRMED); } /** - * Returns false if end time before start time, or service provider not available on that day + * Sets status of specified booking to cancelled. Returns false if booking was already cancelled, + * booking does not exist in database, or date of booking has already passed. * - * @param serviceProvider - * @param year - * @param month - * @param day - * @param starth - * @param startmin - * @param endh - * @param endmin - * @return + * @param booking + * @return true if booking was successfully cancelled */ - public boolean isProviderAvailable(String serviceProvider, int year, int month, int day, - int starth, int startmin, int endh, int endmin){ - - int bookingStart = starth*60 + startmin; - int bookingEnd = endh*60 + endmin; - - if (bookingEnd < bookingStart) return false; - - GregorianCalendar start = new GregorianCalendar(year, month-1, day); - //Calendar.DAY_OF_WEEK starts with 1 for Sunday, and onwards - int dayOfWeek = start.get(Calendar.DAY_OF_WEEK); - Cursor cursor = null; - int availabilityStart, availabilityEnd; - - //Check availabilities on day of week - switch (dayOfWeek){ - case 1: //Sunday - cursor = writeDB.query(TABLE_AVAILABILITY, new String[] {COLUMN_SUNSTART, COLUMN_SUNEND}, - COLUMN_AVAILABILITYNAME + " = ?", new String[] {serviceProvider}, null, - null, null, null); - break; - case 2: //Monday - cursor = writeDB.query(TABLE_AVAILABILITY, new String[] {COLUMN_MONSTART, COLUMN_MONEND}, - COLUMN_AVAILABILITYNAME + " = ?", new String[] {serviceProvider}, null, - null, null, null); - break; - case 3: //Tuesday - cursor = writeDB.query(TABLE_AVAILABILITY, new String[] {COLUMN_TUESTART, COLUMN_TUEEND}, - COLUMN_AVAILABILITYNAME + " = ?", new String[] {serviceProvider}, null, - null, null, null); - break; - case 4: //Wednesday - cursor = writeDB.query(TABLE_AVAILABILITY, new String[] {COLUMN_WEDSTART, COLUMN_WEDEND}, - COLUMN_AVAILABILITYNAME + " = ?", new String[] {serviceProvider}, null, - null, null, null); - break; - case 5: //Thursday - cursor = writeDB.query(TABLE_AVAILABILITY, new String[] {COLUMN_THUSTART, COLUMN_THUEND}, - COLUMN_AVAILABILITYNAME + " = ?", new String[] {serviceProvider}, null, - null, null, null); - break; - case 6: //Friday - cursor = writeDB.query(TABLE_AVAILABILITY, new String[] {COLUMN_FRISTART, COLUMN_FRIEND}, - COLUMN_AVAILABILITYNAME + " = ?", new String[] {serviceProvider}, null, - null, null, null); - break; - case 7: //Saturday - cursor = writeDB.query(TABLE_AVAILABILITY, new String[] {COLUMN_SATSTART, COLUMN_SATEND}, - COLUMN_AVAILABILITYNAME + " = ?", new String[] {serviceProvider}, null, - null, null, null); - break; - } - - cursor.moveToFirst(); - availabilityStart = cursor.getInt(0); - availabilityEnd = cursor.getInt(1); - - //service provider not available if availability end is 0, if availability starts after booking start, - // or if availability ends before booking end - if (availabilityEnd == 0 || availabilityStart > bookingStart || availabilityEnd < bookingEnd) { - return false; - } - - - //now we know for sure that the service provider is available on said day of the week - //we check to see if any of the bookings overlap on this time slot - cursor = writeDB.query(TABLE_BOOKINGS, new String[] {COLUMN_BOOKINGSTART, COLUMN_BOOKINGEND}, - COLUMN_BOOKINGSERVICEPROVIDER + " = ? AND " - + COLUMN_BOOKINGYEAR + " = ? AND " - + COLUMN_BOOKINGMONTH + " = ? AND " - + COLUMN_BOOKINGDATE + " = ? AND " - + COLUMN_BOOKINGSTATUS + " != ?", - new String[] {serviceProvider, String.valueOf(year), - String.valueOf(month), String.valueOf(day), Status.CANCELLED.toString()}, - null, null, COLUMN_BOOKINGSTART, null); - if (cursor.moveToFirst()){ - for (int i = 0; i bookingStart)|| - (availabilityStart < bookingEnd && availabilityEnd > bookingEnd) || - (availabilityStart > bookingStart && availabilityEnd < bookingEnd)) return false; - - cursor.moveToNext(); - } - } - return true; - } - - - - public boolean confirmBooking(Booking booking){ - if (booking == null) return false; - - ContentValues contentValues = new ContentValues(); - contentValues.put(COLUMN_BOOKINGSTATUS, Status.CONFIRMED.toString()); - - GregorianCalendar current = new GregorianCalendar(); - current.setTimeInMillis(System.currentTimeMillis()); - GregorianCalendar bookDate = new GregorianCalendar(booking.getYear(), booking.getMonth(), - booking.getDay(), booking.getStarth(), booking.getStartmin()); - - //check if time of booking is before this time - if (current.compareTo(bookDate) > 0) return false; - - return writeDB.update(TABLE_BOOKINGS, contentValues, - COLUMN_BOOKINGSERVICEPROVIDER + " = ? AND " - + COLUMN_BOOKINGHOMEOWNER + " = ? AND " - + COLUMN_BOOKINGYEAR + " = ? AND " - + COLUMN_BOOKINGMONTH + " = ? AND " - + COLUMN_BOOKINGDATE + " = ? AND " - + COLUMN_BOOKINGSTART + " = ? AND " - + COLUMN_BOOKINGSTATUS + " = ?)", - new String[] {booking.getServiceprovider().getUsername(), - booking.getHomeowner().getUsername(), - String.valueOf(booking.getYear()), - String.valueOf(booking.getMonth()), - String.valueOf(booking.getDay()), - String.valueOf(booking.getStarth()*60 + booking.getStartmin()), - Status.PENDING.toString()}) > 0; - } - public boolean cancelBooking(Booking booking){ - if (booking == null) return false; - - ContentValues contentValues = new ContentValues(); - contentValues.put(COLUMN_BOOKINGSTATUS, Status.CANCELLED.toString()); - - GregorianCalendar current = new GregorianCalendar(); - current.setTimeInMillis(System.currentTimeMillis()); - GregorianCalendar bookDate = new GregorianCalendar(booking.getYear(), booking.getMonth(), - booking.getDay(), booking.getStarth(), booking.getStartmin()); - - //check if time of booking has passed - if (current.compareTo(bookDate) > 0) return false; - - return writeDB.update(TABLE_BOOKINGS, contentValues, - COLUMN_BOOKINGSERVICEPROVIDER + " = ? AND " - + COLUMN_BOOKINGHOMEOWNER + " = ? AND " - + COLUMN_BOOKINGYEAR + " = ? AND " - + COLUMN_BOOKINGMONTH + " = ? AND " - + COLUMN_BOOKINGDATE + " = ? AND " - + COLUMN_BOOKINGSTART + " = ?)", - new String[] {booking.getServiceprovider().getUsername(), - booking.getHomeowner().getUsername(), - String.valueOf(booking.getYear()), - String.valueOf(booking.getMonth()), - String.valueOf(booking.getDay()), - String.valueOf(booking.getStarth()*60 + booking.getStartmin())}) > 0; + return modifyBookingStatus(booking, Status.CANCELLED); } + + /** + * Add a rating for a specific booking, and updates the average rating for the service provider + * and service combination. The booking must have passed before a rating can be added. + * Note that the rating is final. + * + * @param booking + * @param rating + * @return true if adding the rating was successful + */ public boolean addRating(Booking booking, double rating){ if (booking == null) return false; GregorianCalendar current = new GregorianCalendar(); current.setTimeInMillis(System.currentTimeMillis()); - GregorianCalendar bookDate = new GregorianCalendar(booking.getYear(), booking.getMonth(), + GregorianCalendar bookDate = new GregorianCalendar(booking.getYear(), booking.getMonth()-1, booking.getDay(), booking.getEndh(), booking.getEndmin()); //check if time of booking is before this time @@ -1191,11 +1154,26 @@ public class DBHelper extends SQLiteOpenHelper { } + /** + * Returns the average rating for a service provider's service + * + * @param serviceProvider + * @param service + * @return average rating of specified service provider and service combination + */ public double getRatings(ServiceProvider serviceProvider, Service service){ return getRatings(serviceProvider.getUsername(), service.getName()); } + /** + * Returns the average rating for a service provider's service + * + * @param serviceProviderName name of service provider + * @param serviceName name of service + * @return average rating of specified service provider and service combination + */ public double getRatings(String serviceProviderName, String serviceName){ + serviceName = serviceName.trim().toLowerCase(); Cursor cursor = writeDB.query(TABLE_SERVICEPROVIDERS, new String[]{COLUMN_AVERAGERATING}, COLUMN_SERVICEPROVIDERNAME + " = ? AND " + COLUMN_SERVICEPROVIDERSERVICE + " = ?", @@ -1208,12 +1186,27 @@ public class DBHelper extends SQLiteOpenHelper { return rating; } + /** + * Returns the number of people who rated a service provider's service + * + * @param serviceProvider name of service provider + * @param service name of service + * @return number of raters for specified service provider and service combination + */ public int getRaters(ServiceProvider serviceProvider, Service service){ return getRaters(serviceProvider.getUsername(), service.getName()); } + /** + * Returns the number of people who rated a service provider's service + * + * @param serviceProviderName name of service provider + * @param serviceName name of service + * @return number of raters for specified service provider and service combination + */ public int getRaters(String serviceProviderName, String serviceName){ + serviceName = serviceName.trim().toLowerCase(); Cursor cursor = writeDB.query(TABLE_SERVICEPROVIDERS, new String[]{COLUMN_RATERS}, COLUMN_SERVICEPROVIDERNAME + " = ? AND " + COLUMN_SERVICEPROVIDERSERVICE + " = ?", @@ -1225,54 +1218,150 @@ public class DBHelper extends SQLiteOpenHelper { return cursor.getInt(0); } - public List getProvidersAboveRating(Service service, double rating){ + /** + * Returns list of [username, first name, last name, rating] of service providers that + * have a rating equal to or above the specified rating + * + * @param service + * @param rating minimum rating + * @return a List of [username, first name, last name, rating] of service providers + */ + public List getProvidersAboveRating(Service service, double rating){ return getProvidersAboveRating(service.getName(), rating); } - public List getProvidersAboveRating(String serviceName, double rating){ - List providers = getAll("SELECT " + COLUMN_SERVICEPROVIDERNAME + " FROM " + TABLE_SERVICEPROVIDERS - + " WHERE " + COLUMN_SERVICE + " = " + serviceName + " AND " - + COLUMN_AVERAGERATING + " >= " + rating); - List providerList = new ArrayList<>(); - for (String[] provider : providers){ - providerList.add(provider[0]); - } - return providerList; + /** + * Returns list of [username, first name, last name, rating] of service providers that + * have a rating equal to or above the specified rating + * + * @param serviceName name of service + * @param rating minimum rating + * @return a List of [username, first name, last name, rating] of service providers + */ + public List getProvidersAboveRating(String serviceName, double rating){ + serviceName = serviceName.trim().toLowerCase(); + return getAll("SELECT " + TABLE_SERVICEPROVIDERS + "." + COLUMN_SERVICEPROVIDERNAME + ", " + + TABLE_LOGIN + "." + COLUMN_FIRSTNAME + ", " + + TABLE_LOGIN + "." + COLUMN_LASTNAME + ", " + + TABLE_SERVICEPROVIDERS + "." + COLUMN_AVERAGERATING + + " FROM " + TABLE_SERVICEPROVIDERS + " JOIN " + TABLE_LOGIN + + " ON " + TABLE_SERVICEPROVIDERS + "." + COLUMN_SERVICEPROVIDERNAME + " = " + + TABLE_LOGIN + "." + COLUMN_USERNAME + + " AND " + COLUMN_SERVICEPROVIDERSERVICE + " = '" + serviceName + "'" + + " AND " + TABLE_SERVICEPROVIDERS + "." + COLUMN_ACTIVE + " = 'active'" + + " AND " + TABLE_SERVICEPROVIDERS + "." + COLUMN_AVERAGERATING + " >= " + rating + + " ORDER BY " + TABLE_SERVICEPROVIDERS + "." + COLUMN_AVERAGERATING + " DESC"); } - public List getProvidersByTime(Service service, int year, int month, int day, + /** + * Returns list of [username, first name, last name, rating] of service providers + * available at the specified time + * + * @param service + * @param year + * @param month + * @param day + * @param starth starting hour + * @param startmin starting minute + * @param endh ending hour + * @param endmin ending minute + * @return a List of [username, first name, last name, rating] of service providers + */ + public List getProvidersByTime(Service service, int year, int month, int day, int starth, int startmin, int endh, int endmin){ return getProvidersByTime(service.getName(), year, month, day, starth, startmin, endh, endmin); } - public List getProvidersByTime(String serviceName, int year, int month, int day, + /** + * Returns list of [username, first name, last name, rating] of service providers + * available at the specified time + * + * @param serviceName name of service + * @param year + * @param month + * @param day + * @param starth starting hour + * @param startmin starting minute + * @param endh ending hour + * @param endmin ending minute + * @return a List of [username, first name, last name, rating] of service providers + */ + public List getProvidersByTime(String serviceName, int year, int month, int day, int starth, int startmin, int endh, int endmin){ - List providers = getAllProvidersByService(serviceName); - + serviceName = serviceName.trim().toLowerCase(); + List providers = getAll("SELECT " + TABLE_SERVICEPROVIDERS + "." + COLUMN_SERVICEPROVIDERNAME + ", " + + TABLE_LOGIN + "." + COLUMN_FIRSTNAME + ", " + + TABLE_LOGIN + "." + COLUMN_LASTNAME + ", " + + TABLE_SERVICEPROVIDERS + "." + COLUMN_AVERAGERATING + ", " + + " FROM " + TABLE_SERVICEPROVIDERS + " JOIN " + TABLE_LOGIN + + " ON " + TABLE_SERVICEPROVIDERS + "." + COLUMN_SERVICEPROVIDERNAME + " = " + + TABLE_LOGIN + "." + COLUMN_USERNAME + + " AND " + COLUMN_SERVICEPROVIDERSERVICE + " = '" + serviceName + "'" + + " AND " + TABLE_SERVICEPROVIDERS + "." + COLUMN_ACTIVE + " = 'active'" + + " ORDER BY " + TABLE_SERVICEPROVIDERS + "." + COLUMN_AVERAGERATING + " DESC"); for (int i = 0; i < providers.size(); i++){ - String username = providers.get(i); - if (!isProviderAvailable(username, year, month, day, starth, startmin, endh, endmin)){ + if (!isProviderAvailable(providers.get(i)[0], year, month, day, + starth, startmin, endh, endmin)){ providers.remove(i); } } return providers; } - public List getProvidersByTimeAndRating(String serviceName, double rating, int year, int month, int day, + /** + * Returns list of [username, first name, last name, rating] of service providers + * available at the specified time and have a rating equal to or above the specified rating + * + * @param service + * @param rating minimum rating of filter + * @param year + * @param month + * @param day + * @param starth starting hour + * @param startmin starting minute + * @param endh ending hour + * @param endmin ending minute + * @return List of [username, first name, last name, rating] of service providers + */ + public List getProvidersByTimeAndRating(Service service, double rating, int year, int month, int day, + int starth, int startmin, int endh, int endmin){ + return getProvidersByTimeAndRating(service.getName(), rating, year, month, day, + starth, startmin, endh, endmin); + } + + /** + * Returns list of [username, first name, last name, rating] of service providers + * available at the specified time and have a rating equal to or above the specified rating + * + * @param serviceName name of service + * @param rating minimum rating of filter + * @param year + * @param month + * @param day + * @param starth starting hour + * @param startmin starting minute + * @param endh ending hour + * @param endmin ending minute + * @return List of [username, first name, last name, rating] of service providers + */ + public List getProvidersByTimeAndRating(String serviceName, double rating, int year, int month, int day, int starth, int startmin, int endh, int endmin){ - List providers = getProvidersByTime(serviceName, year, month, day, starth, startmin, endh, endmin); - for (int i = 0; i < providers.size(); i++){ - String provider = providers.get(i); - if (getRatings(provider, serviceName) providers = getProvidersByTime(serviceName, year, month, day, starth, startmin, endh, endmin); + + int i = providers.size()-1; + boolean allLowRatingsRemoved = false; + while (i>-1 && !allLowRatingsRemoved){ + if (getRatings(providers.get(i)[0], serviceName)>=rating){ + allLowRatingsRemoved = true; + } else { + providers.remove(i--); } } return providers; } - - /** * Prints all entries of table. One row is printed per line. Columns are * separated by spaces. @@ -1293,6 +1382,17 @@ public class DBHelper extends SQLiteOpenHelper { cursor.close(); } + /** + * Deletes all data from database. It's used for testing when + * DB needs to be cleared. Please don't call this anywhere else. + */ + void deleteAll(){ + writeDB.execSQL("DELETE FROM " + TABLE_LOGIN); + writeDB.execSQL("DELETE FROM " + TABLE_SERVICES); + writeDB.execSQL("DELETE FROM " + TABLE_SERVICEPROVIDERS); + writeDB.execSQL("DELETE FROM " + TABLE_AVAILABILITY); + writeDB.execSQL("DELETE FROM " + TABLE_BOOKINGS); + } /** * Gets all items in a table @@ -1319,15 +1419,187 @@ public class DBHelper extends SQLiteOpenHelper { } /** - * Deletes all data from database. It's used for testing when - * DB needs to be cleared. Please don't call this anywhere else. + * Adds a service provider's availabilities for a specific day to content values + * @param contentValues + * @param startColumn + * @param endColumn + * @param startAndEndTimes */ - void deleteAll(){ - writeDB.execSQL("DELETE FROM " + TABLE_LOGIN); - writeDB.execSQL("DELETE FROM " + TABLE_SERVICES); - writeDB.execSQL("DELETE FROM " + TABLE_SERVICEPROVIDERS); - writeDB.execSQL("DELETE FROM " + TABLE_AVAILABILITY); - writeDB.execSQL("DELETE FROM " + TABLE_BOOKINGS); + private void addAvailabilityToContentValues(ContentValues contentValues, + String startColumn, String endColumn, + int[] startAndEndTimes){ + if (startAndEndTimes == null){ + contentValues.put(startColumn, 0); + contentValues.put(endColumn, 0); + } else { + int startTime = startAndEndTimes[0]*60+startAndEndTimes[1]; + int endTime = startAndEndTimes[2]*60+startAndEndTimes[3]; + if (endTime - startTime <=0 || startTime > 1439 || startTime < 0 + || endTime > 1439 || endTime <= 0) { + contentValues.put(startColumn, 0); + contentValues.put(endColumn, 0); + } else { + contentValues.put(startColumn, startTime); + contentValues.put(endColumn, endTime); + } + } + + } + + /** + * Helper method to get a service provider's availability by day of week + * + * @param serviceProvider username of service provider + * @param year + * @param month + * @param day + * @return Cursor containing the start and end of the service provider's availabilities + * on selected day of the week + */ + private Cursor getAvailabilityByDayOfWeek(String serviceProvider, int year, int month, int day){ + GregorianCalendar start = new GregorianCalendar(year, month-1, day); + //Calendar.DAY_OF_WEEK starts with 1 for Sunday, and onwards + int dayOfWeek = start.get(Calendar.DAY_OF_WEEK); + Cursor cursor = null; + + //Check availabilities on day of week + switch (dayOfWeek){ + case 1: //Sunday + cursor = writeDB.query(TABLE_AVAILABILITY, new String[] {COLUMN_SUNSTART, COLUMN_SUNEND}, + COLUMN_AVAILABILITYNAME + " = ?", new String[] {serviceProvider}, null, + null, null, null); + break; + case 2: //Monday + cursor = writeDB.query(TABLE_AVAILABILITY, new String[] {COLUMN_MONSTART, COLUMN_MONEND}, + COLUMN_AVAILABILITYNAME + " = ?", new String[] {serviceProvider}, null, + null, null, null); + break; + case 3: //Tuesday + cursor = writeDB.query(TABLE_AVAILABILITY, new String[] {COLUMN_TUESTART, COLUMN_TUEEND}, + COLUMN_AVAILABILITYNAME + " = ?", new String[] {serviceProvider}, null, + null, null, null); + break; + case 4: //Wednesday + cursor = writeDB.query(TABLE_AVAILABILITY, new String[] {COLUMN_WEDSTART, COLUMN_WEDEND}, + COLUMN_AVAILABILITYNAME + " = ?", new String[] {serviceProvider}, null, + null, null, null); + break; + case 5: //Thursday + cursor = writeDB.query(TABLE_AVAILABILITY, new String[] {COLUMN_THUSTART, COLUMN_THUEND}, + COLUMN_AVAILABILITYNAME + " = ?", new String[] {serviceProvider}, null, + null, null, null); + break; + case 6: //Friday + cursor = writeDB.query(TABLE_AVAILABILITY, new String[] {COLUMN_FRISTART, COLUMN_FRIEND}, + COLUMN_AVAILABILITYNAME + " = ?", new String[] {serviceProvider}, null, + null, null, null); + break; + case 7: //Saturday + cursor = writeDB.query(TABLE_AVAILABILITY, new String[] {COLUMN_SATSTART, COLUMN_SATEND}, + COLUMN_AVAILABILITYNAME + " = ?", new String[] {serviceProvider}, null, + null, null, null); + break; + } + + return cursor; + } + + /** + * Helper method to change booking status + * @param booking + * @param status status to update + * @return true if modification was successful + */ + private boolean modifyBookingStatus(Booking booking, Status status){ + if (booking == null) return false; + + GregorianCalendar current = new GregorianCalendar(); + current.setTimeInMillis(System.currentTimeMillis()); + GregorianCalendar bookDate = new GregorianCalendar(booking.getYear(), booking.getMonth()-1, + booking.getDay(), booking.getStarth(), booking.getStartmin()); + + //check if time of booking has passed + if (current.compareTo(bookDate) > 0) return false; + + ContentValues contentValues = new ContentValues(); + contentValues.put(COLUMN_BOOKINGSTATUS, status.toString()); + + return writeDB.update(TABLE_BOOKINGS, contentValues, + COLUMN_BOOKINGSERVICEPROVIDER + " = ? AND " + + COLUMN_BOOKINGHOMEOWNER + " = ? AND " + + COLUMN_BOOKINGYEAR + " = ? AND " + + COLUMN_BOOKINGMONTH + " = ? AND " + + COLUMN_BOOKINGDATE + " = ? AND " + + COLUMN_BOOKINGSTART + " = ? AND " + + COLUMN_BOOKINGSTATUS + " != " + Status.CANCELLED.toString() + ")", + new String[] {booking.getServiceprovider().getUsername(), + booking.getHomeowner().getUsername(), + String.valueOf(booking.getYear()), + String.valueOf(booking.getMonth()), + String.valueOf(booking.getDay()), + String.valueOf(booking.getStarth()*60 + booking.getStartmin())}) > 0; + } + + /** + * Helper method to determine whether service provider is available at specified date and time. + * Returns false if end time before start time, or service provider not available + * + * @param serviceProvider + * @param year + * @param month + * @param day + * @param starth + * @param startmin + * @param endh + * @param endmin + * @return true if service provider is available for specified time slot + */ + private boolean isProviderAvailable(String serviceProvider, int year, int month, int day, + int starth, int startmin, int endh, int endmin){ + + int bookingStart = starth*60 + startmin; + int bookingEnd = endh*60 + endmin; + int availabilityStart, availabilityEnd; + + if (bookingEnd < bookingStart) return false; + + Cursor cursor = getAvailabilityByDayOfWeek(serviceProvider, year, month, day); + + cursor.moveToFirst(); + availabilityStart = cursor.getInt(0); + availabilityEnd = cursor.getInt(1); + + //service provider not available if availability end is 0, if availability starts after booking start, + // or if availability ends before booking end + if (availabilityEnd == 0 || availabilityStart > bookingStart || availabilityEnd < bookingEnd) { + return false; + } + + + //now we know for sure that the service provider is available on said day of the week + //we check to see if any of the bookings overlap on this time slot + cursor = writeDB.query(TABLE_BOOKINGS, new String[] {COLUMN_BOOKINGSTART, COLUMN_BOOKINGEND}, + COLUMN_BOOKINGSERVICEPROVIDER + " = ? AND " + + COLUMN_BOOKINGYEAR + " = ? AND " + + COLUMN_BOOKINGMONTH + " = ? AND " + + COLUMN_BOOKINGDATE + " = ? AND " + + COLUMN_BOOKINGSTATUS + " != ?", + new String[] {serviceProvider, String.valueOf(year), + String.valueOf(month), String.valueOf(day), Status.CANCELLED.toString()}, + null, null, COLUMN_BOOKINGSTART, null); + if (cursor.moveToFirst()){ + for (int i = 0; i bookingStart)|| + (availabilityStart < bookingEnd && availabilityEnd > bookingEnd) || + (availabilityStart > bookingStart && availabilityEnd < bookingEnd)) return false; + + cursor.moveToNext(); + } + } + return true; } } diff --git a/OlympusServices/app/src/test/java/com/uottawa/olympus/olympusservices/DBIntegrationTest.java b/OlympusServices/app/src/test/java/com/uottawa/olympus/olympusservices/DBIntegrationTest.java index aca0a49..0e27671 100644 --- a/OlympusServices/app/src/test/java/com/uottawa/olympus/olympusservices/DBIntegrationTest.java +++ b/OlympusServices/app/src/test/java/com/uottawa/olympus/olympusservices/DBIntegrationTest.java @@ -18,6 +18,15 @@ import static org.junit.Assert.*; @RunWith(RobolectricTestRunner.class) @Config(packageName = "com.uottawa.olympus.olympusservices") public class DBIntegrationTest { + + /** + * Enum for setting up before a test + */ + private enum TestAfter{ + USER, SERVICE, LINK, AVAILABILITY, BOOKING, RATING; + } + + private DBHelper dbHelper = new DBHelper(RuntimeEnvironment.application); //testing user login table @@ -121,7 +130,7 @@ public class DBIntegrationTest { dbHelper.deleteUser("jbO4aBF4dC"); - List providersList = dbHelper.getAllProvidersByService("hitman"); + List providersList = dbHelper.getAllProvidersByService("hitman"); assertEquals(0, providersList.size()); providersList = dbHelper.getAllProvidersByService("hitman"); assertEquals(0, providersList.size()); @@ -174,9 +183,10 @@ public class DBIntegrationTest { @Test public void testGetAllUsers(){ - dbHelper.addUser(new HomeOwner("jbO4aBF4dC", "soccer", "Miguel", "Garzon")); + setUp(TestAfter.USER); List allUsers = dbHelper.getAllUsers(); + assertEquals(allUsers.size(), 5); for (String[] user : allUsers){ /* for (String s : user){ @@ -260,15 +270,12 @@ public class DBIntegrationTest { @Test public void testGetAllServices(){ - dbHelper.addService(new Service("Exterminating flatworms", 20.00)); + setUp(TestAfter.SERVICE); List allServices = dbHelper.getAllServices(); + assertTrue(allServices.size() == 3); for (String[] service : allServices){ -/* for (String s : user){ - System.out.print(s + " "); - } - System.out.println();*/ Service dbService = dbHelper.findService(service[0]); assertEquals(dbService.getRate(), Double.parseDouble(service[1]), 0.001); } @@ -278,9 +285,8 @@ public class DBIntegrationTest { @Test public void testAddAndDeleteServiceProvidedByUser(){ - dbHelper.addUser(new ServiceProvider("jbO4aBF4dC", null, null, null, - "testaddress", "8888888888", "companydotcom", true)); - dbHelper.addService(new Service("Hitman", 12358)); + setUp(TestAfter.SERVICE); + boolean added = dbHelper.addServiceProvidedByUser("jbO4aBF4dC", "hitman"); assertTrue(added); boolean deleted = dbHelper.deleteServiceProvidedByUser("jbO4aBF4dC", "Hitman"); @@ -291,19 +297,9 @@ public class DBIntegrationTest { @Test public void testGetAllServicesProvidedByUserAndDeleteService(){ - ServiceProvider serviceProvider = new ServiceProvider("jbO4aBF4dC", null, null, null, - "testaddress", "8888888888", "companydotcom", true); - dbHelper.addUser(serviceProvider); + setUp(TestAfter.LINK); - Service service1 = new Service("Hitman", 12358); - Service service2 = new Service("Exterminating flatworms", 392.457); - dbHelper.addService(service1); - dbHelper.addService(service2); - - dbHelper.addServiceProvidedByUser(serviceProvider, service1); - dbHelper.addServiceProvidedByUser(serviceProvider, service2); - - List servicesProvidedByUser = dbHelper.getAllServicesProvidedByUser(serviceProvider); + List servicesProvidedByUser = dbHelper.getAllServicesProvidedByUser("jbO4aBF4dC"); assertEquals(2, servicesProvidedByUser.size()); assertEquals("hitman", servicesProvidedByUser.get(0)[0]); assertEquals(12358, Double.parseDouble(servicesProvidedByUser.get(0)[1]), 0.00001); @@ -323,20 +319,13 @@ public class DBIntegrationTest { @Test public void testGetAllProvidersByService(){ - dbHelper.addService(new Service("Exterminating flatworms", 392.457)); - dbHelper.addUser(new ServiceProvider("jbO4aBF4dC", null, null, null, - "testaddress", "8888888888", "companydotcom", true)); - dbHelper.addUser(new ServiceProvider("7MuF1c59XP", null, null, null, - "testaddress", "8888888888", "companydotcom", true)); + setUp(TestAfter.LINK); - dbHelper.addServiceProvidedByUser("jbO4aBF4dC", "exterminating flatworms"); - dbHelper.addServiceProvidedByUser("7MuF1c59XP", "exterminating flatworms"); - - List providersByService = dbHelper.getAllProvidersByService("exterminating flatworms"); + List providersByService = dbHelper.getAllProvidersByService("exterminating flatworms"); assertEquals(2, providersByService.size()); - assertEquals("jbO4aBF4dC", providersByService.get(0)); - assertEquals("7MuF1c59XP", providersByService.get(1)); + assertEquals("jbO4aBF4dC", providersByService.get(0)[0]); + assertEquals("DW44FkUsX7", providersByService.get(1)[0]); dbHelper.deleteAll(); } @@ -344,19 +333,9 @@ public class DBIntegrationTest { @Test public void testDeleteServiceProvidedByUser(){ - ServiceProvider serviceProvider = new ServiceProvider("jbO4aBF4dC", null, null, null, - "testaddress", "8888888888", "companydotcom", true); - dbHelper.addUser(serviceProvider); + setUp(TestAfter.LINK); - Service service1 = new Service("Hitman", 12358); - Service service2 = new Service("Exterminating flatworms", 392.457); - dbHelper.addService(service1); - dbHelper.addService(service2); - - dbHelper.addServiceProvidedByUser(serviceProvider, service1); - dbHelper.addServiceProvidedByUser(serviceProvider, service2); - - List servicesProvidedByUser = dbHelper.getAllServicesProvidedByUser(serviceProvider); + List servicesProvidedByUser = dbHelper.getAllServicesProvidedByUser("jbO4aBF4dC"); assertEquals(2, servicesProvidedByUser.size()); dbHelper.deleteServiceProvidedByUser("jbO4aBF4dC","hitman"); @@ -435,32 +414,90 @@ public class DBIntegrationTest { @Test public void testAddBooking(){ - ServiceProvider serviceProvider = new ServiceProvider("jbO4aBF4dC", null, null, null, - "testaddress", "8888888888", "companydotcom", true); - serviceProvider.setAvailabilities(0, 4, 18, 19, 30); - serviceProvider.setAvailabilities(1, 5, 20, 21, 11); - serviceProvider.setAvailabilities(3, 7, 12, 15, 14); - serviceProvider.setAvailabilities(4, 0, 0, 23, 29); - - dbHelper.addUser(serviceProvider); - dbHelper.updateAvailability(serviceProvider); - - dbHelper.addUser(new HomeOwner("7MuF1c59XP", null, null, null)); - - dbHelper.addService(new Service("Hitman", 12358)); - dbHelper.addServiceProvidedByUser("jbO4aBF4dC", "Hitman"); + setUp(TestAfter.BOOKING); + //December 1, 2020 is a Tuesday. Provider is available from 5:20 to 21:11 boolean added = dbHelper.addBooking("jbO4aBF4dC", "7MuF1c59XP", "Hitman", - 2018, 11, 20, 8, 12, 10, 0); + 2020, 12, 1, 8, 12, 10, 0); assertTrue(added); + //Provider is available from 5:20 to 21:11, but has a booking from 8:12 to 10:00 added = dbHelper.addBooking("jbO4aBF4dC", "7MuF1c59XP", "Hitman", - 2018, 11, 20, 9, 12, 12, 0); + 2020, 12, 1, 9, 12, 12, 0); assertTrue(!added); + + //December 3, 2020 is was a Thursday. Provider is available from 7:12 to 15:14 added = dbHelper.addBooking("jbO4aBF4dC", "7MuF1c59XP", "Hitman", - 2018, 11, 22, 6, 12, 7, 30); + 2020, 12, 3, 6, 12, 7, 30); + assertTrue(!added); + + //November 20, 2018 is in the past. Should not be able to add booking + added = dbHelper.addBooking("jbO4aBF4dC", "7MuF1c59XP", "Hitman", + 2018, 11, 20, 8, 12, 10, 0); assertTrue(!added); dbHelper.deleteAll(); } + +// @Test +// public void testConfirmBooking(){ +// setUp(TestAfter.RATING); +// +// } + + // Ever gotten tired of adding things at the start of a test just to delete it all again? + // I have. + // This is a work in progress + private void setUp(TestAfter testAfter){ + dbHelper.deleteAll(); + + dbHelper.addUser(new Admin()); + + ServiceProvider serviceProvider1 = new ServiceProvider("jbO4aBF4dC", null, "Jack", "Black", + "testaddress", "8888888888", "companydotcom", true); + dbHelper.addUser(serviceProvider1); + + ServiceProvider serviceProvider2 = new ServiceProvider("DW44FkUsX7", null, "Dwayne", "Johnson", + "testaddress", "1248921742", "companydotcom", false); + dbHelper.addUser(serviceProvider2); + + HomeOwner homeOwner1 = new HomeOwner("7MuF1c59XP", null, "Mufasa", "Died"); + dbHelper.addUser(homeOwner1); + + HomeOwner homeOwner2 = new HomeOwner("wRV3phzpl5", null, "Wren", "Phillips"); + dbHelper.addUser(homeOwner2); + + Service service1 = new Service("Hitman", 12358); + dbHelper.addService(service1); + + Service service2 = new Service("Exterminating flatworms", 392.457); + dbHelper.addService(service2); + + Service service3 = new Service("Petting cats", 0); + dbHelper.addService(service3); + + if (!(testAfter.equals(TestAfter.USER) || testAfter.equals(TestAfter.SERVICE))){ + dbHelper.addServiceProvidedByUser(serviceProvider1, service1); + dbHelper.addServiceProvidedByUser(serviceProvider1, service2); + + dbHelper.addServiceProvidedByUser(serviceProvider2, service3); + dbHelper.addServiceProvidedByUser(serviceProvider2, service2); + + if (!testAfter.equals(TestAfter.LINK)){ + serviceProvider1.setAvailabilities(0, 4, 18, 19, 30); + serviceProvider1.setAvailabilities(1, 5, 20, 21, 11); + serviceProvider1.setAvailabilities(3, 7, 12, 15, 14); + serviceProvider1.setAvailabilities(4, 0, 0, 23, 29); + + dbHelper.updateAvailability(serviceProvider1); + + if (!testAfter.equals(TestAfter.AVAILABILITY)){ + Booking booking1 = new Booking(8, 12, 10, 0,1, + 12, 2020, serviceProvider1, homeOwner1, service1); + dbHelper.addBooking(booking1); + } + } + } + } + }