From 3cd7a6bff4fd13499c8ea62b2ac001c5a3c6e0ad Mon Sep 17 00:00:00 2001 From: Kaveesha529 Date: Sun, 13 Jul 2025 16:42:11 +0530 Subject: [PATCH 01/28] fix: today best renamed as platform revenue. fix the incorrect business logic --- .../Quicky_Backend/entity/DriverDetails.java | 11 ++- .../repository/DriverDetailsRepo.java | 91 ++++++++++--------- .../repository/DriverEarningsRepo.java | 4 +- .../service/NewRegistrationsService.java | 4 +- 4 files changed, 59 insertions(+), 51 deletions(-) diff --git a/src/main/java/com/pentagon/Quicky_Backend/entity/DriverDetails.java b/src/main/java/com/pentagon/Quicky_Backend/entity/DriverDetails.java index 4cd95a4..4b1e6f1 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/entity/DriverDetails.java +++ b/src/main/java/com/pentagon/Quicky_Backend/entity/DriverDetails.java @@ -66,8 +66,15 @@ public class DriverDetails { @Column(name = "wallet_balance", nullable = false) private Double walletBalance; - @Column(name = "approved", nullable = false, columnDefinition = "BOOLEAN DEFAULT FALSE") - private Boolean approved; + public enum ApprovalStatus { + PENDING, + APPROVED, + REJECTED + } + + @Enumerated(EnumType.STRING) + @Column(name = "approved", nullable = false, columnDefinition = "VARCHAR(20) DEFAULT 'PENDING'") + private ApprovalStatus approved; //Cardinality among tables @OneToOne diff --git a/src/main/java/com/pentagon/Quicky_Backend/repository/DriverDetailsRepo.java b/src/main/java/com/pentagon/Quicky_Backend/repository/DriverDetailsRepo.java index ca29f34..1a0bbe9 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/repository/DriverDetailsRepo.java +++ b/src/main/java/com/pentagon/Quicky_Backend/repository/DriverDetailsRepo.java @@ -40,7 +40,7 @@ public interface DriverDetailsRepo extends JpaRepository d.mobile_number AS mobileNumber FROM driver_details dd LEFT JOIN drivers d ON dd.user_id = d.user_id - WHERE dd.approved = false + WHERE dd.approved = 'PENDING' ORDER BY dd.user_details_id """, nativeQuery = true) List findAllPendingRegistrations(); @@ -69,7 +69,7 @@ public interface DriverDetailsRepo extends JpaRepository FROM driver_details dd JOIN drivers d ON d.user_id = dd.user_id LEFT JOIN rating r ON r.user_details_id = dd.user_details_id - WHERE dd.approved = true + WHERE dd.approved = 'APPROVED' GROUP BY dd.user_details_id, dd.first_name, dd.last_name, dd.date_of_birth, dd.gender, dd.home_no, dd.street_name, dd.city, dd.district, dd.license_number, dd.license_front_url, dd.license_back_url, dd.registration_date, dd.availability, @@ -102,7 +102,7 @@ public interface DriverDetailsRepo extends JpaRepository FROM driver_details dd JOIN drivers d ON d.user_id = dd.user_id LEFT JOIN rating r ON r.user_details_id = dd.user_details_id - WHERE dd.approve_status = 'ACCEPTED' + WHERE dd.approved = 'APPROVED' AND dd.registration_date = CURRENT_DATE GROUP BY dd.user_details_id, dd.first_name, dd.last_name, dd.date_of_birth, dd.gender, dd.home_no, dd.street_name, dd.city, dd.district, dd.license_number, @@ -114,53 +114,54 @@ public interface DriverDetailsRepo extends JpaRepository @Query(value = "SELECT registration_date, COUNT(*) AS driversCount " + "FROM driver_details " + - "WHERE approved = true " + + "WHERE approved = 'APPROVED' " + "GROUP BY registration_date " + "ORDER BY registration_date", nativeQuery = true) List countApprovedDriversByRegistrationDate(); @Query(value = """ - SELECT - dd.user_details_id AS userDetailsId, - dd.first_name AS firstName, - dd.last_name AS lastName, - dd.date_of_birth AS dateOfBirth, - dd.gender AS gender, - dd.home_no AS homeNo, - dd.street_name AS streetName, - dd.city AS city, - dd.district AS district, - dd.license_number AS licenseNumber, - dd.license_front_url AS licenseFrontURL, - dd.license_back_url AS licenseBackURL, - dd.registration_date AS registrationDate, - dd.availability AS availability, - dd.stripe_id AS stripeId, - dd.wallet_balance AS walletBalance, - d.email AS email, - d.mobile_number AS mobileNumber, - COALESCE(SUM(r.rating_count) / NULLIF(COUNT(r.rating_id), 0), 0) AS rating, - COALESCE(SUM(e.delivery_charge), 0) AS earnings - FROM - driver_details dd - JOIN - drivers d ON dd.user_id = d.user_id - LEFT JOIN - earning e ON dd.user_details_id = e.driver_id - LEFT JOIN - delivery_order o ON e.delivery_id = o.delivery_id AND DATE(o.time_stamp) = CURRENT_DATE - LEFT JOIN - rating r ON o.delivery_id = r.delivery_id - WHERE - dd.approve_status = 'ACCEPTED' - GROUP BY - dd.user_details_id, dd.first_name, dd.last_name, dd.date_of_birth, dd.gender, - dd.home_no, dd.street_name, dd.city, dd.district, dd.license_number, - dd.license_front_url, dd.license_back_url, dd.registration_date, dd.availability, - dd.stripe_id, dd.wallet_balance, d.email, d.mobile_number - ORDER BY - earnings DESC - """, nativeQuery = true) + SELECT + dd.user_details_id AS userDetailsId, + dd.first_name AS firstName, + dd.last_name AS lastName, + dd.date_of_birth AS dateOfBirth, + dd.gender AS gender, + dd.home_no AS homeNo, + dd.street_name AS streetName, + dd.city AS city, + dd.district AS district, + dd.license_number AS licenseNumber, + dd.license_front_url AS licenseFrontURL, + dd.license_back_url AS licenseBackURL, + dd.registration_date AS registrationDate, + dd.availability AS availability, + dd.stripe_id AS stripeId, + dd.wallet_balance AS walletBalance, + d.email AS email, + d.mobile_number AS mobileNumber, + COALESCE(SUM(r.rating_count) / NULLIF(COUNT(r.rating_id), 0), 0) AS rating, + COALESCE(SUM(e.delivery_charge), 0) AS earnings + FROM + driver_details dd + JOIN + drivers d ON dd.user_id = d.user_id + LEFT JOIN + earning e ON dd.user_details_id = e.driver_id + LEFT JOIN + delivery_order o ON e.delivery_id = o.delivery_id + LEFT JOIN + rating r ON o.delivery_id = r.delivery_id + WHERE + dd.approved = 'APPROVED' + AND DATE(e.created_at) = CURRENT_DATE + GROUP BY + dd.user_details_id, dd.first_name, dd.last_name, dd.date_of_birth, dd.gender, + dd.home_no, dd.street_name, dd.city, dd.district, dd.license_number, + dd.license_front_url, dd.license_back_url, dd.registration_date, dd.availability, + dd.stripe_id, dd.wallet_balance, d.email, d.mobile_number + ORDER BY + earnings DESC + """, nativeQuery = true) List findApprovedDriversWithEarningsToday(); // Churn feature query diff --git a/src/main/java/com/pentagon/Quicky_Backend/repository/DriverEarningsRepo.java b/src/main/java/com/pentagon/Quicky_Backend/repository/DriverEarningsRepo.java index 225253e..0e0113f 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/repository/DriverEarningsRepo.java +++ b/src/main/java/com/pentagon/Quicky_Backend/repository/DriverEarningsRepo.java @@ -13,14 +13,14 @@ public interface DriverEarningsRepo extends JpaRepository { @Query(value = """ SELECT - DATE(o.time_stamp) AS earningDate, + DATE(e.created_at) AS earningDate, COALESCE(SUM(e.delivery_charge), 0) AS amount FROM earning e JOIN delivery_order o ON e.delivery_id = o.delivery_id GROUP BY - DATE(o.time_stamp) + DATE(e.created_at) ORDER BY earningDate """, nativeQuery = true) diff --git a/src/main/java/com/pentagon/Quicky_Backend/service/NewRegistrationsService.java b/src/main/java/com/pentagon/Quicky_Backend/service/NewRegistrationsService.java index 050a558..9f573d4 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/service/NewRegistrationsService.java +++ b/src/main/java/com/pentagon/Quicky_Backend/service/NewRegistrationsService.java @@ -26,7 +26,7 @@ public boolean addDriver(Integer userDetailsId) { if (optionalNewDriver.isPresent()) { DriverDetails newDriver = optionalNewDriver.get(); - newDriver.setApproved(true); + newDriver.setApproved(DriverDetails.ApprovalStatus.APPROVED); newDriver.setRegistrationDate(LocalDate.now()); driverDetailsRepo.save(newDriver); @@ -41,7 +41,7 @@ public boolean rejectDriver(Integer userDetailsId) { if (optionalNewDriver.isPresent()) { DriverDetails newDriver = optionalNewDriver.get(); - newDriver.setApproved(false); + newDriver.setApproved(DriverDetails.ApprovalStatus.REJECTED); driverDetailsRepo.save(newDriver); return true; From 40666f7d95175d51d34282a0a50b3a309e1ee796 Mon Sep 17 00:00:00 2001 From: Kaveesha529 Date: Sun, 13 Jul 2025 18:12:01 +0530 Subject: [PATCH 02/28] feat(inactive drivers): create CRUD to display inactive drivers in a table --- .../controller/DriverProfilesController.java | 6 +++ .../repository/DriverDetailsRepo.java | 42 ++++++++++++++++++- .../service/DriverProfilesService.java | 3 ++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/pentagon/Quicky_Backend/controller/DriverProfilesController.java b/src/main/java/com/pentagon/Quicky_Backend/controller/DriverProfilesController.java index 42430ee..08be429 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/controller/DriverProfilesController.java +++ b/src/main/java/com/pentagon/Quicky_Backend/controller/DriverProfilesController.java @@ -44,4 +44,10 @@ public ResponseEntity> getTodayEarnings() { return new ResponseEntity<>(drivers, HttpStatus.OK); } + @GetMapping("/driver-profiles/inactive-drivers") + public ResponseEntity> getInactiveDrivers() { + List drivers = driverProfilesService.getInactiveDrivers(); + return new ResponseEntity<>(drivers, HttpStatus.OK); + } + } diff --git a/src/main/java/com/pentagon/Quicky_Backend/repository/DriverDetailsRepo.java b/src/main/java/com/pentagon/Quicky_Backend/repository/DriverDetailsRepo.java index 1a0bbe9..b5ea5fe 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/repository/DriverDetailsRepo.java +++ b/src/main/java/com/pentagon/Quicky_Backend/repository/DriverDetailsRepo.java @@ -213,4 +213,44 @@ driver_ratings AS ( """, nativeQuery = true) List getDriverFeaturesForChurnPrediction(); -} + @Query(value = """ + SELECT + dd.user_details_id AS userDetailsId, + dd.first_name AS firstName, + dd.last_name AS lastName, + dd.date_of_birth AS dateOfBirth, + dd.gender AS gender, + dd.home_no AS homeNo, + dd.street_name AS streetName, + dd.city AS city, + dd.district AS district, + dd.license_number AS licenseNumber, + dd.license_front_url AS licenseFrontURL, + dd.license_back_url AS licenseBackURL, + dd.registration_date AS registrationDate, + dd.availability AS availability, + dd.stripe_id AS stripeId, + dd.wallet_balance AS walletBalance, + d.email AS email, + d.mobile_number AS mobileNumber, + COALESCE(SUM(r.rating_count) / NULLIF(COUNT(r.rating_id), 0), 0) AS rating + FROM driver_details dd + JOIN drivers d ON d.user_id = dd.user_id + LEFT JOIN rating r ON r.user_details_id = dd.user_details_id + WHERE dd.approved = 'APPROVED' + AND d.user_id IN ( + SELECT da.user_id + FROM driver_availability da + GROUP BY da.user_id + HAVING MAX(da.end_time) < now() - interval '7 days' + ) + GROUP BY dd.user_details_id, dd.first_name, dd.last_name, dd.date_of_birth, dd.gender, + dd.home_no, dd.street_name, dd.city, dd.district, dd.license_number, + dd.license_front_url, dd.license_back_url, dd.registration_date, dd.availability, + dd.stripe_id, dd.wallet_balance, d.email, d.mobile_number + ORDER BY dd.user_details_id +""", nativeQuery = true) + List findApprovedInactiveDrivers(); + + +} \ No newline at end of file diff --git a/src/main/java/com/pentagon/Quicky_Backend/service/DriverProfilesService.java b/src/main/java/com/pentagon/Quicky_Backend/service/DriverProfilesService.java index 6808fae..7830f92 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/service/DriverProfilesService.java +++ b/src/main/java/com/pentagon/Quicky_Backend/service/DriverProfilesService.java @@ -31,4 +31,7 @@ public List getTodayEarnings() { return driverDetailsRepo.findApprovedDriversWithEarningsToday(); } + public List getInactiveDrivers() { + return driverDetailsRepo.findApprovedInactiveDrivers(); + } } From 0c7cc42b6703ba5d15bcee2252fe2c319630c31b Mon Sep 17 00:00:00 2001 From: Kaveesha529 Date: Sun, 13 Jul 2025 19:35:50 +0530 Subject: [PATCH 03/28] feat(inactive drivers): create CRUD to display inactive drivers in a pie chart --- .../controller/DriverProfilesController.java | 7 +++++ .../dto/InactiveDriversCountDto.java | 6 ++++ .../repository/DriverDetailsRepo.java | 30 +++++++++++++++---- .../service/DriverProfilesService.java | 5 ++++ 4 files changed, 43 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/pentagon/Quicky_Backend/dto/InactiveDriversCountDto.java diff --git a/src/main/java/com/pentagon/Quicky_Backend/controller/DriverProfilesController.java b/src/main/java/com/pentagon/Quicky_Backend/controller/DriverProfilesController.java index 08be429..d650300 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/controller/DriverProfilesController.java +++ b/src/main/java/com/pentagon/Quicky_Backend/controller/DriverProfilesController.java @@ -3,6 +3,7 @@ import com.pentagon.Quicky_Backend.dto.DriverEarningsProfilesDto; import com.pentagon.Quicky_Backend.dto.DriverProfilesDto; import com.pentagon.Quicky_Backend.dto.DriversCountDto; +import com.pentagon.Quicky_Backend.dto.InactiveDriversCountDto; import com.pentagon.Quicky_Backend.service.DriverProfilesService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; @@ -50,4 +51,10 @@ public ResponseEntity> getInactiveDrivers() { return new ResponseEntity<>(drivers, HttpStatus.OK); } + @GetMapping("/driver-profiles/inactive-drivers/count-by-availability") + public ResponseEntity> getInactiveDriversCount() { + List drivers = driverProfilesService.getInactiveDriversCount(); + return new ResponseEntity<>(drivers, HttpStatus.OK); + } + } diff --git a/src/main/java/com/pentagon/Quicky_Backend/dto/InactiveDriversCountDto.java b/src/main/java/com/pentagon/Quicky_Backend/dto/InactiveDriversCountDto.java new file mode 100644 index 0000000..b9848cb --- /dev/null +++ b/src/main/java/com/pentagon/Quicky_Backend/dto/InactiveDriversCountDto.java @@ -0,0 +1,6 @@ +package com.pentagon.Quicky_Backend.dto; + +public interface InactiveDriversCountDto { + Long getInactiveDriversCount(); + Long getActiveDriversCount(); +} diff --git a/src/main/java/com/pentagon/Quicky_Backend/repository/DriverDetailsRepo.java b/src/main/java/com/pentagon/Quicky_Backend/repository/DriverDetailsRepo.java index b5ea5fe..310711c 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/repository/DriverDetailsRepo.java +++ b/src/main/java/com/pentagon/Quicky_Backend/repository/DriverDetailsRepo.java @@ -1,10 +1,6 @@ package com.pentagon.Quicky_Backend.repository; -import com.pentagon.Quicky_Backend.dto.ChurnPredictFeatureDto; -import com.pentagon.Quicky_Backend.dto.DriverEarningsProfilesDto; -import com.pentagon.Quicky_Backend.dto.DriverProfilesDto; -import com.pentagon.Quicky_Backend.dto.DriversCountDto; -import com.pentagon.Quicky_Backend.dto.NewRegistrationsDto; +import com.pentagon.Quicky_Backend.dto.*; import com.pentagon.Quicky_Backend.entity.DriverDetails; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; @@ -252,5 +248,29 @@ HAVING MAX(da.end_time) < now() - interval '7 days' """, nativeQuery = true) List findApprovedInactiveDrivers(); + @Query(value = """ + SELECT + COUNT(*) FILTER ( + WHERE d.user_id IN ( + SELECT da.user_id + FROM driver_availability da + GROUP BY da.user_id + HAVING MAX(da.end_time) < now() - interval '7 days' + ) + ) AS inactiveDriversCount, + + COUNT(*) FILTER ( + WHERE d.user_id NOT IN ( + SELECT da.user_id + FROM driver_availability da + GROUP BY da.user_id + HAVING MAX(da.end_time) < now() - interval '7 days' + ) + ) AS activeDriversCount + FROM driver_details dd + JOIN drivers d ON d.user_id = dd.user_id + WHERE dd.approved = 'APPROVED' +""", nativeQuery = true) + List countApprovedInactiveDrivers(); } \ No newline at end of file diff --git a/src/main/java/com/pentagon/Quicky_Backend/service/DriverProfilesService.java b/src/main/java/com/pentagon/Quicky_Backend/service/DriverProfilesService.java index 7830f92..a375846 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/service/DriverProfilesService.java +++ b/src/main/java/com/pentagon/Quicky_Backend/service/DriverProfilesService.java @@ -3,6 +3,7 @@ import com.pentagon.Quicky_Backend.dto.DriverEarningsProfilesDto; import com.pentagon.Quicky_Backend.dto.DriverProfilesDto; import com.pentagon.Quicky_Backend.dto.DriversCountDto; +import com.pentagon.Quicky_Backend.dto.InactiveDriversCountDto; import com.pentagon.Quicky_Backend.repository.DriverDetailsRepo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -34,4 +35,8 @@ public List getTodayEarnings() { public List getInactiveDrivers() { return driverDetailsRepo.findApprovedInactiveDrivers(); } + + public List getInactiveDriversCount() { + return driverDetailsRepo.countApprovedInactiveDrivers(); + } } From c41553221f1f04ddca1854fabcfb852f90a031e9 Mon Sep 17 00:00:00 2001 From: HashiruG Date: Mon, 14 Jul 2025 00:24:35 +0530 Subject: [PATCH 04/28] refactor: remove unused query and imports in OfferRepo --- .../pentagon/Quicky_Backend/repository/OfferRepo.java | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/pentagon/Quicky_Backend/repository/OfferRepo.java b/src/main/java/com/pentagon/Quicky_Backend/repository/OfferRepo.java index 43de3a3..15929b7 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/repository/OfferRepo.java +++ b/src/main/java/com/pentagon/Quicky_Backend/repository/OfferRepo.java @@ -1,17 +1,12 @@ package com.pentagon.Quicky_Backend.repository; -import java.util.List; - import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; + import org.springframework.stereotype.Repository; -import com.pentagon.Quicky_Backend.dto.OfferResponseDto; import com.pentagon.Quicky_Backend.entity.Offer; @Repository public interface OfferRepo extends JpaRepository { - @Query("SELECT new com.pentagon.Quicky_Backend.dto.OfferResponseDto(o.offerId, o.offerTitle, o.offerDescription," + - "o.discountPercentage, o.offerType, o.startDate, o.endDate) FROM Offer o") - List findAllOfferDetails(); + } From fe9dc79a684bb31ed678cb4ed2d5f0003291824c Mon Sep 17 00:00:00 2001 From: HashiruG Date: Mon, 14 Jul 2025 00:24:51 +0530 Subject: [PATCH 05/28] feat: add OfferedDriversDto class and update OfferResponseDto to include offeredDrivers list --- .../Quicky_Backend/dto/OfferResponseDto.java | 2 ++ .../Quicky_Backend/dto/OfferedDriversDto.java | 15 +++++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 src/main/java/com/pentagon/Quicky_Backend/dto/OfferedDriversDto.java diff --git a/src/main/java/com/pentagon/Quicky_Backend/dto/OfferResponseDto.java b/src/main/java/com/pentagon/Quicky_Backend/dto/OfferResponseDto.java index 00e38e9..07cd49c 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/dto/OfferResponseDto.java +++ b/src/main/java/com/pentagon/Quicky_Backend/dto/OfferResponseDto.java @@ -1,6 +1,7 @@ package com.pentagon.Quicky_Backend.dto; import java.time.LocalDate; +import java.util.List; import lombok.AllArgsConstructor; import lombok.Data; @@ -17,4 +18,5 @@ public class OfferResponseDto { private String offerType; private LocalDate startDate; private LocalDate endDate; + private List offeredDrivers; } diff --git a/src/main/java/com/pentagon/Quicky_Backend/dto/OfferedDriversDto.java b/src/main/java/com/pentagon/Quicky_Backend/dto/OfferedDriversDto.java new file mode 100644 index 0000000..5d7d7cb --- /dev/null +++ b/src/main/java/com/pentagon/Quicky_Backend/dto/OfferedDriversDto.java @@ -0,0 +1,15 @@ +package com.pentagon.Quicky_Backend.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@AllArgsConstructor +@NoArgsConstructor +@Data +public class OfferedDriversDto { + private Integer driverId; + private String driverName; + private String gender; + private String city; +} From 98414257af931e366c64e9d9f176ae1d83f5f442 Mon Sep 17 00:00:00 2001 From: HashiruG Date: Mon, 14 Jul 2025 00:25:05 +0530 Subject: [PATCH 06/28] feat: enhance OfferService to fetch offers with detailed driver information --- .../controller/OfferController.java | 2 -- .../Quicky_Backend/service/OfferService.java | 32 +++++++++++++++++-- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/pentagon/Quicky_Backend/controller/OfferController.java b/src/main/java/com/pentagon/Quicky_Backend/controller/OfferController.java index 7f388ac..6c70ce2 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/controller/OfferController.java +++ b/src/main/java/com/pentagon/Quicky_Backend/controller/OfferController.java @@ -1,10 +1,8 @@ package com.pentagon.Quicky_Backend.controller; import org.springframework.web.bind.annotation.RestController; - import com.pentagon.Quicky_Backend.dto.OfferRequestDto; import com.pentagon.Quicky_Backend.dto.OfferResponseDto; - import com.pentagon.Quicky_Backend.service.OfferService; import java.util.List; diff --git a/src/main/java/com/pentagon/Quicky_Backend/service/OfferService.java b/src/main/java/com/pentagon/Quicky_Backend/service/OfferService.java index a99154f..465b4ae 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/service/OfferService.java +++ b/src/main/java/com/pentagon/Quicky_Backend/service/OfferService.java @@ -1,12 +1,14 @@ package com.pentagon.Quicky_Backend.service; import java.util.List; +import java.util.stream.Collectors; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import com.pentagon.Quicky_Backend.dto.OfferRequestDto; import com.pentagon.Quicky_Backend.dto.OfferResponseDto; +import com.pentagon.Quicky_Backend.dto.OfferedDriversDto; import com.pentagon.Quicky_Backend.entity.DriverDetails; import com.pentagon.Quicky_Backend.entity.Offer; @@ -26,7 +28,31 @@ public OfferService(OfferRepo offerRepo, DriverDetailsRepo driverDetailsRepo) { public List getOffers() { try { - return offerRepo.findAllOfferDetails(); + + List offers = offerRepo.findAll(); + + return offers.stream().map(offer -> { + OfferResponseDto offerDto = new OfferResponseDto(); + offerDto.setOfferId(offer.getOfferId()); + offerDto.setOfferTitle(offer.getOfferTitle()); + offerDto.setOfferDescription(offer.getOfferDescription()); + offerDto.setDiscountPercentage(offer.getDiscountPercentage()); + offerDto.setOfferType(offer.getOfferType()); + offerDto.setStartDate(offer.getStartDate()); + offerDto.setEndDate(offer.getEndDate()); + + List offeredDrivers = offer.getDriverDetails().stream().map(driver -> { + String driverName = driver.getFirstName() + " " + driver.getLastName(); + + return new OfferedDriversDto(driver.getUserDetailsId(), driverName, driver.getGender(), + driver.getCity()); + + }).collect(Collectors.toList()); + + offerDto.setOfferedDrivers(offeredDrivers); + return offerDto; + + }).collect(Collectors.toList()); } catch (Exception e) { throw new RuntimeException("Failed to fetch offers", e); } @@ -65,11 +91,13 @@ public ResponseEntity createOffer(OfferRequestDto offerRequestDto) { for (DriverDetails driver : drivers) { List currentOffers = driver.getOffers(); + System.out.println("Current Offers: " + currentOffers); currentOffers.add(offer); driver.setOffers(currentOffers); driverDetailsRepo.save(driver); + System.out.println("Updated Driver Offers: " + driver.getOffers()); } - return ResponseEntity.ok("Custom offer created successfully for all drivers"); + return ResponseEntity.ok("General offer created successfully for all drivers"); } else { offer.setOfferType("Custom"); From bc9dac6c5ba689fe73d5909595d8713ece6b54a9 Mon Sep 17 00:00:00 2001 From: HashiruG Date: Mon, 14 Jul 2025 07:45:17 +0530 Subject: [PATCH 07/28] feat: update entity structures for DeliveryOrder, DriverDetails, Drivers, Earning, and Vehicle --- .../Quicky_Backend/entity/DeliveryOrder.java | 2 +- .../Quicky_Backend/entity/DriverDetails.java | 15 +++++++----- .../Quicky_Backend/entity/Drivers.java | 23 ++++++++++++++++--- .../Quicky_Backend/entity/Earning.java | 22 ++++++++++++++---- .../Quicky_Backend/entity/Vehicle.java | 8 +++++-- 5 files changed, 53 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/pentagon/Quicky_Backend/entity/DeliveryOrder.java b/src/main/java/com/pentagon/Quicky_Backend/entity/DeliveryOrder.java index 4f455d1..7f09a75 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/entity/DeliveryOrder.java +++ b/src/main/java/com/pentagon/Quicky_Backend/entity/DeliveryOrder.java @@ -48,7 +48,7 @@ public class DeliveryOrder { private LocalDateTime endTime; @Column(name = "completion_time") - private LocalDateTime completionTime; + private Long completionTime; @Column(name = "payment_methode", nullable = false ) private String paymentMethode; diff --git a/src/main/java/com/pentagon/Quicky_Backend/entity/DriverDetails.java b/src/main/java/com/pentagon/Quicky_Backend/entity/DriverDetails.java index 4cd95a4..da8e384 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/entity/DriverDetails.java +++ b/src/main/java/com/pentagon/Quicky_Backend/entity/DriverDetails.java @@ -57,17 +57,20 @@ public class DriverDetails { @Column(name = "registration_date", nullable = false, columnDefinition = "DATE DEFAULT CURRENT_DATE") private LocalDate registrationDate; - @Column(name = "availability", nullable = false, columnDefinition = "BOOLEAN DEFAULT TRUE") - private boolean availability = true; + @Column(name = "availability", nullable = false, columnDefinition = "BOOLEAN DEFAULT FALSE") + private boolean availability = false; @Column(name = "stripe_id", nullable = false) private String stripeId; - @Column(name = "wallet_balance", nullable = false) - private Double walletBalance; + @Column(name = "wallet_balance", nullable = false, columnDefinition = "double precision default 0") + private Double walletBalance = 0.0; @Column(name = "approved", nullable = false, columnDefinition = "BOOLEAN DEFAULT FALSE") - private Boolean approved; + private Boolean approved = false; + + @Column(name = "profile_image_url") + private String profileImageUrl; //Cardinality among tables @OneToOne @@ -96,4 +99,4 @@ public void setRegistrationDateIfNull() { this.registrationDate = LocalDate.now(); } } -} +} \ No newline at end of file diff --git a/src/main/java/com/pentagon/Quicky_Backend/entity/Drivers.java b/src/main/java/com/pentagon/Quicky_Backend/entity/Drivers.java index 053278d..4b10bf3 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/entity/Drivers.java +++ b/src/main/java/com/pentagon/Quicky_Backend/entity/Drivers.java @@ -5,6 +5,7 @@ import lombok.Data; import lombok.NoArgsConstructor; +import java.util.Date; import java.util.List; @Entity @@ -31,12 +32,28 @@ public class Drivers { @Column(name = "password", nullable = false, unique = true) private String password; + @Column(name = "role", columnDefinition = "VARCHAR(255) DEFAULT 'User'") + private String role = "User"; + @Column(name = "push_notification_token") private String pushNotificationToken; @Column(name = "language", nullable = false) private String language; + @Column(name = "reset_password_token", unique = true) + private String resetPasswordToken; + + @Column(name = "reset_password_token_expiry") + private Date resetPasswordTokenExpiry; + + @Column(name = "is_active", nullable = false) + private boolean isActive; + + @Column(name = "fcm_token") + private String fcmToken; + + //Cardinality among tables @OneToOne(mappedBy = "drivers", cascade = CascadeType.ALL, orphanRemoval = true) private DriverDetails userDetails; @@ -49,12 +66,12 @@ public class Drivers { @OneToMany(mappedBy = "drivers", cascade = CascadeType.ALL, orphanRemoval = true) private List deliveryOrderSlots; - @OneToMany(mappedBy = "drivers", cascade = CascadeType.ALL, orphanRemoval = true) - private List locationSlots; + @OneToOne(mappedBy = "drivers", cascade = CascadeType.ALL, orphanRemoval = true) + private DriverLocation locationSlots; @OneToOne(mappedBy = "drivers", cascade = CascadeType.ALL, orphanRemoval = true) private Balance balance; @OneToMany(mappedBy = "drivers", cascade = CascadeType.ALL, orphanRemoval = true) private List notificationSlots; -} +} \ No newline at end of file diff --git a/src/main/java/com/pentagon/Quicky_Backend/entity/Earning.java b/src/main/java/com/pentagon/Quicky_Backend/entity/Earning.java index 6cdea11..38cac79 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/entity/Earning.java +++ b/src/main/java/com/pentagon/Quicky_Backend/entity/Earning.java @@ -1,17 +1,17 @@ package com.pentagon.Quicky_Backend.entity; -import java.time.LocalDateTime; - import jakarta.persistence.*; import lombok.*; +import java.time.LocalDateTime; + @Entity @Data @AllArgsConstructor @NoArgsConstructor @Table(name = "earning") -@ToString(exclude = { "driverDetails", "delivery" }) -@EqualsAndHashCode(exclude = { "driverDetails", "delivery" }) +@ToString(exclude = {"driverDetails", "delivery"}) +@EqualsAndHashCode(exclude = {"driverDetails", "delivery"}) public class Earning { @Id @@ -25,6 +25,12 @@ public class Earning { @Column(name = "created_at") private LocalDateTime createdAt; + + //Cardinality among tables +// @OneToOne +// @JoinColumn(name = "delivery_id") +// private DeliveryOrder delivery; + @ManyToOne @JoinColumn(name = "driver_id", referencedColumnName = "user_details_id") private DriverDetails driverDetails; @@ -32,4 +38,10 @@ public class Earning { @OneToOne @JoinColumn(name = "delivery_id", referencedColumnName = "delivery_id") private DeliveryOrder delivery; -} + + @PrePersist + protected void onCreate() { + this.createdAt = LocalDateTime.now(); + } + +} \ No newline at end of file diff --git a/src/main/java/com/pentagon/Quicky_Backend/entity/Vehicle.java b/src/main/java/com/pentagon/Quicky_Backend/entity/Vehicle.java index 4d2ed68..07543b7 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/entity/Vehicle.java +++ b/src/main/java/com/pentagon/Quicky_Backend/entity/Vehicle.java @@ -3,7 +3,6 @@ import jakarta.persistence.*; import lombok.*; - @Entity @Table(name = "vehicle") @Getter @@ -37,8 +36,13 @@ public class Vehicle { @Column(name = "vehicle_book_url", nullable = false) private String vehicleBookURL; - + + //Cardinality among tables @OneToOne @JoinColumn(name = "user_id", referencedColumnName = "user_id") private Drivers drivers; + + @OneToOne + @JoinColumn(name = "driver_details_id", referencedColumnName = "user_details_id") + private DriverDetails driverDetails; } \ No newline at end of file From 7f10e8c347ae5f20665242d73018c2522d503dd5 Mon Sep 17 00:00:00 2001 From: HashiruG Date: Wed, 16 Jul 2025 12:18:03 +0530 Subject: [PATCH 08/28] feat: add CommissionRate entity and repository for commission rate management --- .../Quicky_Backend/dto/CommissionRateDto.java | 12 ++++++++ .../Quicky_Backend/entity/CommissionRate.java | 30 +++++++++++++++++++ .../repository/CommissionRateRepo.java | 9 ++++++ 3 files changed, 51 insertions(+) create mode 100644 src/main/java/com/pentagon/Quicky_Backend/dto/CommissionRateDto.java create mode 100644 src/main/java/com/pentagon/Quicky_Backend/entity/CommissionRate.java create mode 100644 src/main/java/com/pentagon/Quicky_Backend/repository/CommissionRateRepo.java diff --git a/src/main/java/com/pentagon/Quicky_Backend/dto/CommissionRateDto.java b/src/main/java/com/pentagon/Quicky_Backend/dto/CommissionRateDto.java new file mode 100644 index 0000000..2069b1a --- /dev/null +++ b/src/main/java/com/pentagon/Quicky_Backend/dto/CommissionRateDto.java @@ -0,0 +1,12 @@ +package com.pentagon.Quicky_Backend.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@AllArgsConstructor +@NoArgsConstructor +@Data +public class CommissionRateDto { + private Double commissionRate; +} diff --git a/src/main/java/com/pentagon/Quicky_Backend/entity/CommissionRate.java b/src/main/java/com/pentagon/Quicky_Backend/entity/CommissionRate.java new file mode 100644 index 0000000..bfc106a --- /dev/null +++ b/src/main/java/com/pentagon/Quicky_Backend/entity/CommissionRate.java @@ -0,0 +1,30 @@ +package com.pentagon.Quicky_Backend.entity; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.Date; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Entity +@AllArgsConstructor +@NoArgsConstructor +@Data +@Table(name = "commission_rate") +public class CommissionRate { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private LocalDateTime changedDate; + private Double commissionRate; + +} diff --git a/src/main/java/com/pentagon/Quicky_Backend/repository/CommissionRateRepo.java b/src/main/java/com/pentagon/Quicky_Backend/repository/CommissionRateRepo.java new file mode 100644 index 0000000..84c1eec --- /dev/null +++ b/src/main/java/com/pentagon/Quicky_Backend/repository/CommissionRateRepo.java @@ -0,0 +1,9 @@ +package com.pentagon.Quicky_Backend.repository; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.pentagon.Quicky_Backend.entity.CommissionRate; + +public interface CommissionRateRepo extends JpaRepository { + CommissionRate findFirstByOrderByChangedDateDesc(); +} From b47b06f892ea8518c27c7455b9fb7d0189959736 Mon Sep 17 00:00:00 2001 From: HashiruG Date: Wed, 16 Jul 2025 12:18:16 +0530 Subject: [PATCH 09/28] feat: implement CommissionRateController and CommissionRateService for commission rate management --- .../controller/CommissionRateController.java | 35 +++++++++++++++++++ .../service/CommissionRateService.java | 33 +++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 src/main/java/com/pentagon/Quicky_Backend/controller/CommissionRateController.java create mode 100644 src/main/java/com/pentagon/Quicky_Backend/service/CommissionRateService.java diff --git a/src/main/java/com/pentagon/Quicky_Backend/controller/CommissionRateController.java b/src/main/java/com/pentagon/Quicky_Backend/controller/CommissionRateController.java new file mode 100644 index 0000000..8d856eb --- /dev/null +++ b/src/main/java/com/pentagon/Quicky_Backend/controller/CommissionRateController.java @@ -0,0 +1,35 @@ +package com.pentagon.Quicky_Backend.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.pentagon.Quicky_Backend.dto.CommissionRateDto; +import com.pentagon.Quicky_Backend.service.CommissionRateService; + +@RestController +@RequestMapping("/commission") +public class CommissionRateController { + + private final CommissionRateService commissionRateService; + + public CommissionRateController(CommissionRateService commissionRateService) { + this.commissionRateService = commissionRateService; + } + + @GetMapping("/get-commission-rate") + public ResponseEntity getLatestCommissionRate() { + CommissionRateDto response = commissionRateService.getLatestCommissionRate(); + return ResponseEntity.ok(response); + } + + @PostMapping("/change-commission-rate") + public ResponseEntity changeCommissionRate(@RequestBody CommissionRateDto commissionRateDto) { + commissionRateService.updateCommissionRate(commissionRateDto.getCommissionRate()); + return ResponseEntity.ok("Commission rate updated successfully"); + } +} diff --git a/src/main/java/com/pentagon/Quicky_Backend/service/CommissionRateService.java b/src/main/java/com/pentagon/Quicky_Backend/service/CommissionRateService.java new file mode 100644 index 0000000..563ed17 --- /dev/null +++ b/src/main/java/com/pentagon/Quicky_Backend/service/CommissionRateService.java @@ -0,0 +1,33 @@ +package com.pentagon.Quicky_Backend.service; + +import org.springframework.stereotype.Service; + +import com.pentagon.Quicky_Backend.dto.CommissionRateDto; +import com.pentagon.Quicky_Backend.entity.CommissionRate; +import com.pentagon.Quicky_Backend.repository.CommissionRateRepo; + +@Service +public class CommissionRateService { + private final CommissionRateRepo commissionRateRepo; + + public CommissionRateService(CommissionRateRepo commissionRateRepo) { + this.commissionRateRepo = commissionRateRepo; + } + + public CommissionRateDto getLatestCommissionRate() { + CommissionRate rateRec = commissionRateRepo.findFirstByOrderByChangedDateDesc(); + if (rateRec != null) { + return new CommissionRateDto(rateRec.getCommissionRate()); + } else { + return new CommissionRateDto(12.0); + } + } + + public void updateCommissionRate(Double newRate) { + + CommissionRate newRateRec = new CommissionRate(); + newRateRec.setCommissionRate(newRate); + newRateRec.setChangedDate(java.time.LocalDateTime.now()); + commissionRateRepo.save(newRateRec); + } +} From b3cb1bd4d12eb2b277199906cb714e61ff8e2394 Mon Sep 17 00:00:00 2001 From: HashiruG Date: Thu, 17 Jul 2025 14:33:06 +0530 Subject: [PATCH 10/28] refactor: remove unused import for Autowired in CommissionRateController --- .../Quicky_Backend/controller/CommissionRateController.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/pentagon/Quicky_Backend/controller/CommissionRateController.java b/src/main/java/com/pentagon/Quicky_Backend/controller/CommissionRateController.java index 8d856eb..468fd98 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/controller/CommissionRateController.java +++ b/src/main/java/com/pentagon/Quicky_Backend/controller/CommissionRateController.java @@ -1,6 +1,5 @@ package com.pentagon.Quicky_Backend.controller; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; From 25844984c09bf2005c50c89e7248d88e3fc4d9a3 Mon Sep 17 00:00:00 2001 From: HashiruG Date: Thu, 17 Jul 2025 14:51:05 +0530 Subject: [PATCH 11/28] feat: enhance DTOs and services for churn driver and offer management --- .../Quicky_Backend/dto/ChurnResponseDto.java | 2 + .../Quicky_Backend/dto/OfferRequestDto.java | 6 +- .../Quicky_Backend/dto/SelectedDriverDto.java | 13 +++ .../Quicky_Backend/entity/ChurnDriver.java | 3 + .../repository/ChurnDriverRepo.java | 2 + .../service/ChurnDriverService.java | 2 + .../Quicky_Backend/service/OfferService.java | 83 ++++++++++++------- 7 files changed, 76 insertions(+), 35 deletions(-) create mode 100644 src/main/java/com/pentagon/Quicky_Backend/dto/SelectedDriverDto.java diff --git a/src/main/java/com/pentagon/Quicky_Backend/dto/ChurnResponseDto.java b/src/main/java/com/pentagon/Quicky_Backend/dto/ChurnResponseDto.java index a606ebf..59404cc 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/dto/ChurnResponseDto.java +++ b/src/main/java/com/pentagon/Quicky_Backend/dto/ChurnResponseDto.java @@ -8,8 +8,10 @@ @NoArgsConstructor @Data public class ChurnResponseDto { + private Long predictionId; private Integer driverDetailsId; private String driverName; private String gender; private String city; + private String status; } diff --git a/src/main/java/com/pentagon/Quicky_Backend/dto/OfferRequestDto.java b/src/main/java/com/pentagon/Quicky_Backend/dto/OfferRequestDto.java index de81d53..9d562dc 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/dto/OfferRequestDto.java +++ b/src/main/java/com/pentagon/Quicky_Backend/dto/OfferRequestDto.java @@ -7,14 +7,14 @@ import lombok.Data; import lombok.NoArgsConstructor; -@AllArgsConstructor -@NoArgsConstructor @Data +@NoArgsConstructor +@AllArgsConstructor public class OfferRequestDto { private String offerTitle; private String offerDescription; private Double discountPercentage; private LocalDate startDate; private LocalDate endDate; - private List selectedIds; + private List selectedDrivers; } diff --git a/src/main/java/com/pentagon/Quicky_Backend/dto/SelectedDriverDto.java b/src/main/java/com/pentagon/Quicky_Backend/dto/SelectedDriverDto.java new file mode 100644 index 0000000..e8d722a --- /dev/null +++ b/src/main/java/com/pentagon/Quicky_Backend/dto/SelectedDriverDto.java @@ -0,0 +1,13 @@ +package com.pentagon.Quicky_Backend.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class SelectedDriverDto { + private Integer driverDetailsId; + private Long predictionId; +} \ No newline at end of file diff --git a/src/main/java/com/pentagon/Quicky_Backend/entity/ChurnDriver.java b/src/main/java/com/pentagon/Quicky_Backend/entity/ChurnDriver.java index 896483f..cdf6c41 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/entity/ChurnDriver.java +++ b/src/main/java/com/pentagon/Quicky_Backend/entity/ChurnDriver.java @@ -32,4 +32,7 @@ public class ChurnDriver { @ManyToOne @JoinColumn(name = "driver_id", referencedColumnName = "user_details_id") private DriverDetails driver; + + private String status = "not incentivized"; } + diff --git a/src/main/java/com/pentagon/Quicky_Backend/repository/ChurnDriverRepo.java b/src/main/java/com/pentagon/Quicky_Backend/repository/ChurnDriverRepo.java index 7b0864f..9aafe1c 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/repository/ChurnDriverRepo.java +++ b/src/main/java/com/pentagon/Quicky_Backend/repository/ChurnDriverRepo.java @@ -13,4 +13,6 @@ public interface ChurnDriverRepo extends JpaRepository { @Query("SELECT c FROM ChurnDriver c WHERE c.predictionDate = (SELECT MAX(c2.predictionDate) FROM ChurnDriver c2)") List findLatestChurnDrivers(); + + List findAllByPredictionIdIn(List predictionIds); } diff --git a/src/main/java/com/pentagon/Quicky_Backend/service/ChurnDriverService.java b/src/main/java/com/pentagon/Quicky_Backend/service/ChurnDriverService.java index 25b4c95..0c92bff 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/service/ChurnDriverService.java +++ b/src/main/java/com/pentagon/Quicky_Backend/service/ChurnDriverService.java @@ -75,11 +75,13 @@ public List getLatestChurnDrivers() { return latestChurners.stream() .map(churnDriver -> { ChurnResponseDto responseDto = new ChurnResponseDto(); + responseDto.setPredictionId(churnDriver.getPredictionId()); responseDto.setDriverDetailsId(churnDriver.getDriver().getUserDetailsId()); responseDto.setDriverName( churnDriver.getDriver().getFirstName() + " " + churnDriver.getDriver().getLastName()); responseDto.setGender(churnDriver.getDriver().getGender()); responseDto.setCity(churnDriver.getDriver().getCity()); + responseDto.setStatus(churnDriver.getStatus()); return responseDto; }) .collect(Collectors.toList()); diff --git a/src/main/java/com/pentagon/Quicky_Backend/service/OfferService.java b/src/main/java/com/pentagon/Quicky_Backend/service/OfferService.java index 465b4ae..ac28979 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/service/OfferService.java +++ b/src/main/java/com/pentagon/Quicky_Backend/service/OfferService.java @@ -9,28 +9,34 @@ import com.pentagon.Quicky_Backend.dto.OfferRequestDto; import com.pentagon.Quicky_Backend.dto.OfferResponseDto; import com.pentagon.Quicky_Backend.dto.OfferedDriversDto; +import com.pentagon.Quicky_Backend.dto.SelectedDriverDto; +import com.pentagon.Quicky_Backend.entity.ChurnDriver; import com.pentagon.Quicky_Backend.entity.DriverDetails; - import com.pentagon.Quicky_Backend.entity.Offer; +import com.pentagon.Quicky_Backend.repository.ChurnDriverRepo; import com.pentagon.Quicky_Backend.repository.DriverDetailsRepo; import com.pentagon.Quicky_Backend.repository.OfferRepo; @Service public class OfferService { - private OfferRepo offerRepo; - private DriverDetailsRepo driverDetailsRepo; + private final OfferRepo offerRepo; + private final DriverDetailsRepo driverDetailsRepo; + private final ChurnDriverRepo churnDriverRepo; - public OfferService(OfferRepo offerRepo, DriverDetailsRepo driverDetailsRepo) { - this.driverDetailsRepo = driverDetailsRepo; + public OfferService( + OfferRepo offerRepo, + DriverDetailsRepo driverDetailsRepo, + ChurnDriverRepo churnDriverRepo + ) { this.offerRepo = offerRepo; + this.driverDetailsRepo = driverDetailsRepo; + this.churnDriverRepo = churnDriverRepo; } public List getOffers() { try { - List offers = offerRepo.findAll(); - return offers.stream().map(offer -> { OfferResponseDto offerDto = new OfferResponseDto(); offerDto.setOfferId(offer.getOfferId()); @@ -41,17 +47,20 @@ public List getOffers() { offerDto.setStartDate(offer.getStartDate()); offerDto.setEndDate(offer.getEndDate()); - List offeredDrivers = offer.getDriverDetails().stream().map(driver -> { - String driverName = driver.getFirstName() + " " + driver.getLastName(); - - return new OfferedDriversDto(driver.getUserDetailsId(), driverName, driver.getGender(), - driver.getCity()); - - }).collect(Collectors.toList()); + List offeredDrivers = offer.getDriverDetails().stream() + .map(driver -> { + String driverName = driver.getFirstName() + " " + driver.getLastName(); + return new OfferedDriversDto( + driver.getUserDetailsId(), + driverName, + driver.getGender(), + driver.getCity() + ); + }) + .collect(Collectors.toList()); offerDto.setOfferedDrivers(offeredDrivers); return offerDto; - }).collect(Collectors.toList()); } catch (Exception e) { throw new RuntimeException("Failed to fetch offers", e); @@ -60,7 +69,8 @@ public List getOffers() { public ResponseEntity deleteOffer(Long offerId) { try { - Offer offer = offerRepo.findById(offerId).orElseThrow(() -> new RuntimeException("Offer not found")); + Offer offer = offerRepo.findById(offerId) + .orElseThrow(() -> new RuntimeException("Offer not found")); for (DriverDetails driver : offer.getDriverDetails()) { driver.getOffers().remove(offer); driverDetailsRepo.save(driver); @@ -70,7 +80,6 @@ public ResponseEntity deleteOffer(Long offerId) { } catch (Exception e) { return ResponseEntity.status(500).body("Error occurred while deleting the offer: " + e.getMessage()); } - } public ResponseEntity createOffer(OfferRequestDto offerRequestDto) { @@ -82,40 +91,50 @@ public ResponseEntity createOffer(OfferRequestDto offerRequestDto) { offer.setStartDate(offerRequestDto.getStartDate()); offer.setEndDate(offerRequestDto.getEndDate()); - if (offerRequestDto.getSelectedIds().size() == 0) { + List selectedDrivers = offerRequestDto.getSelectedDrivers(); + if (selectedDrivers == null || selectedDrivers.isEmpty()) { + // General offer for all drivers offer.setOfferType("General"); offerRepo.save(offer); - List drivers = driverDetailsRepo.findAll(); - - for (DriverDetails driver : drivers) { - List currentOffers = driver.getOffers(); - System.out.println("Current Offers: " + currentOffers); - currentOffers.add(offer); - driver.setOffers(currentOffers); + List allDrivers = driverDetailsRepo.findAll(); + for (DriverDetails driver : allDrivers) { + driver.getOffers().add(offer); driverDetailsRepo.save(driver); - System.out.println("Updated Driver Offers: " + driver.getOffers()); } return ResponseEntity.ok("General offer created successfully for all drivers"); } else { - + // Custom offer for selected drivers offer.setOfferType("Custom"); offerRepo.save(offer); - List drivers = driverDetailsRepo.findAllById(offerRequestDto.getSelectedIds()); - + // Assign offer to selected drivers: get driver IDs (Integer) + List driverIds = selectedDrivers.stream() + .map(SelectedDriverDto::getDriverDetailsId) + .collect(Collectors.toList()); + List drivers = driverDetailsRepo.findAllById(driverIds); for (DriverDetails driver : drivers) { driver.getOffers().add(offer); driverDetailsRepo.save(driver); } - return ResponseEntity.ok("Custom offer created successfully"); + // Update status of selected ChurnDriver predictions (Long) + List predictionIds = selectedDrivers.stream() + .map(SelectedDriverDto::getPredictionId) + .collect(Collectors.toList()); + if (!predictionIds.isEmpty()) { + List churnDrivers = churnDriverRepo.findAllByPredictionIdIn(predictionIds); + for (ChurnDriver churnDriver : churnDrivers) { + churnDriver.setStatus("incentivized"); + churnDriverRepo.save(churnDriver); + } + } + + return ResponseEntity.ok("Custom offer created and churn drivers updated successfully"); } } catch (Exception e) { return ResponseEntity.status(500).body("Error occurred while creating the offer: " + e.getMessage()); } - } - } From 7c04cf2244a6a7db056ebf9678111b836acd6be0 Mon Sep 17 00:00:00 2001 From: Kaveesha529 Date: Tue, 22 Jul 2025 16:47:04 +0530 Subject: [PATCH 12/28] feat(delivery management): created REST Api for delivery management table --- .../controller/DeliveryController.java | 27 +++++++++++++++ .../dto/DeliveryRecordsDto.java | 15 +++++++++ .../repository/DeliveryRepo.java | 33 +++++++++++++++++++ .../service/DeliveryService.java | 20 +++++++++++ 4 files changed, 95 insertions(+) create mode 100644 src/main/java/com/pentagon/Quicky_Backend/controller/DeliveryController.java create mode 100644 src/main/java/com/pentagon/Quicky_Backend/dto/DeliveryRecordsDto.java create mode 100644 src/main/java/com/pentagon/Quicky_Backend/repository/DeliveryRepo.java create mode 100644 src/main/java/com/pentagon/Quicky_Backend/service/DeliveryService.java diff --git a/src/main/java/com/pentagon/Quicky_Backend/controller/DeliveryController.java b/src/main/java/com/pentagon/Quicky_Backend/controller/DeliveryController.java new file mode 100644 index 0000000..b698500 --- /dev/null +++ b/src/main/java/com/pentagon/Quicky_Backend/controller/DeliveryController.java @@ -0,0 +1,27 @@ +package com.pentagon.Quicky_Backend.controller; + +import com.pentagon.Quicky_Backend.dto.DeliveryRecordsDto; +import com.pentagon.Quicky_Backend.dto.DriverProfilesDto; +import com.pentagon.Quicky_Backend.service.DeliveryService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@RestController +@CrossOrigin(origins = "http://localhost:5173") +public class DeliveryController { + + @Autowired + private DeliveryService deliveryService; + + @GetMapping("/delivery_records") + public ResponseEntity> getDeliveryRecords() { + List deliveries = deliveryService.getDeliveryRecords(); + return new ResponseEntity<>(deliveries, HttpStatus.OK); + } +} diff --git a/src/main/java/com/pentagon/Quicky_Backend/dto/DeliveryRecordsDto.java b/src/main/java/com/pentagon/Quicky_Backend/dto/DeliveryRecordsDto.java new file mode 100644 index 0000000..67d4629 --- /dev/null +++ b/src/main/java/com/pentagon/Quicky_Backend/dto/DeliveryRecordsDto.java @@ -0,0 +1,15 @@ +package com.pentagon.Quicky_Backend.dto; + +import java.time.LocalDate; + +public interface DeliveryRecordsDto { + Long getDeliveryId(); + Double getDeliveryFee(); + String getPickupLocation(); + String getDropOffLocation(); + String getDeliveryStatus(); + LocalDate getDeliveryDate(); + String getFirstName(); + String getLastName(); + Double getRating(); +} diff --git a/src/main/java/com/pentagon/Quicky_Backend/repository/DeliveryRepo.java b/src/main/java/com/pentagon/Quicky_Backend/repository/DeliveryRepo.java new file mode 100644 index 0000000..1ab91e7 --- /dev/null +++ b/src/main/java/com/pentagon/Quicky_Backend/repository/DeliveryRepo.java @@ -0,0 +1,33 @@ +package com.pentagon.Quicky_Backend.repository; + +import com.pentagon.Quicky_Backend.dto.DeliveryRecordsDto; +import com.pentagon.Quicky_Backend.entity.DeliveryOrder; +import com.pentagon.Quicky_Backend.entity.DriverDetails; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface DeliveryRepo extends JpaRepository { + + @Query(value = """ + SELECT + d.delivery_id AS deliveryId, + d.delivery_fee AS deliveryFee, + d.pick_up_location AS pickupLocation, + d.drop_off_location AS dropOffLocation, + d.delivery_status AS deliveryStatus, + CAST(d.start_time AS DATE) AS deliveryDate, + dd.first_name AS firstName, + dd.last_name AS lastName, + r.rating_count AS rating + FROM delivery_order d + LEFT JOIN driver_details dd ON d.user_details_id = dd.user_details_id + LEFT JOIN rating r ON d.delivery_id = r.delivery_id + ORDER BY d.delivery_id DESC +""", nativeQuery = true) + List getDeliveryRecords(); + +} diff --git a/src/main/java/com/pentagon/Quicky_Backend/service/DeliveryService.java b/src/main/java/com/pentagon/Quicky_Backend/service/DeliveryService.java new file mode 100644 index 0000000..caaf7ac --- /dev/null +++ b/src/main/java/com/pentagon/Quicky_Backend/service/DeliveryService.java @@ -0,0 +1,20 @@ +package com.pentagon.Quicky_Backend.service; + +import com.pentagon.Quicky_Backend.dto.DeliveryRecordsDto; +import com.pentagon.Quicky_Backend.repository.DeliveryRepo; +import com.pentagon.Quicky_Backend.repository.DriverDetailsRepo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class DeliveryService { + + @Autowired + private DeliveryRepo deliveryRepo; + + public List getDeliveryRecords() { + return deliveryRepo.getDeliveryRecords(); + } +} From 7608539e4d05b5cd5d67c9e31f794f4764e046c2 Mon Sep 17 00:00:00 2001 From: Kaveesha529 Date: Tue, 22 Jul 2025 20:44:26 +0530 Subject: [PATCH 13/28] feat(delivery distribution): created REST Api for delivery distribution area chart --- .../controller/DeliveryController.java | 7 +++++++ .../Quicky_Backend/dto/DeliveriesCountDto.java | 8 ++++++++ .../Quicky_Backend/repository/DeliveryRepo.java | 14 ++++++++++++++ .../Quicky_Backend/service/DeliveryService.java | 5 +++++ 4 files changed, 34 insertions(+) create mode 100644 src/main/java/com/pentagon/Quicky_Backend/dto/DeliveriesCountDto.java diff --git a/src/main/java/com/pentagon/Quicky_Backend/controller/DeliveryController.java b/src/main/java/com/pentagon/Quicky_Backend/controller/DeliveryController.java index b698500..066b8c1 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/controller/DeliveryController.java +++ b/src/main/java/com/pentagon/Quicky_Backend/controller/DeliveryController.java @@ -1,5 +1,6 @@ package com.pentagon.Quicky_Backend.controller; +import com.pentagon.Quicky_Backend.dto.DeliveriesCountDto; import com.pentagon.Quicky_Backend.dto.DeliveryRecordsDto; import com.pentagon.Quicky_Backend.dto.DriverProfilesDto; import com.pentagon.Quicky_Backend.service.DeliveryService; @@ -24,4 +25,10 @@ public ResponseEntity> getDeliveryRecords() { List deliveries = deliveryService.getDeliveryRecords(); return new ResponseEntity<>(deliveries, HttpStatus.OK); } + + @GetMapping("/deliveries_count") + public ResponseEntity> getDeliveriesCount() { + List deliveries = deliveryService.getDeliveriesCount(); + return new ResponseEntity<>(deliveries, HttpStatus.OK); + } } diff --git a/src/main/java/com/pentagon/Quicky_Backend/dto/DeliveriesCountDto.java b/src/main/java/com/pentagon/Quicky_Backend/dto/DeliveriesCountDto.java new file mode 100644 index 0000000..4443493 --- /dev/null +++ b/src/main/java/com/pentagon/Quicky_Backend/dto/DeliveriesCountDto.java @@ -0,0 +1,8 @@ +package com.pentagon.Quicky_Backend.dto; + +import java.time.LocalDate; + +public interface DeliveriesCountDto { + LocalDate getDeliveryDate(); + Long getDeliveriesCount(); +} diff --git a/src/main/java/com/pentagon/Quicky_Backend/repository/DeliveryRepo.java b/src/main/java/com/pentagon/Quicky_Backend/repository/DeliveryRepo.java index 1ab91e7..7afd6c4 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/repository/DeliveryRepo.java +++ b/src/main/java/com/pentagon/Quicky_Backend/repository/DeliveryRepo.java @@ -1,5 +1,6 @@ package com.pentagon.Quicky_Backend.repository; +import com.pentagon.Quicky_Backend.dto.DeliveriesCountDto; import com.pentagon.Quicky_Backend.dto.DeliveryRecordsDto; import com.pentagon.Quicky_Backend.entity.DeliveryOrder; import com.pentagon.Quicky_Backend.entity.DriverDetails; @@ -30,4 +31,17 @@ public interface DeliveryRepo extends JpaRepository { """, nativeQuery = true) List getDeliveryRecords(); + @Query(value = """ + SELECT + CAST(d.start_time AS DATE) AS deliveryDate, + COUNT(d.delivery_id) AS deliveriesCount + FROM + delivery_order d + GROUP BY + CAST(d.start_time AS DATE) + ORDER BY + deliveryDate + """, nativeQuery = true) + List getDeliveriesCount(); + } diff --git a/src/main/java/com/pentagon/Quicky_Backend/service/DeliveryService.java b/src/main/java/com/pentagon/Quicky_Backend/service/DeliveryService.java index caaf7ac..d604f3e 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/service/DeliveryService.java +++ b/src/main/java/com/pentagon/Quicky_Backend/service/DeliveryService.java @@ -1,5 +1,6 @@ package com.pentagon.Quicky_Backend.service; +import com.pentagon.Quicky_Backend.dto.DeliveriesCountDto; import com.pentagon.Quicky_Backend.dto.DeliveryRecordsDto; import com.pentagon.Quicky_Backend.repository.DeliveryRepo; import com.pentagon.Quicky_Backend.repository.DriverDetailsRepo; @@ -17,4 +18,8 @@ public class DeliveryService { public List getDeliveryRecords() { return deliveryRepo.getDeliveryRecords(); } + + public List getDeliveriesCount() { + return deliveryRepo.getDeliveriesCount(); + } } From 27957772ceaa148896e8610e9cff2704b855cbd6 Mon Sep 17 00:00:00 2001 From: Kaveesha529 Date: Tue, 22 Jul 2025 21:21:20 +0530 Subject: [PATCH 14/28] feat(delivery distribution): created REST Api for today delivery distribution table --- .../controller/DeliveryController.java | 6 ++++++ .../repository/DeliveryRepo.java | 19 +++++++++++++++++++ .../service/DeliveryService.java | 4 ++++ 3 files changed, 29 insertions(+) diff --git a/src/main/java/com/pentagon/Quicky_Backend/controller/DeliveryController.java b/src/main/java/com/pentagon/Quicky_Backend/controller/DeliveryController.java index 066b8c1..50f1023 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/controller/DeliveryController.java +++ b/src/main/java/com/pentagon/Quicky_Backend/controller/DeliveryController.java @@ -31,4 +31,10 @@ public ResponseEntity> getDeliveriesCount() { List deliveries = deliveryService.getDeliveriesCount(); return new ResponseEntity<>(deliveries, HttpStatus.OK); } + + @GetMapping("/delivery_records/today") + public ResponseEntity> getDeliveryRecordsToday() { + List deliveries = deliveryService.getDeliveryRecordsToday(); + return new ResponseEntity<>(deliveries, HttpStatus.OK); + } } diff --git a/src/main/java/com/pentagon/Quicky_Backend/repository/DeliveryRepo.java b/src/main/java/com/pentagon/Quicky_Backend/repository/DeliveryRepo.java index 7afd6c4..7e50a9f 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/repository/DeliveryRepo.java +++ b/src/main/java/com/pentagon/Quicky_Backend/repository/DeliveryRepo.java @@ -44,4 +44,23 @@ public interface DeliveryRepo extends JpaRepository { """, nativeQuery = true) List getDeliveriesCount(); + @Query(value = """ + SELECT + d.delivery_id AS deliveryId, + d.delivery_fee AS deliveryFee, + d.pick_up_location AS pickupLocation, + d.drop_off_location AS dropOffLocation, + d.delivery_status AS deliveryStatus, + CAST(d.start_time AS DATE) AS deliveryDate, + dd.first_name AS firstName, + dd.last_name AS lastName, + r.rating_count AS rating + FROM delivery_order d + LEFT JOIN driver_details dd ON d.user_details_id = dd.user_details_id + LEFT JOIN rating r ON d.delivery_id = r.delivery_id + WHERE CAST(d.start_time AS DATE) = CURRENT_DATE + ORDER BY d.delivery_id DESC +""", nativeQuery = true) + List getDeliveryRecordsToday(); + } diff --git a/src/main/java/com/pentagon/Quicky_Backend/service/DeliveryService.java b/src/main/java/com/pentagon/Quicky_Backend/service/DeliveryService.java index d604f3e..4ceb74a 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/service/DeliveryService.java +++ b/src/main/java/com/pentagon/Quicky_Backend/service/DeliveryService.java @@ -22,4 +22,8 @@ public List getDeliveryRecords() { public List getDeliveriesCount() { return deliveryRepo.getDeliveriesCount(); } + + public List getDeliveryRecordsToday() { + return deliveryRepo.getDeliveryRecordsToday(); + } } From 7cca737af4408d9ead5b73afa1c79db0f4427db8 Mon Sep 17 00:00:00 2001 From: Kaveesha529 Date: Wed, 23 Jul 2025 00:55:49 +0530 Subject: [PATCH 15/28] feat(realTimeDriverLocation): created REST Api for realTimeDriverLocation --- .../controller/DriverLocationController.java | 25 +++++++++++++++++++ .../Quicky_Backend/dto/DriverLocationDto.java | 6 +++++ .../repository/DriverLocationRepo.java | 25 +++++++++++++++++++ .../service/DriverLocationService.java | 19 ++++++++++++++ 4 files changed, 75 insertions(+) create mode 100644 src/main/java/com/pentagon/Quicky_Backend/controller/DriverLocationController.java create mode 100644 src/main/java/com/pentagon/Quicky_Backend/dto/DriverLocationDto.java create mode 100644 src/main/java/com/pentagon/Quicky_Backend/repository/DriverLocationRepo.java create mode 100644 src/main/java/com/pentagon/Quicky_Backend/service/DriverLocationService.java diff --git a/src/main/java/com/pentagon/Quicky_Backend/controller/DriverLocationController.java b/src/main/java/com/pentagon/Quicky_Backend/controller/DriverLocationController.java new file mode 100644 index 0000000..78a01a6 --- /dev/null +++ b/src/main/java/com/pentagon/Quicky_Backend/controller/DriverLocationController.java @@ -0,0 +1,25 @@ +package com.pentagon.Quicky_Backend.controller; + +import com.pentagon.Quicky_Backend.dto.DriverLocationDto; +import com.pentagon.Quicky_Backend.service.DriverLocationService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@CrossOrigin(origins = "http://localhost:5173") +public class DriverLocationController { + + @Autowired + private DriverLocationService driverLocationService; + + @GetMapping("/search-driver-location/{userId}") + public ResponseEntity> getDriverLocation(@PathVariable Integer userId) { + List drivers = driverLocationService.getDriverLocation(userId); + return new ResponseEntity<>(drivers, HttpStatus.OK); + } + +} \ No newline at end of file diff --git a/src/main/java/com/pentagon/Quicky_Backend/dto/DriverLocationDto.java b/src/main/java/com/pentagon/Quicky_Backend/dto/DriverLocationDto.java new file mode 100644 index 0000000..fdeb499 --- /dev/null +++ b/src/main/java/com/pentagon/Quicky_Backend/dto/DriverLocationDto.java @@ -0,0 +1,6 @@ +package com.pentagon.Quicky_Backend.dto; + +public interface DriverLocationDto { + Double getCurrentLatitude(); + Double getCurrentLongitude(); +} diff --git a/src/main/java/com/pentagon/Quicky_Backend/repository/DriverLocationRepo.java b/src/main/java/com/pentagon/Quicky_Backend/repository/DriverLocationRepo.java new file mode 100644 index 0000000..4bcb827 --- /dev/null +++ b/src/main/java/com/pentagon/Quicky_Backend/repository/DriverLocationRepo.java @@ -0,0 +1,25 @@ +package com.pentagon.Quicky_Backend.repository; + +import com.pentagon.Quicky_Backend.entity.DriverLocation; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; +import org.springframework.data.jpa.repository.Query; +import com.pentagon.Quicky_Backend.dto.*; + +import java.util.List; + +@Repository +public interface DriverLocationRepo extends JpaRepository { + + @Query(value = """ + SELECT + dl.current_latitude AS currentLatitude, + dl.current_longitude AS currentLongitude + FROM driver_location dl + WHERE dl.user_id = :userId + ORDER BY dl.driver_location_id + """, nativeQuery = true) + List getDriverLocation(@Param("userId") Integer userId); + +} diff --git a/src/main/java/com/pentagon/Quicky_Backend/service/DriverLocationService.java b/src/main/java/com/pentagon/Quicky_Backend/service/DriverLocationService.java new file mode 100644 index 0000000..1198f9a --- /dev/null +++ b/src/main/java/com/pentagon/Quicky_Backend/service/DriverLocationService.java @@ -0,0 +1,19 @@ +package com.pentagon.Quicky_Backend.service; + +import com.pentagon.Quicky_Backend.dto.DriverLocationDto; +import com.pentagon.Quicky_Backend.repository.DriverLocationRepo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class DriverLocationService { + + @Autowired + private DriverLocationRepo driverLocationRepo; + + public List getDriverLocation(Integer userId) { + return driverLocationRepo.getDriverLocation(userId); + } +} From f8104e9d674fbd50f8f65cb5d2cae485687e6ce2 Mon Sep 17 00:00:00 2001 From: Kaveesha529 Date: Thu, 24 Jul 2025 13:20:29 +0530 Subject: [PATCH 16/28] feat(blacklist): created REST Api for blacklisting drivers --- .../NewRegistrationsController.java | 10 +++++ .../Quicky_Backend/entity/DriverDetails.java | 3 +- .../service/NewRegistrationsService.java | 39 +++++++++---------- 3 files changed, 31 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/pentagon/Quicky_Backend/controller/NewRegistrationsController.java b/src/main/java/com/pentagon/Quicky_Backend/controller/NewRegistrationsController.java index 1c6ec27..8d96a49 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/controller/NewRegistrationsController.java +++ b/src/main/java/com/pentagon/Quicky_Backend/controller/NewRegistrationsController.java @@ -41,4 +41,14 @@ public ResponseEntity rejectDriver(@PathVariable Integer userDetailsId) return new ResponseEntity<>("Driver not rejected", HttpStatus.BAD_REQUEST); } } + + @PostMapping("/driver-profiles/blacklist-driver/{userDetailsId}") + public ResponseEntity blacklistDriver(@PathVariable Integer userDetailsId) { + boolean success = newRegistrationsService.blacklistDriver(userDetailsId); + if (success) { + return new ResponseEntity<>("Driver blacklisted successfully", HttpStatus.OK); + } else { + return new ResponseEntity<>("Driver not blacklisted", HttpStatus.BAD_REQUEST); + } + } } diff --git a/src/main/java/com/pentagon/Quicky_Backend/entity/DriverDetails.java b/src/main/java/com/pentagon/Quicky_Backend/entity/DriverDetails.java index 7898132..28ca88d 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/entity/DriverDetails.java +++ b/src/main/java/com/pentagon/Quicky_Backend/entity/DriverDetails.java @@ -70,7 +70,8 @@ public class DriverDetails { public enum ApprovalStatus { PENDING, APPROVED, - REJECTED + REJECTED, + BLACKLISTED } @Enumerated(EnumType.STRING) diff --git a/src/main/java/com/pentagon/Quicky_Backend/service/NewRegistrationsService.java b/src/main/java/com/pentagon/Quicky_Backend/service/NewRegistrationsService.java index 9f573d4..5de0cff 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/service/NewRegistrationsService.java +++ b/src/main/java/com/pentagon/Quicky_Backend/service/NewRegistrationsService.java @@ -21,32 +21,31 @@ public List getNewRegistrations() { return driverDetailsRepo.findAllPendingRegistrations(); } - public boolean addDriver(Integer userDetailsId) { - Optional optionalNewDriver = driverDetailsRepo.findByUserDetailsId(userDetailsId); - - if (optionalNewDriver.isPresent()) { - DriverDetails newDriver = optionalNewDriver.get(); - newDriver.setApproved(DriverDetails.ApprovalStatus.APPROVED); - newDriver.setRegistrationDate(LocalDate.now()); - driverDetailsRepo.save(newDriver); - + private boolean updateDriverStatus(Integer userDetailsId, DriverDetails.ApprovalStatus status) { + Optional optionalDriver = driverDetailsRepo.findByUserDetailsId(userDetailsId); + + if (optionalDriver.isPresent()) { + DriverDetails driver = optionalDriver.get(); + driver.setApproved(status); + if (status == DriverDetails.ApprovalStatus.APPROVED) { + driver.setRegistrationDate(LocalDate.now()); + } + driverDetailsRepo.save(driver); return true; } - return false; } - public boolean rejectDriver(Integer userDetailsId) { - Optional optionalNewDriver = driverDetailsRepo.findById(userDetailsId); - - if (optionalNewDriver.isPresent()) { - DriverDetails newDriver = optionalNewDriver.get(); - newDriver.setApproved(DriverDetails.ApprovalStatus.REJECTED); - driverDetailsRepo.save(newDriver); + public boolean addDriver(Integer userDetailsId) { + return updateDriverStatus(userDetailsId, DriverDetails.ApprovalStatus.APPROVED); + } - return true; - } + public boolean rejectDriver(Integer userDetailsId) { + return updateDriverStatus(userDetailsId, DriverDetails.ApprovalStatus.REJECTED); + } - return false; + public boolean blacklistDriver(Integer userDetailsId) { + return updateDriverStatus(userDetailsId, DriverDetails.ApprovalStatus.BLACKLISTED); } + } From 8038302ccdf0dd35cb1874592462ca96b287482b Mon Sep 17 00:00:00 2001 From: Kaveesha529 Date: Thu, 24 Jul 2025 20:08:53 +0530 Subject: [PATCH 17/28] feat(blacklist): created REST Api for blacklisting drivers --- .../controller/DriverProfilesController.java | 6 ++++ .../NewRegistrationsController.java | 10 ++++++ .../repository/DriverDetailsRepo.java | 33 +++++++++++++++++++ .../service/DriverProfilesService.java | 4 +++ .../service/NewRegistrationsService.java | 14 +++++--- 5 files changed, 62 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/pentagon/Quicky_Backend/controller/DriverProfilesController.java b/src/main/java/com/pentagon/Quicky_Backend/controller/DriverProfilesController.java index d650300..dfa4299 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/controller/DriverProfilesController.java +++ b/src/main/java/com/pentagon/Quicky_Backend/controller/DriverProfilesController.java @@ -57,4 +57,10 @@ public ResponseEntity> getInactiveDriversCount() { return new ResponseEntity<>(drivers, HttpStatus.OK); } + @GetMapping("/blacklist") + public ResponseEntity> getBlacklist() { + List drivers = driverProfilesService.getBlacklist(); + return new ResponseEntity<>(drivers, HttpStatus.OK); + } + } diff --git a/src/main/java/com/pentagon/Quicky_Backend/controller/NewRegistrationsController.java b/src/main/java/com/pentagon/Quicky_Backend/controller/NewRegistrationsController.java index 8d96a49..0fe3cc9 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/controller/NewRegistrationsController.java +++ b/src/main/java/com/pentagon/Quicky_Backend/controller/NewRegistrationsController.java @@ -51,4 +51,14 @@ public ResponseEntity blacklistDriver(@PathVariable Integer userDetailsI return new ResponseEntity<>("Driver not blacklisted", HttpStatus.BAD_REQUEST); } } + + @PostMapping("/driver-profiles/UnBlacklist/{userDetailsId}") + public ResponseEntity unBlacklistDriver(@PathVariable Integer userDetailsId) { + boolean success = newRegistrationsService.unBlacklistDriver(userDetailsId); + if (success) { + return new ResponseEntity<>("Driver unBlacklisted successfully", HttpStatus.OK); + } else { + return new ResponseEntity<>("Driver not unBlacklisted", HttpStatus.BAD_REQUEST); + } + } } diff --git a/src/main/java/com/pentagon/Quicky_Backend/repository/DriverDetailsRepo.java b/src/main/java/com/pentagon/Quicky_Backend/repository/DriverDetailsRepo.java index 310711c..dc7004c 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/repository/DriverDetailsRepo.java +++ b/src/main/java/com/pentagon/Quicky_Backend/repository/DriverDetailsRepo.java @@ -273,4 +273,37 @@ HAVING MAX(da.end_time) < now() - interval '7 days' """, nativeQuery = true) List countApprovedInactiveDrivers(); + @Query(value = """ + SELECT + dd.user_details_id AS userDetailsId, + dd.first_name AS firstName, + dd.last_name AS lastName, + dd.date_of_birth AS dateOfBirth, + dd.gender AS gender, + dd.home_no AS homeNo, + dd.street_name AS streetName, + dd.city AS city, + dd.district AS district, + dd.license_number AS licenseNumber, + dd.license_front_url AS licenseFrontURL, + dd.license_back_url AS licenseBackURL, + dd.registration_date AS registrationDate, + dd.availability AS availability, + dd.stripe_id AS stripeId, + dd.wallet_balance AS walletBalance, + d.email AS email, + d.mobile_number AS mobileNumber, + COALESCE(SUM(r.rating_count) / NULLIF(COUNT(r.rating_id), 0), 0) AS rating + FROM driver_details dd + JOIN drivers d ON d.user_id = dd.user_id + LEFT JOIN rating r ON r.user_details_id = dd.user_details_id + WHERE dd.approved = 'BLACKLISTED' + GROUP BY dd.user_details_id, dd.first_name, dd.last_name, dd.date_of_birth, dd.gender, + dd.home_no, dd.street_name, dd.city, dd.district, dd.license_number, + dd.license_front_url, dd.license_back_url, dd.registration_date, dd.availability, + dd.stripe_id, dd.wallet_balance, d.email, d.mobile_number + ORDER BY dd.user_details_id + """, nativeQuery = true) + List getBlacklist(); + } \ No newline at end of file diff --git a/src/main/java/com/pentagon/Quicky_Backend/service/DriverProfilesService.java b/src/main/java/com/pentagon/Quicky_Backend/service/DriverProfilesService.java index a375846..f218409 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/service/DriverProfilesService.java +++ b/src/main/java/com/pentagon/Quicky_Backend/service/DriverProfilesService.java @@ -39,4 +39,8 @@ public List getInactiveDrivers() { public List getInactiveDriversCount() { return driverDetailsRepo.countApprovedInactiveDrivers(); } + + public List getBlacklist() { + return driverDetailsRepo.getBlacklist(); + } } diff --git a/src/main/java/com/pentagon/Quicky_Backend/service/NewRegistrationsService.java b/src/main/java/com/pentagon/Quicky_Backend/service/NewRegistrationsService.java index 5de0cff..fb8fce8 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/service/NewRegistrationsService.java +++ b/src/main/java/com/pentagon/Quicky_Backend/service/NewRegistrationsService.java @@ -21,13 +21,13 @@ public List getNewRegistrations() { return driverDetailsRepo.findAllPendingRegistrations(); } - private boolean updateDriverStatus(Integer userDetailsId, DriverDetails.ApprovalStatus status) { + private boolean updateDriverStatus(Integer userDetailsId, DriverDetails.ApprovalStatus status, boolean setRegistrationDate) { Optional optionalDriver = driverDetailsRepo.findByUserDetailsId(userDetailsId); if (optionalDriver.isPresent()) { DriverDetails driver = optionalDriver.get(); driver.setApproved(status); - if (status == DriverDetails.ApprovalStatus.APPROVED) { + if (setRegistrationDate && status == DriverDetails.ApprovalStatus.APPROVED) { driver.setRegistrationDate(LocalDate.now()); } driverDetailsRepo.save(driver); @@ -37,15 +37,19 @@ private boolean updateDriverStatus(Integer userDetailsId, DriverDetails.Approval } public boolean addDriver(Integer userDetailsId) { - return updateDriverStatus(userDetailsId, DriverDetails.ApprovalStatus.APPROVED); + return updateDriverStatus(userDetailsId, DriverDetails.ApprovalStatus.APPROVED, true); } public boolean rejectDriver(Integer userDetailsId) { - return updateDriverStatus(userDetailsId, DriverDetails.ApprovalStatus.REJECTED); + return updateDriverStatus(userDetailsId, DriverDetails.ApprovalStatus.REJECTED, false); } public boolean blacklistDriver(Integer userDetailsId) { - return updateDriverStatus(userDetailsId, DriverDetails.ApprovalStatus.BLACKLISTED); + return updateDriverStatus(userDetailsId, DriverDetails.ApprovalStatus.BLACKLISTED, false); + } + + public boolean unBlacklistDriver(Integer userDetailsId) { + return updateDriverStatus(userDetailsId, DriverDetails.ApprovalStatus.APPROVED, false); } } From 31022d0cbf9c02da756c06abe76e00b4907bf0ab Mon Sep 17 00:00:00 2001 From: HashiruG Date: Fri, 25 Jul 2025 07:51:27 +0530 Subject: [PATCH 18/28] fix(ChurnDriver): correct status string casing to "Not Incentivized" --- .../java/com/pentagon/Quicky_Backend/entity/ChurnDriver.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/pentagon/Quicky_Backend/entity/ChurnDriver.java b/src/main/java/com/pentagon/Quicky_Backend/entity/ChurnDriver.java index cdf6c41..b3e8ed5 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/entity/ChurnDriver.java +++ b/src/main/java/com/pentagon/Quicky_Backend/entity/ChurnDriver.java @@ -33,6 +33,6 @@ public class ChurnDriver { @JoinColumn(name = "driver_id", referencedColumnName = "user_details_id") private DriverDetails driver; - private String status = "not incentivized"; + private String status = "Not Incentivized"; } From ccbc5edfc87da83d2d4a6a84840ceacfea927cce Mon Sep 17 00:00:00 2001 From: HashiruG Date: Sat, 26 Jul 2025 06:18:45 +0530 Subject: [PATCH 19/28] feat: add role and name fields to registration DTO --- .../com/pentagon/Quicky_Backend/dto/RegisterRequestDto.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/pentagon/Quicky_Backend/dto/RegisterRequestDto.java b/src/main/java/com/pentagon/Quicky_Backend/dto/RegisterRequestDto.java index b93ab35..091ade1 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/dto/RegisterRequestDto.java +++ b/src/main/java/com/pentagon/Quicky_Backend/dto/RegisterRequestDto.java @@ -10,4 +10,6 @@ public class RegisterRequestDto { private String username; private String password; + private String role; + private String name; } From 66c12f4b36dee25638897cbcb263047db8cfc043 Mon Sep 17 00:00:00 2001 From: HashiruG Date: Sat, 26 Jul 2025 06:19:28 +0530 Subject: [PATCH 20/28] fix: add missing @Repository annotation in UserRepo --- .../java/com/pentagon/Quicky_Backend/repository/UserRepo.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/pentagon/Quicky_Backend/repository/UserRepo.java b/src/main/java/com/pentagon/Quicky_Backend/repository/UserRepo.java index 49b64e0..b4efc73 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/repository/UserRepo.java +++ b/src/main/java/com/pentagon/Quicky_Backend/repository/UserRepo.java @@ -1,9 +1,11 @@ package com.pentagon.Quicky_Backend.repository; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; import com.pentagon.Quicky_Backend.entity.Admin; +@Repository public interface UserRepo extends JpaRepository { Admin findByUsername(String username); From 524d8abdfeebec00a2ffd8ac76a8320c92985915 Mon Sep 17 00:00:00 2001 From: HashiruG Date: Sat, 26 Jul 2025 06:20:47 +0530 Subject: [PATCH 21/28] feat: add role and name attributes to admin entity --- .../java/com/pentagon/Quicky_Backend/entity/Admin.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/pentagon/Quicky_Backend/entity/Admin.java b/src/main/java/com/pentagon/Quicky_Backend/entity/Admin.java index ddc66b7..4c15b6f 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/entity/Admin.java +++ b/src/main/java/com/pentagon/Quicky_Backend/entity/Admin.java @@ -4,6 +4,7 @@ import java.util.Collections; import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import jakarta.persistence.*; @@ -18,16 +19,19 @@ @NoArgsConstructor @Data @Table(name = "admin") + public class Admin implements UserDetails{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; private String username; private String password; + private String role; + private String name; - @Override + @Override public Collection getAuthorities() { - return Collections.emptyList(); + return Collections.singletonList(new SimpleGrantedAuthority("ROLE_" + role)); } } \ No newline at end of file From 1c3df3cf462c58c6a55f85b6b1a1005f569c7af6 Mon Sep 17 00:00:00 2001 From: HashiruG Date: Sat, 26 Jul 2025 06:21:40 +0530 Subject: [PATCH 22/28] feat: create AdminResponseDto with name, username, and role fields --- .../Quicky_Backend/dto/AdminResponseDto.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/main/java/com/pentagon/Quicky_Backend/dto/AdminResponseDto.java diff --git a/src/main/java/com/pentagon/Quicky_Backend/dto/AdminResponseDto.java b/src/main/java/com/pentagon/Quicky_Backend/dto/AdminResponseDto.java new file mode 100644 index 0000000..bef6c22 --- /dev/null +++ b/src/main/java/com/pentagon/Quicky_Backend/dto/AdminResponseDto.java @@ -0,0 +1,14 @@ +package com.pentagon.Quicky_Backend.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@AllArgsConstructor +@NoArgsConstructor +@Data +public class AdminResponseDto { + private String name; + private String username; + private String role; +} From 59c385ee918bc742d8269f1475aae868fe335fdd Mon Sep 17 00:00:00 2001 From: HashiruG Date: Sat, 26 Jul 2025 06:21:57 +0530 Subject: [PATCH 23/28] feat: add endpoints to view and delete admins in AuthController --- .../controller/AuthController.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/main/java/com/pentagon/Quicky_Backend/controller/AuthController.java b/src/main/java/com/pentagon/Quicky_Backend/controller/AuthController.java index aee8b9b..8cc1356 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/controller/AuthController.java +++ b/src/main/java/com/pentagon/Quicky_Backend/controller/AuthController.java @@ -1,5 +1,7 @@ package com.pentagon.Quicky_Backend.controller; +import java.util.List; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; @@ -7,6 +9,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import com.pentagon.Quicky_Backend.dto.AdminResponseDto; import com.pentagon.Quicky_Backend.dto.ForgotPasswordRequestDto; import com.pentagon.Quicky_Backend.dto.LoginRequestDto; import com.pentagon.Quicky_Backend.dto.LoginResponseDto; @@ -14,6 +17,12 @@ import com.pentagon.Quicky_Backend.dto.ResetPasswordRequestDto; import com.pentagon.Quicky_Backend.service.AuthService; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestParam; + + @RestController @RequestMapping("/auth") public class AuthController { @@ -30,6 +39,17 @@ public ResponseEntity register(@RequestBody RegisterRequestDto registerR return authService.Register(registerRequest); } + @GetMapping("register/view-admins") + public ResponseEntity> getAllAdmins() { + return authService.getAllAdmins(); + } + + @DeleteMapping("/register/delete-admin/{username}") + public ResponseEntity deleteAdmin(@PathVariable String username) { + return authService.deleteAdmin(username); + } + + @PostMapping("/login") public ResponseEntity login(@RequestBody LoginRequestDto loginRequest) { return authService.Login(loginRequest); From 23e85f37cccb5210c5dd2d4fa5a521ac6ad44319 Mon Sep 17 00:00:00 2001 From: HashiruG Date: Sat, 26 Jul 2025 06:24:12 +0530 Subject: [PATCH 24/28] feat: enhance JWT authentication and authorization flow with role management --- .../security/JwtAuthenticationFilter.java | 52 +++++++++++++------ .../security/SecurityConfig.java | 3 +- .../Quicky_Backend/service/AuthService.java | 47 ++++++++++++----- .../Quicky_Backend/service/JwtService.java | 49 ++++++++++++----- 4 files changed, 106 insertions(+), 45 deletions(-) diff --git a/src/main/java/com/pentagon/Quicky_Backend/security/JwtAuthenticationFilter.java b/src/main/java/com/pentagon/Quicky_Backend/security/JwtAuthenticationFilter.java index 13250cd..5de3a28 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/security/JwtAuthenticationFilter.java +++ b/src/main/java/com/pentagon/Quicky_Backend/security/JwtAuthenticationFilter.java @@ -1,48 +1,66 @@ package com.pentagon.Quicky_Backend.security; import java.io.IOException; -import java.util.ArrayList; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; +import org.springframework.security.core.userdetails.UserDetails; import com.pentagon.Quicky_Backend.service.JwtService; +import com.pentagon.Quicky_Backend.service.UserDetailsServiceImpl; +import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import org.springframework.lang.NonNull; + @Component -public class JwtAuthenticationFilter extends OncePerRequestFilter{ +public class JwtAuthenticationFilter extends OncePerRequestFilter { + private final JwtService jwtService; + private final UserDetailsServiceImpl userDetailsService; - private JwtService jwtService; - JwtAuthenticationFilter(JwtService jwtService) { + public JwtAuthenticationFilter(JwtService jwtService, UserDetailsServiceImpl userDetailsService) { this.jwtService = jwtService; + this.userDetailsService = userDetailsService; } - @Override protected void doFilterInternal( - HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) - throws ServletException, IOException{ - String token = request.getHeader("Authorization"); - - if (token != null && token.startsWith("Bearer ")) { - - // Remove "Bearer " prefix - token = token.substring(7); + @NonNull HttpServletRequest request, + @NonNull HttpServletResponse response, + @NonNull FilterChain filterChain) + throws ServletException, IOException { + final String authHeader = request.getHeader("Authorization"); + final String jwt; + final String username; - String username = jwtService.extractEmail(token); + if (authHeader == null || !authHeader.startsWith("Bearer ")) { + filterChain.doFilter(request, response); + return; + } - if (username != null && jwtService.validateToken(token, username)) { + jwt = authHeader.substring(7); + username = jwtService.extractUsername(jwt); - SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(username, null, new ArrayList<>())); + if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { + UserDetails userDetails = this.userDetailsService.loadUserByUsername(username); + if (jwtService.validateToken(jwt, userDetails)) { + UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken( + userDetails, + null, + userDetails.getAuthorities() // This provides the roles + ); + authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + SecurityContextHolder.getContext().setAuthentication(authToken); } } filterChain.doFilter(request, response); - }} \ No newline at end of file + } +} \ No newline at end of file diff --git a/src/main/java/com/pentagon/Quicky_Backend/security/SecurityConfig.java b/src/main/java/com/pentagon/Quicky_Backend/security/SecurityConfig.java index 1501965..306eedb 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/security/SecurityConfig.java +++ b/src/main/java/com/pentagon/Quicky_Backend/security/SecurityConfig.java @@ -33,7 +33,8 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti .cors(withDefaults()) .csrf(csrf -> csrf.disable()) .authorizeHttpRequests((authorize) -> authorize - .requestMatchers("/auth/register", "/auth/login", "/auth/forgot-password", "/auth/reset-password").permitAll() + .requestMatchers( "/auth/login", "/auth/forgot-password", "/auth/reset-password").permitAll() + .requestMatchers("/auth/register").hasRole("SUPER_ADMIN") .anyRequest().authenticated() ) .sessionManagement(sess -> sess.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) diff --git a/src/main/java/com/pentagon/Quicky_Backend/service/AuthService.java b/src/main/java/com/pentagon/Quicky_Backend/service/AuthService.java index caf9ae8..9819339 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/service/AuthService.java +++ b/src/main/java/com/pentagon/Quicky_Backend/service/AuthService.java @@ -1,11 +1,16 @@ package com.pentagon.Quicky_Backend.service; +import java.util.List; +import java.util.stream.Collectors; + + import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; +import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; @@ -14,6 +19,7 @@ import com.pentagon.Quicky_Backend.dto.LoginResponseDto; import com.pentagon.Quicky_Backend.dto.RegisterRequestDto; import com.pentagon.Quicky_Backend.dto.ResetPasswordRequestDto; +import com.pentagon.Quicky_Backend.dto.AdminResponseDto; import com.pentagon.Quicky_Backend.entity.PasswordResetToken; import com.pentagon.Quicky_Backend.entity.Admin; import com.pentagon.Quicky_Backend.exception.InvalidCredentialsException; @@ -54,32 +60,28 @@ public ResponseEntity Register(RegisterRequestDto registerRequest) { Admin user = new Admin(); user.setUsername(registerRequest.getUsername()); user.setPassword(passwordEncoder.encode(registerRequest.getPassword())); + user.setRole(registerRequest.getRole()); + user.setName(registerRequest.getName()); userRepo.save(user); return new ResponseEntity<>("User registered successfully", HttpStatus.CREATED); } public ResponseEntity Login(LoginRequestDto loginRequest) { - - String username = loginRequest.getUsername(); - Admin user = userRepo.findByUsername(username); - if (user == null) { - throw new UserNotFoundException("User not found with username: " + username); - } try { - UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken( - loginRequest.getUsername(), loginRequest.getPassword()); - Authentication authentication = authenticationManager.authenticate(authToken); + Authentication authentication = authenticationManager.authenticate( + new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()) + ); if (authentication.isAuthenticated()) { - String token = jwtService.generateToken(loginRequest.getUsername()); + UserDetails userDetails = (UserDetails) authentication.getPrincipal(); + String token = jwtService.generateToken(userDetails); return new ResponseEntity<>(new LoginResponseDto(token), HttpStatus.OK); } else { - throw new InvalidCredentialsException("Username or password is incorrect"); + throw new InvalidCredentialsException("Authentication failed"); } - - } catch (BadCredentialsException ex) { - throw new InvalidCredentialsException("Username or password is incorrect"); + } catch (BadCredentialsException e) { + throw new InvalidCredentialsException("Invalid username or password"); } } @@ -110,4 +112,21 @@ public ResponseEntity resetPassword(ResetPasswordRequestDto resetPasswor } }; + + public ResponseEntity> getAllAdmins() { + List admins = userRepo.findAll(); + List adminResponseDtos = admins.stream() + .map(admin -> new AdminResponseDto(admin.getName(), admin.getUsername(), admin.getRole())) + .collect(Collectors.toList()); + return new ResponseEntity<>(adminResponseDtos, HttpStatus.OK); + } + + public ResponseEntity deleteAdmin(String username){ + Admin admin = userRepo.findByUsername(username); + if (admin == null) { + throw new UserNotFoundException("User not found with username: " + username); + } + userRepo.delete(admin); + return new ResponseEntity<>("Admin deleted successfully", HttpStatus.OK); + } } diff --git a/src/main/java/com/pentagon/Quicky_Backend/service/JwtService.java b/src/main/java/com/pentagon/Quicky_Backend/service/JwtService.java index 440be13..779e7ae 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/service/JwtService.java +++ b/src/main/java/com/pentagon/Quicky_Backend/service/JwtService.java @@ -6,10 +6,16 @@ import io.jsonwebtoken.security.Keys; import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Service; import javax.crypto.SecretKey; import java.util.Date; +import java.util.HashMap; +import java.util.stream.Collectors; +import java.util.List; +import java.util.Map; @Service public class JwtService { @@ -17,25 +23,35 @@ public class JwtService { @Value("${jwt.secret}") private String SECRET; - public String generateToken(String email){ + /** + * Generates a JWT including user roles as a custom claim. + * @param userDetails The user details object from which to create the token. + * @return A signed JWT string. + */ + public String generateToken(UserDetails userDetails) { + Map claims = new HashMap<>(); + + // Extract roles and add them to the "roles" claim + List roles = userDetails.getAuthorities().stream() + .map(GrantedAuthority::getAuthority) + .collect(Collectors.toList()); + claims.put("roles", roles); - return Jwts.builder() - .subject(email) - .issuedAt(new Date()) - .expiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 24)) + return Jwts.builder() + .claims(claims) + .subject(userDetails.getUsername()) + .issuedAt(new Date(System.currentTimeMillis())) + .expiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 24)) // 24 hours .signWith(getSigningKey(), Jwts.SIG.HS256) .compact(); - } private SecretKey getSigningKey() { - return Keys.hmacShaKeyFor(Decoders.BASE64.decode(SECRET)); + byte[] keyBytes = Decoders.BASE64.decode(SECRET); + return Keys.hmacShaKeyFor(keyBytes); } private Claims parseClaims(String token) { - if (token == null || token.trim().isEmpty()) { - throw new IllegalArgumentException("JWT token is missing"); - } return Jwts.parser() .verifyWith(getSigningKey()) .build() @@ -43,7 +59,7 @@ private Claims parseClaims(String token) { .getPayload(); } - public String extractEmail(String token) { + public String extractUsername(String token) { return parseClaims(token).getSubject(); } @@ -55,7 +71,14 @@ private boolean isTokenExpired(String token) { return extractExpiration(token).before(new Date()); } - public boolean validateToken(String token, String email) { - return (email.equals(extractEmail(token)) && !isTokenExpired(token)); + /** + * Validates the token against the UserDetails. + * @param token The JWT token. + * @param userDetails The user details from the database. + * @return True if the token is valid, false otherwise. + */ + public boolean validateToken(String token, UserDetails userDetails) { + final String username = extractUsername(token); + return (username.equals(userDetails.getUsername()) && !isTokenExpired(token)); } } \ No newline at end of file From a49e4978b36ce6b01702854b0cec1faee0dd100c Mon Sep 17 00:00:00 2001 From: HashiruG Date: Sat, 26 Jul 2025 06:25:50 +0530 Subject: [PATCH 25/28] refactor: clean up unused imports --- .../controller/AuthController.java | 5 +- .../controller/DeliveryController.java | 1 - .../Quicky_Backend/entity/CommissionRate.java | 2 - .../repository/DeliveryRepo.java | 83 +++++++++---------- .../service/DeliveryService.java | 1 - 5 files changed, 42 insertions(+), 50 deletions(-) diff --git a/src/main/java/com/pentagon/Quicky_Backend/controller/AuthController.java b/src/main/java/com/pentagon/Quicky_Backend/controller/AuthController.java index 8cc1356..421cc93 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/controller/AuthController.java +++ b/src/main/java/com/pentagon/Quicky_Backend/controller/AuthController.java @@ -20,8 +20,6 @@ import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestParam; - @RestController @RequestMapping("/auth") @@ -47,8 +45,7 @@ public ResponseEntity> getAllAdmins() { @DeleteMapping("/register/delete-admin/{username}") public ResponseEntity deleteAdmin(@PathVariable String username) { return authService.deleteAdmin(username); - } - + } @PostMapping("/login") public ResponseEntity login(@RequestBody LoginRequestDto loginRequest) { diff --git a/src/main/java/com/pentagon/Quicky_Backend/controller/DeliveryController.java b/src/main/java/com/pentagon/Quicky_Backend/controller/DeliveryController.java index 50f1023..a8c176d 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/controller/DeliveryController.java +++ b/src/main/java/com/pentagon/Quicky_Backend/controller/DeliveryController.java @@ -2,7 +2,6 @@ import com.pentagon.Quicky_Backend.dto.DeliveriesCountDto; import com.pentagon.Quicky_Backend.dto.DeliveryRecordsDto; -import com.pentagon.Quicky_Backend.dto.DriverProfilesDto; import com.pentagon.Quicky_Backend.service.DeliveryService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; diff --git a/src/main/java/com/pentagon/Quicky_Backend/entity/CommissionRate.java b/src/main/java/com/pentagon/Quicky_Backend/entity/CommissionRate.java index bfc106a..b78c0b9 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/entity/CommissionRate.java +++ b/src/main/java/com/pentagon/Quicky_Backend/entity/CommissionRate.java @@ -1,8 +1,6 @@ package com.pentagon.Quicky_Backend.entity; -import java.time.LocalDate; import java.time.LocalDateTime; -import java.util.Date; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; diff --git a/src/main/java/com/pentagon/Quicky_Backend/repository/DeliveryRepo.java b/src/main/java/com/pentagon/Quicky_Backend/repository/DeliveryRepo.java index 7e50a9f..3379498 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/repository/DeliveryRepo.java +++ b/src/main/java/com/pentagon/Quicky_Backend/repository/DeliveryRepo.java @@ -3,7 +3,6 @@ import com.pentagon.Quicky_Backend.dto.DeliveriesCountDto; import com.pentagon.Quicky_Backend.dto.DeliveryRecordsDto; import com.pentagon.Quicky_Backend.entity.DeliveryOrder; -import com.pentagon.Quicky_Backend.entity.DriverDetails; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; @@ -14,53 +13,53 @@ public interface DeliveryRepo extends JpaRepository { @Query(value = """ - SELECT - d.delivery_id AS deliveryId, - d.delivery_fee AS deliveryFee, - d.pick_up_location AS pickupLocation, - d.drop_off_location AS dropOffLocation, - d.delivery_status AS deliveryStatus, - CAST(d.start_time AS DATE) AS deliveryDate, - dd.first_name AS firstName, - dd.last_name AS lastName, - r.rating_count AS rating - FROM delivery_order d - LEFT JOIN driver_details dd ON d.user_details_id = dd.user_details_id - LEFT JOIN rating r ON d.delivery_id = r.delivery_id - ORDER BY d.delivery_id DESC -""", nativeQuery = true) + SELECT + d.delivery_id AS deliveryId, + d.delivery_fee AS deliveryFee, + d.pick_up_location AS pickupLocation, + d.drop_off_location AS dropOffLocation, + d.delivery_status AS deliveryStatus, + CAST(d.start_time AS DATE) AS deliveryDate, + dd.first_name AS firstName, + dd.last_name AS lastName, + r.rating_count AS rating + FROM delivery_order d + LEFT JOIN driver_details dd ON d.user_details_id = dd.user_details_id + LEFT JOIN rating r ON d.delivery_id = r.delivery_id + ORDER BY d.delivery_id DESC + """, nativeQuery = true) List getDeliveryRecords(); @Query(value = """ - SELECT - CAST(d.start_time AS DATE) AS deliveryDate, - COUNT(d.delivery_id) AS deliveriesCount - FROM - delivery_order d - GROUP BY - CAST(d.start_time AS DATE) - ORDER BY - deliveryDate - """, nativeQuery = true) + SELECT + CAST(d.start_time AS DATE) AS deliveryDate, + COUNT(d.delivery_id) AS deliveriesCount + FROM + delivery_order d + GROUP BY + CAST(d.start_time AS DATE) + ORDER BY + deliveryDate + """, nativeQuery = true) List getDeliveriesCount(); @Query(value = """ - SELECT - d.delivery_id AS deliveryId, - d.delivery_fee AS deliveryFee, - d.pick_up_location AS pickupLocation, - d.drop_off_location AS dropOffLocation, - d.delivery_status AS deliveryStatus, - CAST(d.start_time AS DATE) AS deliveryDate, - dd.first_name AS firstName, - dd.last_name AS lastName, - r.rating_count AS rating - FROM delivery_order d - LEFT JOIN driver_details dd ON d.user_details_id = dd.user_details_id - LEFT JOIN rating r ON d.delivery_id = r.delivery_id - WHERE CAST(d.start_time AS DATE) = CURRENT_DATE - ORDER BY d.delivery_id DESC -""", nativeQuery = true) + SELECT + d.delivery_id AS deliveryId, + d.delivery_fee AS deliveryFee, + d.pick_up_location AS pickupLocation, + d.drop_off_location AS dropOffLocation, + d.delivery_status AS deliveryStatus, + CAST(d.start_time AS DATE) AS deliveryDate, + dd.first_name AS firstName, + dd.last_name AS lastName, + r.rating_count AS rating + FROM delivery_order d + LEFT JOIN driver_details dd ON d.user_details_id = dd.user_details_id + LEFT JOIN rating r ON d.delivery_id = r.delivery_id + WHERE CAST(d.start_time AS DATE) = CURRENT_DATE + ORDER BY d.delivery_id DESC + """, nativeQuery = true) List getDeliveryRecordsToday(); } diff --git a/src/main/java/com/pentagon/Quicky_Backend/service/DeliveryService.java b/src/main/java/com/pentagon/Quicky_Backend/service/DeliveryService.java index 4ceb74a..91389d9 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/service/DeliveryService.java +++ b/src/main/java/com/pentagon/Quicky_Backend/service/DeliveryService.java @@ -3,7 +3,6 @@ import com.pentagon.Quicky_Backend.dto.DeliveriesCountDto; import com.pentagon.Quicky_Backend.dto.DeliveryRecordsDto; import com.pentagon.Quicky_Backend.repository.DeliveryRepo; -import com.pentagon.Quicky_Backend.repository.DriverDetailsRepo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; From 16ba7562f203a6ca6f08b3feb45b92d767b3352f Mon Sep 17 00:00:00 2001 From: HashiruG Date: Mon, 28 Jul 2025 11:00:23 +0530 Subject: [PATCH 26/28] fix: update query to get churn features --- .../repository/DriverDetailsRepo.java | 279 +++++++++--------- 1 file changed, 140 insertions(+), 139 deletions(-) diff --git a/src/main/java/com/pentagon/Quicky_Backend/repository/DriverDetailsRepo.java b/src/main/java/com/pentagon/Quicky_Backend/repository/DriverDetailsRepo.java index 310711c..4683fc4 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/repository/DriverDetailsRepo.java +++ b/src/main/java/com/pentagon/Quicky_Backend/repository/DriverDetailsRepo.java @@ -116,161 +116,162 @@ public interface DriverDetailsRepo extends JpaRepository List countApprovedDriversByRegistrationDate(); @Query(value = """ - SELECT - dd.user_details_id AS userDetailsId, - dd.first_name AS firstName, - dd.last_name AS lastName, - dd.date_of_birth AS dateOfBirth, - dd.gender AS gender, - dd.home_no AS homeNo, - dd.street_name AS streetName, - dd.city AS city, - dd.district AS district, - dd.license_number AS licenseNumber, - dd.license_front_url AS licenseFrontURL, - dd.license_back_url AS licenseBackURL, - dd.registration_date AS registrationDate, - dd.availability AS availability, - dd.stripe_id AS stripeId, - dd.wallet_balance AS walletBalance, - d.email AS email, - d.mobile_number AS mobileNumber, - COALESCE(SUM(r.rating_count) / NULLIF(COUNT(r.rating_id), 0), 0) AS rating, - COALESCE(SUM(e.delivery_charge), 0) AS earnings - FROM - driver_details dd - JOIN - drivers d ON dd.user_id = d.user_id - LEFT JOIN - earning e ON dd.user_details_id = e.driver_id - LEFT JOIN - delivery_order o ON e.delivery_id = o.delivery_id - LEFT JOIN - rating r ON o.delivery_id = r.delivery_id - WHERE - dd.approved = 'APPROVED' - AND DATE(e.created_at) = CURRENT_DATE - GROUP BY - dd.user_details_id, dd.first_name, dd.last_name, dd.date_of_birth, dd.gender, - dd.home_no, dd.street_name, dd.city, dd.district, dd.license_number, - dd.license_front_url, dd.license_back_url, dd.registration_date, dd.availability, - dd.stripe_id, dd.wallet_balance, d.email, d.mobile_number - ORDER BY - earnings DESC - """, nativeQuery = true) + SELECT + dd.user_details_id AS userDetailsId, + dd.first_name AS firstName, + dd.last_name AS lastName, + dd.date_of_birth AS dateOfBirth, + dd.gender AS gender, + dd.home_no AS homeNo, + dd.street_name AS streetName, + dd.city AS city, + dd.district AS district, + dd.license_number AS licenseNumber, + dd.license_front_url AS licenseFrontURL, + dd.license_back_url AS licenseBackURL, + dd.registration_date AS registrationDate, + dd.availability AS availability, + dd.stripe_id AS stripeId, + dd.wallet_balance AS walletBalance, + d.email AS email, + d.mobile_number AS mobileNumber, + COALESCE(SUM(r.rating_count) / NULLIF(COUNT(r.rating_id), 0), 0) AS rating, + COALESCE(SUM(e.delivery_charge), 0) AS earnings + FROM + driver_details dd + JOIN + drivers d ON dd.user_id = d.user_id + LEFT JOIN + earning e ON dd.user_details_id = e.driver_id + LEFT JOIN + delivery_order o ON e.delivery_id = o.delivery_id + LEFT JOIN + rating r ON o.delivery_id = r.delivery_id + WHERE + dd.approved = 'APPROVED' + AND DATE(e.created_at) = CURRENT_DATE + GROUP BY + dd.user_details_id, dd.first_name, dd.last_name, dd.date_of_birth, dd.gender, + dd.home_no, dd.street_name, dd.city, dd.district, dd.license_number, + dd.license_front_url, dd.license_back_url, dd.registration_date, dd.availability, + dd.stripe_id, dd.wallet_balance, d.email, d.mobile_number + ORDER BY + earnings DESC + """, nativeQuery = true) List findApprovedDriversWithEarningsToday(); // Churn feature query @Query(value = """ WITH driver_activity AS ( - SELECT - d.user_details_id, - MAX(CASE WHEN deo.delivery_status = 'Completed' THEN deo.completion_time ELSE NULL END) AS last_completed_trip, - COUNT(DISTINCT CASE WHEN deo.delivery_status = 'Completed' AND deo.completion_time >= NOW() - INTERVAL '30 day' THEN deo.delivery_id ELSE NULL END) AS completed_deliveries_last_30_days, - SUM(CASE WHEN deo.delivery_status = 'Completed' AND deo.completion_time >= NOW() - INTERVAL '30 day' THEN e.driver_charge ELSE 0 END) AS total_earnings_last_30_days - FROM - driver_details d - LEFT JOIN - delivery_order deo ON d.user_details_id = deo.user_details_id - LEFT JOIN - earning e ON deo.delivery_id = e.delivery_id - GROUP BY - d.user_details_id - ), - driver_ratings AS ( - - SELECT - r.user_details_id, - AVG(r.rating_count) AS avg_rating_last_30_days - FROM - rating r - JOIN - delivery_order deo ON r.delivery_id = deo.delivery_id - WHERE - deo.completion_time >= NOW() - INTERVAL '30 day' - GROUP BY - r.user_details_id - ) - SELECT - d.user_details_id AS driverId, - EXTRACT(DAY FROM NOW() - da.last_completed_trip) AS days_since_last_trip, - COALESCE(da.completed_deliveries_last_30_days, 0) AS completed_deliveries_last_30_days, - COALESCE(dr.avg_rating_last_30_days, 0) AS avg_rating_last_30_days, - COALESCE(da.total_earnings_last_30_days, 0) AS total_earnings_last_30_days, - d.wallet_balance AS wallet_balance, - EXTRACT(DAY FROM NOW() - d.registration_date) AS tenure_in_days + d.user_details_id, + MAX(CASE WHEN deo.delivery_status = 'Completed' THEN deo.time_stamp ELSE NULL END) AS last_completed_trip, + COUNT(DISTINCT CASE WHEN deo.delivery_status = 'Completed' AND deo.time_stamp >= NOW() - INTERVAL '30 day' THEN deo.delivery_id ELSE NULL END) AS completed_deliveries_last_30_days, + SUM(CASE WHEN deo.delivery_status = 'Completed' AND deo.time_stamp >= NOW() - INTERVAL '30 day' THEN e.driver_charge ELSE 0 END) AS total_earnings_last_30_days FROM driver_details d LEFT JOIN - driver_activity da ON d.user_details_id = da.user_details_id + delivery_order deo ON d.user_details_id = deo.user_details_id LEFT JOIN - driver_ratings dr ON d.user_details_id = dr.user_details_id - """, nativeQuery = true) + earning e ON deo.delivery_id = e.delivery_id + GROUP BY + d.user_details_id + ), + driver_ratings AS ( + SELECT + r.user_details_id, + AVG(r.rating_count) AS avg_rating_last_30_days + FROM + rating r + JOIN + delivery_order deo ON r.delivery_id = deo.delivery_id + WHERE + deo.time_stamp >= NOW() - INTERVAL '30 day' + GROUP BY + r.user_details_id + ) + SELECT + d.user_details_id AS driverId, + COALESCE(EXTRACT(DAY FROM NOW() - da.last_completed_trip), 0) AS days_since_last_trip, + COALESCE(da.completed_deliveries_last_30_days, 0) AS completed_deliveries_last_30_days, + COALESCE(dr.avg_rating_last_30_days, 0) AS avg_rating_last_30_days, + COALESCE(da.total_earnings_last_30_days, 0) AS total_earnings_last_30_days, + d.wallet_balance AS wallet_balance, + EXTRACT(DAY FROM NOW() - d.registration_date) AS tenure_in_days + FROM + driver_details d + INNER JOIN + driver_activity da ON d.user_details_id = da.user_details_id + LEFT JOIN + driver_ratings dr ON d.user_details_id = dr.user_details_id + WHERE + da.last_completed_trip IS NOT NULL; + + """, nativeQuery = true) List getDriverFeaturesForChurnPrediction(); @Query(value = """ - SELECT - dd.user_details_id AS userDetailsId, - dd.first_name AS firstName, - dd.last_name AS lastName, - dd.date_of_birth AS dateOfBirth, - dd.gender AS gender, - dd.home_no AS homeNo, - dd.street_name AS streetName, - dd.city AS city, - dd.district AS district, - dd.license_number AS licenseNumber, - dd.license_front_url AS licenseFrontURL, - dd.license_back_url AS licenseBackURL, - dd.registration_date AS registrationDate, - dd.availability AS availability, - dd.stripe_id AS stripeId, - dd.wallet_balance AS walletBalance, - d.email AS email, - d.mobile_number AS mobileNumber, - COALESCE(SUM(r.rating_count) / NULLIF(COUNT(r.rating_id), 0), 0) AS rating - FROM driver_details dd - JOIN drivers d ON d.user_id = dd.user_id - LEFT JOIN rating r ON r.user_details_id = dd.user_details_id - WHERE dd.approved = 'APPROVED' - AND d.user_id IN ( - SELECT da.user_id - FROM driver_availability da - GROUP BY da.user_id - HAVING MAX(da.end_time) < now() - interval '7 days' - ) - GROUP BY dd.user_details_id, dd.first_name, dd.last_name, dd.date_of_birth, dd.gender, - dd.home_no, dd.street_name, dd.city, dd.district, dd.license_number, - dd.license_front_url, dd.license_back_url, dd.registration_date, dd.availability, - dd.stripe_id, dd.wallet_balance, d.email, d.mobile_number - ORDER BY dd.user_details_id -""", nativeQuery = true) + SELECT + dd.user_details_id AS userDetailsId, + dd.first_name AS firstName, + dd.last_name AS lastName, + dd.date_of_birth AS dateOfBirth, + dd.gender AS gender, + dd.home_no AS homeNo, + dd.street_name AS streetName, + dd.city AS city, + dd.district AS district, + dd.license_number AS licenseNumber, + dd.license_front_url AS licenseFrontURL, + dd.license_back_url AS licenseBackURL, + dd.registration_date AS registrationDate, + dd.availability AS availability, + dd.stripe_id AS stripeId, + dd.wallet_balance AS walletBalance, + d.email AS email, + d.mobile_number AS mobileNumber, + COALESCE(SUM(r.rating_count) / NULLIF(COUNT(r.rating_id), 0), 0) AS rating + FROM driver_details dd + JOIN drivers d ON d.user_id = dd.user_id + LEFT JOIN rating r ON r.user_details_id = dd.user_details_id + WHERE dd.approved = 'APPROVED' + AND d.user_id IN ( + SELECT da.user_id + FROM driver_availability da + GROUP BY da.user_id + HAVING MAX(da.end_time) < now() - interval '7 days' + ) + GROUP BY dd.user_details_id, dd.first_name, dd.last_name, dd.date_of_birth, dd.gender, + dd.home_no, dd.street_name, dd.city, dd.district, dd.license_number, + dd.license_front_url, dd.license_back_url, dd.registration_date, dd.availability, + dd.stripe_id, dd.wallet_balance, d.email, d.mobile_number + ORDER BY dd.user_details_id + """, nativeQuery = true) List findApprovedInactiveDrivers(); @Query(value = """ - SELECT - COUNT(*) FILTER ( - WHERE d.user_id IN ( - SELECT da.user_id - FROM driver_availability da - GROUP BY da.user_id - HAVING MAX(da.end_time) < now() - interval '7 days' - ) - ) AS inactiveDriversCount, - - COUNT(*) FILTER ( - WHERE d.user_id NOT IN ( - SELECT da.user_id - FROM driver_availability da - GROUP BY da.user_id - HAVING MAX(da.end_time) < now() - interval '7 days' - ) - ) AS activeDriversCount - FROM driver_details dd - JOIN drivers d ON d.user_id = dd.user_id - WHERE dd.approved = 'APPROVED' -""", nativeQuery = true) + SELECT + COUNT(*) FILTER ( + WHERE d.user_id IN ( + SELECT da.user_id + FROM driver_availability da + GROUP BY da.user_id + HAVING MAX(da.end_time) < now() - interval '7 days' + ) + ) AS inactiveDriversCount, + + COUNT(*) FILTER ( + WHERE d.user_id NOT IN ( + SELECT da.user_id + FROM driver_availability da + GROUP BY da.user_id + HAVING MAX(da.end_time) < now() - interval '7 days' + ) + ) AS activeDriversCount + FROM driver_details dd + JOIN drivers d ON d.user_id = dd.user_id + WHERE dd.approved = 'APPROVED' + """, nativeQuery = true) List countApprovedInactiveDrivers(); } \ No newline at end of file From 03b4a04b5197e53e7383495ee754df1686b8b4cc Mon Sep 17 00:00:00 2001 From: HashiruG Date: Mon, 28 Jul 2025 14:19:37 +0530 Subject: [PATCH 27/28] fix: fix deployment issues --- pom.xml | 254 +++++++++--------- .../controller/PayOutController.java | 4 +- .../Quicky_Backend/dto/PayOutResponseDto.java | 2 +- .../Quicky_Backend/service/PayOutService.java | 8 +- 4 files changed, 138 insertions(+), 130 deletions(-) diff --git a/pom.xml b/pom.xml index 7d38123..4cc54b6 100644 --- a/pom.xml +++ b/pom.xml @@ -1,130 +1,138 @@ - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 3.4.3 - - - com.pentagon - Quicky_Backend - 0.0.1-SNAPSHOT - Quicky_Backend - Backend of the Quicky project - - - - - - - - - - - - - - - 17 - - - - org.springframework.boot - spring-boot-starter-data-jpa - - - org.springframework.boot - spring-boot-starter-security - - - org.springframework.boot - spring-boot-starter-web - + - - org.springframework.boot - spring-boot-devtools - runtime - true - - - org.postgresql - postgresql - runtime - - - com.stripe - stripe-java - 24.9.0 - - - org.projectlombok - lombok - true - - - org.springframework.boot - spring-boot-starter-test - test - - - org.springframework.security - spring-security-test - test - + 4.0.0 - - io.jsonwebtoken - jjwt-api - 0.12.6 - - - io.jsonwebtoken - jjwt-impl - 0.12.6 - runtime - - - io.jsonwebtoken - jjwt-jackson - 0.12.6 - runtime - - + org.springframework.boot - spring-boot-starter-mail - - + spring-boot-starter-parent + 3.4.3 + + - - - - org.apache.maven.plugins - maven-compiler-plugin - - - - org.projectlombok - lombok - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - org.projectlombok - lombok - - - - - - + com.pentagon + Quicky_Backend + 0.0.1-SNAPSHOT + Quicky_Backend + Backend of the Quicky project + + + 17 + + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-mail + + + org.springframework.boot + spring-boot-devtools + runtime + true + + + + + org.postgresql + postgresql + runtime + + + + + com.stripe + stripe-java + 24.9.0 + + + + + io.jsonwebtoken + jjwt-api + 0.12.6 + + + io.jsonwebtoken + jjwt-impl + 0.12.6 + runtime + + + io.jsonwebtoken + jjwt-jackson + 0.12.6 + runtime + + + + + org.projectlombok + lombok + 1.18.32 + provided + + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.security + spring-security-test + test + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + org.projectlombok + lombok + 1.18.32 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + org.projectlombok + lombok + + + + + + diff --git a/src/main/java/com/pentagon/Quicky_Backend/controller/PayOutController.java b/src/main/java/com/pentagon/Quicky_Backend/controller/PayOutController.java index 5d9fad0..1b18f93 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/controller/PayOutController.java +++ b/src/main/java/com/pentagon/Quicky_Backend/controller/PayOutController.java @@ -11,7 +11,7 @@ import org.springframework.web.bind.annotation.RestController; import com.pentagon.Quicky_Backend.dto.PayOutRequestDto; -import com.pentagon.Quicky_Backend.dto.PayoutResponseDto; +import com.pentagon.Quicky_Backend.dto.PayOutResponseDto; import com.pentagon.Quicky_Backend.service.PayOutService; import org.springframework.web.bind.annotation.GetMapping; @@ -29,7 +29,7 @@ public ResponseEntity acceptPayout(@RequestBody PayOutRequestDto payOutR } @GetMapping("/get-payouts") - public ResponseEntity> getPayouts() { + public ResponseEntity> getPayouts() { return payOutService.getPayouts(); } diff --git a/src/main/java/com/pentagon/Quicky_Backend/dto/PayOutResponseDto.java b/src/main/java/com/pentagon/Quicky_Backend/dto/PayOutResponseDto.java index c7c959e..9c6c9a1 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/dto/PayOutResponseDto.java +++ b/src/main/java/com/pentagon/Quicky_Backend/dto/PayOutResponseDto.java @@ -10,7 +10,7 @@ @AllArgsConstructor @NoArgsConstructor @Data -public class PayoutResponseDto { +public class PayOutResponseDto { private Integer payoutId; private double amount; private String status; diff --git a/src/main/java/com/pentagon/Quicky_Backend/service/PayOutService.java b/src/main/java/com/pentagon/Quicky_Backend/service/PayOutService.java index 8c175c6..d398666 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/service/PayOutService.java +++ b/src/main/java/com/pentagon/Quicky_Backend/service/PayOutService.java @@ -11,7 +11,7 @@ import org.springframework.transaction.annotation.Transactional; import com.pentagon.Quicky_Backend.dto.PayOutRequestDto; -import com.pentagon.Quicky_Backend.dto.PayoutResponseDto; +import com.pentagon.Quicky_Backend.dto.PayOutResponseDto; import com.pentagon.Quicky_Backend.entity.DriverDetails; import com.pentagon.Quicky_Backend.entity.PayOutRequests; @@ -84,11 +84,11 @@ public ResponseEntity processPayOuts(PayOutRequestDto payOutRequestDto, } } - public ResponseEntity> getPayouts(){ + public ResponseEntity> getPayouts(){ List payOutRequests = payOutRepo.findAll(); - List payoutResponses = new ArrayList<>(); + List payoutResponses = new ArrayList<>(); for (PayOutRequests request : payOutRequests) { - PayoutResponseDto payoutResponse = new PayoutResponseDto( + PayOutResponseDto payoutResponse = new PayOutResponseDto( request.getPayoutId(), request.getAmount(), request.getStatus(), From 46404e23085c056dc65a852074731a2214f5bde2 Mon Sep 17 00:00:00 2001 From: Kaveesha529 Date: Mon, 28 Jul 2025 17:33:13 +0530 Subject: [PATCH 28/28] fix:add vehicle details to tables --- .../Quicky_Backend/dto/DriverProfilesDto.java | 8 + .../dto/NewRegistrationsDto.java | 8 + .../repository/DriverDetailsRepo.java | 345 ++++++++++++------ 3 files changed, 245 insertions(+), 116 deletions(-) diff --git a/src/main/java/com/pentagon/Quicky_Backend/dto/DriverProfilesDto.java b/src/main/java/com/pentagon/Quicky_Backend/dto/DriverProfilesDto.java index c396103..669196f 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/dto/DriverProfilesDto.java +++ b/src/main/java/com/pentagon/Quicky_Backend/dto/DriverProfilesDto.java @@ -22,4 +22,12 @@ public interface DriverProfilesDto { String getEmail(); String getMobileNumber(); Double getRating(); + Integer getVehicleId(); + String getNumberPlate(); + String getVehicleType(); + String getVehicleFrontURL(); + String getVehicleBackURL(); + String getVehicleSideURL(); + String getVehicleRevenueLicenseURL(); + String getVehicleBookURL(); } diff --git a/src/main/java/com/pentagon/Quicky_Backend/dto/NewRegistrationsDto.java b/src/main/java/com/pentagon/Quicky_Backend/dto/NewRegistrationsDto.java index c82e88e..15ada32 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/dto/NewRegistrationsDto.java +++ b/src/main/java/com/pentagon/Quicky_Backend/dto/NewRegistrationsDto.java @@ -17,4 +17,12 @@ public interface NewRegistrationsDto { String getLicenseBackURL(); String getEmail(); String getMobileNumber(); + Integer getVehicleId(); + String getNumberPlate(); + String getVehicleType(); + String getVehicleFrontURL(); + String getVehicleBackURL(); + String getVehicleSideURL(); + String getVehicleRevenueLicenseURL(); + String getVehicleBookURL(); } diff --git a/src/main/java/com/pentagon/Quicky_Backend/repository/DriverDetailsRepo.java b/src/main/java/com/pentagon/Quicky_Backend/repository/DriverDetailsRepo.java index dc7004c..f74503a 100644 --- a/src/main/java/com/pentagon/Quicky_Backend/repository/DriverDetailsRepo.java +++ b/src/main/java/com/pentagon/Quicky_Backend/repository/DriverDetailsRepo.java @@ -19,95 +19,147 @@ public interface DriverDetailsRepo extends JpaRepository Optional findByUserDetailsId(Integer userDetailsId); @Query(value = """ - SELECT - dd.user_details_id AS userDetailsId, - dd.first_name AS firstName, - dd.last_name AS lastName, - dd.date_of_birth AS dateOfBirth, - dd.gender AS gender, - dd.home_no AS homeNo, - dd.street_name AS streetName, - dd.city AS city, - dd.district AS district, - dd.license_number AS licenseNumber, - dd.license_front_url AS licenseFrontURL, - dd.license_back_url AS licenseBackURL, - d.email AS email, - d.mobile_number AS mobileNumber - FROM driver_details dd - LEFT JOIN drivers d ON dd.user_id = d.user_id - WHERE dd.approved = 'PENDING' - ORDER BY dd.user_details_id - """, nativeQuery = true) + SELECT + dd.user_details_id AS userDetailsId, + dd.first_name AS firstName, + dd.last_name AS lastName, + dd.date_of_birth AS dateOfBirth, + dd.gender AS gender, + dd.home_no AS homeNo, + dd.street_name AS streetName, + dd.city AS city, + dd.district AS district, + dd.license_number AS licenseNumber, + dd.license_front_url AS licenseFrontURL, + dd.license_back_url AS licenseBackURL, + d.email AS email, + d.mobile_number AS mobileNumber, + v.vehicle_id AS vehicleId, + v.number_plate AS numberPlate, + v.vehicle_type AS vehicleType, + v.vehicle_front_url AS vehicleFrontURL, + v.vehicle_back_url AS vehicleBackURL, + v.vehicle_side_url AS vehicleSideURL, + v.vehicle_revenue_license_url AS vehicleRevenueLicenseURL, + v.vehicle_book_url AS vehicleBookURL + FROM driver_details dd + LEFT JOIN drivers d ON dd.user_id = d.user_id + LEFT JOIN vehicle v ON dd.user_id = v.user_id + WHERE dd.approved = 'PENDING' + ORDER BY dd.user_details_id +""", nativeQuery = true) List findAllPendingRegistrations(); + @Query(value = """ - SELECT - dd.user_details_id AS userDetailsId, - dd.first_name AS firstName, - dd.last_name AS lastName, - dd.date_of_birth AS dateOfBirth, - dd.gender AS gender, - dd.home_no AS homeNo, - dd.street_name AS streetName, - dd.city AS city, - dd.district AS district, - dd.license_number AS licenseNumber, - dd.license_front_url AS licenseFrontURL, - dd.license_back_url AS licenseBackURL, - dd.registration_date AS registrationDate, - dd.availability AS availability, - dd.stripe_id AS stripeId, - dd.wallet_balance AS walletBalance, - d.email AS email, - d.mobile_number AS mobileNumber, - COALESCE(SUM(r.rating_count) / NULLIF(COUNT(r.rating_id), 0), 0) AS rating - FROM driver_details dd - JOIN drivers d ON d.user_id = dd.user_id - LEFT JOIN rating r ON r.user_details_id = dd.user_details_id - WHERE dd.approved = 'APPROVED' - GROUP BY dd.user_details_id, dd.first_name, dd.last_name, dd.date_of_birth, dd.gender, - dd.home_no, dd.street_name, dd.city, dd.district, dd.license_number, - dd.license_front_url, dd.license_back_url, dd.registration_date, dd.availability, - dd.stripe_id, dd.wallet_balance, d.email, d.mobile_number - ORDER BY dd.user_details_id - """, nativeQuery = true) + SELECT + dd.user_details_id AS userDetailsId, + dd.first_name AS firstName, + dd.last_name AS lastName, + dd.date_of_birth AS dateOfBirth, + dd.gender AS gender, + dd.home_no AS homeNo, + dd.street_name AS streetName, + dd.city AS city, + dd.district AS district, + dd.license_number AS licenseNumber, + dd.license_front_url AS licenseFrontURL, + dd.license_back_url AS licenseBackURL, + dd.registration_date AS registrationDate, + dd.availability AS availability, + dd.stripe_id AS stripeId, + dd.wallet_balance AS walletBalance, + d.email AS email, + d.mobile_number AS mobileNumber, + COALESCE(SUM(r.rating_count) / NULLIF(COUNT(r.rating_id), 0), 0) AS rating, + + -- Vehicle details + v.vehicle_id AS vehicleId, + v.number_plate AS numberPlate, + v.vehicle_type AS vehicleType, + v.vehicle_front_url AS vehicleFrontURL, + v.vehicle_back_url AS vehicleBackURL, + v.vehicle_side_url AS vehicleSideURL, + v.vehicle_revenue_license_url AS vehicleRevenueLicenseURL, + v.vehicle_book_url AS vehicleBookURL + + FROM driver_details dd + JOIN drivers d ON d.user_id = dd.user_id + LEFT JOIN rating r ON r.user_details_id = dd.user_details_id + LEFT JOIN vehicle v ON v.driver_details_id = dd.user_details_id + + WHERE dd.approved = 'APPROVED' + + GROUP BY + dd.user_details_id, dd.first_name, dd.last_name, dd.date_of_birth, dd.gender, + dd.home_no, dd.street_name, dd.city, dd.district, dd.license_number, + dd.license_front_url, dd.license_back_url, dd.registration_date, dd.availability, + dd.stripe_id, dd.wallet_balance, d.email, d.mobile_number, + + v.vehicle_id, v.number_plate, v.vehicle_type, + v.vehicle_front_url, v.vehicle_back_url, v.vehicle_side_url, + v.vehicle_revenue_license_url, v.vehicle_book_url + + ORDER BY dd.user_details_id +""", nativeQuery = true) List getApprovedDriverProfiles(); + @Query(value = """ - SELECT - dd.user_details_id AS userDetailsId, - dd.first_name AS firstName, - dd.last_name AS lastName, - dd.date_of_birth AS dateOfBirth, - dd.gender AS gender, - dd.home_no AS homeNo, - dd.street_name AS streetName, - dd.city AS city, - dd.district AS district, - dd.license_number AS licenseNumber, - dd.license_front_url AS licenseFrontURL, - dd.license_back_url AS licenseBackURL, - dd.registration_date AS registrationDate, - dd.availability AS availability, - dd.stripe_id AS stripeId, - dd.wallet_balance AS walletBalance, - d.email AS email, - d.mobile_number AS mobileNumber, - COALESCE(SUM(r.rating_count) / NULLIF(COUNT(r.rating_id), 0), 0) AS rating - FROM driver_details dd - JOIN drivers d ON d.user_id = dd.user_id - LEFT JOIN rating r ON r.user_details_id = dd.user_details_id - WHERE dd.approved = 'APPROVED' - AND dd.registration_date = CURRENT_DATE - GROUP BY dd.user_details_id, dd.first_name, dd.last_name, dd.date_of_birth, dd.gender, - dd.home_no, dd.street_name, dd.city, dd.district, dd.license_number, - dd.license_front_url, dd.license_back_url, dd.registration_date, dd.availability, - dd.stripe_id, dd.wallet_balance, d.email, d.mobile_number - ORDER BY dd.user_details_id - """, nativeQuery = true) + SELECT + dd.user_details_id AS userDetailsId, + dd.first_name AS firstName, + dd.last_name AS lastName, + dd.date_of_birth AS dateOfBirth, + dd.gender AS gender, + dd.home_no AS homeNo, + dd.street_name AS streetName, + dd.city AS city, + dd.district AS district, + dd.license_number AS licenseNumber, + dd.license_front_url AS licenseFrontURL, + dd.license_back_url AS licenseBackURL, + dd.registration_date AS registrationDate, + dd.availability AS availability, + dd.stripe_id AS stripeId, + dd.wallet_balance AS walletBalance, + d.email AS email, + d.mobile_number AS mobileNumber, + COALESCE(SUM(r.rating_count) / NULLIF(COUNT(r.rating_id), 0), 0) AS rating, + + -- Vehicle details + v.vehicle_id AS vehicleId, + v.number_plate AS numberPlate, + v.vehicle_type AS vehicleType, + v.vehicle_front_url AS vehicleFrontURL, + v.vehicle_back_url AS vehicleBackURL, + v.vehicle_side_url AS vehicleSideURL, + v.vehicle_revenue_license_url AS vehicleRevenueLicenseURL, + v.vehicle_book_url AS vehicleBookURL + + FROM driver_details dd + JOIN drivers d ON d.user_id = dd.user_id + LEFT JOIN rating r ON r.user_details_id = dd.user_details_id + LEFT JOIN vehicle v ON v.driver_details_id = dd.user_details_id + + WHERE dd.approved = 'APPROVED' + AND dd.registration_date = CURRENT_DATE + + GROUP BY + dd.user_details_id, dd.first_name, dd.last_name, dd.date_of_birth, dd.gender, + dd.home_no, dd.street_name, dd.city, dd.district, dd.license_number, + dd.license_front_url, dd.license_back_url, dd.registration_date, dd.availability, + dd.stripe_id, dd.wallet_balance, d.email, d.mobile_number, + + v.vehicle_id, v.number_plate, v.vehicle_type, + v.vehicle_front_url, v.vehicle_back_url, v.vehicle_side_url, + v.vehicle_revenue_license_url, v.vehicle_book_url + + ORDER BY dd.user_details_id +""", nativeQuery = true) List getTodayRegisteredApprovedDriverProfiles(); + @Query(value = "SELECT registration_date, COUNT(*) AS driversCount " + "FROM driver_details " + "WHERE approved = 'APPROVED' " + @@ -136,7 +188,18 @@ public interface DriverDetailsRepo extends JpaRepository d.email AS email, d.mobile_number AS mobileNumber, COALESCE(SUM(r.rating_count) / NULLIF(COUNT(r.rating_id), 0), 0) AS rating, - COALESCE(SUM(e.delivery_charge), 0) AS earnings + COALESCE(SUM(e.delivery_charge), 0) AS earnings, + + -- Vehicle details + v.vehicle_id AS vehicleId, + v.number_plate AS numberPlate, + v.vehicle_type AS vehicleType, + v.vehicle_front_url AS vehicleFrontURL, + v.vehicle_back_url AS vehicleBackURL, + v.vehicle_side_url AS vehicleSideURL, + v.vehicle_revenue_license_url AS vehicleRevenueLicenseURL, + v.vehicle_book_url AS vehicleBookURL + FROM driver_details dd JOIN @@ -147,19 +210,29 @@ public interface DriverDetailsRepo extends JpaRepository delivery_order o ON e.delivery_id = o.delivery_id LEFT JOIN rating r ON o.delivery_id = r.delivery_id + LEFT JOIN + vehicle v ON v.driver_details_id = dd.user_details_id + WHERE dd.approved = 'APPROVED' AND DATE(e.created_at) = CURRENT_DATE + GROUP BY dd.user_details_id, dd.first_name, dd.last_name, dd.date_of_birth, dd.gender, dd.home_no, dd.street_name, dd.city, dd.district, dd.license_number, dd.license_front_url, dd.license_back_url, dd.registration_date, dd.availability, - dd.stripe_id, dd.wallet_balance, d.email, d.mobile_number + dd.stripe_id, dd.wallet_balance, d.email, d.mobile_number, + + v.vehicle_id, v.number_plate, v.vehicle_type, + v.vehicle_front_url, v.vehicle_back_url, v.vehicle_side_url, + v.vehicle_revenue_license_url, v.vehicle_book_url + ORDER BY earnings DESC - """, nativeQuery = true) +""", nativeQuery = true) List findApprovedDriversWithEarningsToday(); + // Churn feature query @Query(value = """ WITH driver_activity AS ( @@ -229,10 +302,23 @@ driver_ratings AS ( dd.wallet_balance AS walletBalance, d.email AS email, d.mobile_number AS mobileNumber, - COALESCE(SUM(r.rating_count) / NULLIF(COUNT(r.rating_id), 0), 0) AS rating + COALESCE(SUM(r.rating_count) / NULLIF(COUNT(r.rating_id), 0), 0) AS rating, + + -- Vehicle details + v.vehicle_id AS vehicleId, + v.number_plate AS numberPlate, + v.vehicle_type AS vehicleType, + v.vehicle_front_url AS vehicleFrontURL, + v.vehicle_back_url AS vehicleBackURL, + v.vehicle_side_url AS vehicleSideURL, + v.vehicle_revenue_license_url AS vehicleRevenueLicenseURL, + v.vehicle_book_url AS vehicleBookURL + FROM driver_details dd JOIN drivers d ON d.user_id = dd.user_id LEFT JOIN rating r ON r.user_details_id = dd.user_details_id + LEFT JOIN vehicle v ON v.driver_details_id = dd.user_details_id + WHERE dd.approved = 'APPROVED' AND d.user_id IN ( SELECT da.user_id @@ -240,14 +326,21 @@ AND d.user_id IN ( GROUP BY da.user_id HAVING MAX(da.end_time) < now() - interval '7 days' ) + GROUP BY dd.user_details_id, dd.first_name, dd.last_name, dd.date_of_birth, dd.gender, dd.home_no, dd.street_name, dd.city, dd.district, dd.license_number, dd.license_front_url, dd.license_back_url, dd.registration_date, dd.availability, - dd.stripe_id, dd.wallet_balance, d.email, d.mobile_number + dd.stripe_id, dd.wallet_balance, d.email, d.mobile_number, + + v.vehicle_id, v.number_plate, v.vehicle_type, + v.vehicle_front_url, v.vehicle_back_url, v.vehicle_side_url, + v.vehicle_revenue_license_url, v.vehicle_book_url + ORDER BY dd.user_details_id """, nativeQuery = true) List findApprovedInactiveDrivers(); + @Query(value = """ SELECT COUNT(*) FILTER ( @@ -274,36 +367,56 @@ HAVING MAX(da.end_time) < now() - interval '7 days' List countApprovedInactiveDrivers(); @Query(value = """ - SELECT - dd.user_details_id AS userDetailsId, - dd.first_name AS firstName, - dd.last_name AS lastName, - dd.date_of_birth AS dateOfBirth, - dd.gender AS gender, - dd.home_no AS homeNo, - dd.street_name AS streetName, - dd.city AS city, - dd.district AS district, - dd.license_number AS licenseNumber, - dd.license_front_url AS licenseFrontURL, - dd.license_back_url AS licenseBackURL, - dd.registration_date AS registrationDate, - dd.availability AS availability, - dd.stripe_id AS stripeId, - dd.wallet_balance AS walletBalance, - d.email AS email, - d.mobile_number AS mobileNumber, - COALESCE(SUM(r.rating_count) / NULLIF(COUNT(r.rating_id), 0), 0) AS rating - FROM driver_details dd - JOIN drivers d ON d.user_id = dd.user_id - LEFT JOIN rating r ON r.user_details_id = dd.user_details_id - WHERE dd.approved = 'BLACKLISTED' - GROUP BY dd.user_details_id, dd.first_name, dd.last_name, dd.date_of_birth, dd.gender, - dd.home_no, dd.street_name, dd.city, dd.district, dd.license_number, - dd.license_front_url, dd.license_back_url, dd.registration_date, dd.availability, - dd.stripe_id, dd.wallet_balance, d.email, d.mobile_number - ORDER BY dd.user_details_id - """, nativeQuery = true) + SELECT + dd.user_details_id AS userDetailsId, + dd.first_name AS firstName, + dd.last_name AS lastName, + dd.date_of_birth AS dateOfBirth, + dd.gender AS gender, + dd.home_no AS homeNo, + dd.street_name AS streetName, + dd.city AS city, + dd.district AS district, + dd.license_number AS licenseNumber, + dd.license_front_url AS licenseFrontURL, + dd.license_back_url AS licenseBackURL, + dd.registration_date AS registrationDate, + dd.availability AS availability, + dd.stripe_id AS stripeId, + dd.wallet_balance AS walletBalance, + d.email AS email, + d.mobile_number AS mobileNumber, + COALESCE(SUM(r.rating_count) / NULLIF(COUNT(r.rating_id), 0), 0) AS rating, + + -- Vehicle details + v.vehicle_id AS vehicleId, + v.number_plate AS numberPlate, + v.vehicle_type AS vehicleType, + v.vehicle_front_url AS vehicleFrontURL, + v.vehicle_back_url AS vehicleBackURL, + v.vehicle_side_url AS vehicleSideURL, + v.vehicle_revenue_license_url AS vehicleRevenueLicenseURL, + v.vehicle_book_url AS vehicleBookURL + + FROM driver_details dd + JOIN drivers d ON d.user_id = dd.user_id + LEFT JOIN rating r ON r.user_details_id = dd.user_details_id + LEFT JOIN vehicle v ON v.driver_details_id = dd.user_details_id + + WHERE dd.approved = 'BLACKLISTED' + + GROUP BY dd.user_details_id, dd.first_name, dd.last_name, dd.date_of_birth, dd.gender, + dd.home_no, dd.street_name, dd.city, dd.district, dd.license_number, + dd.license_front_url, dd.license_back_url, dd.registration_date, dd.availability, + dd.stripe_id, dd.wallet_balance, d.email, d.mobile_number, + + v.vehicle_id, v.number_plate, v.vehicle_type, + v.vehicle_front_url, v.vehicle_back_url, v.vehicle_side_url, + v.vehicle_revenue_license_url, v.vehicle_book_url + + ORDER BY dd.user_details_id +""", nativeQuery = true) List getBlacklist(); + } \ No newline at end of file