fix coupon analytics
This commit is contained in:
@@ -5,12 +5,15 @@ import com.petshop.backend.entity.User;
|
|||||||
import com.petshop.backend.repository.UserRepository;
|
import com.petshop.backend.repository.UserRepository;
|
||||||
import com.petshop.backend.service.AnalyticsService;
|
import com.petshop.backend.service.AnalyticsService;
|
||||||
import com.petshop.backend.util.AuthenticationHelper;
|
import com.petshop.backend.util.AuthenticationHelper;
|
||||||
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.server.ResponseStatusException;
|
import org.springframework.web.server.ResponseStatusException;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/api/v1/analytics")
|
@RequestMapping("/api/v1/analytics")
|
||||||
@PreAuthorize("hasAnyRole('ADMIN', 'STAFF')")
|
@PreAuthorize("hasAnyRole('ADMIN', 'STAFF')")
|
||||||
@@ -27,7 +30,11 @@ public class AnalyticsController {
|
|||||||
@GetMapping("/dashboard")
|
@GetMapping("/dashboard")
|
||||||
public ResponseEntity<DashboardResponse> getDashboard(
|
public ResponseEntity<DashboardResponse> getDashboard(
|
||||||
@RequestParam(defaultValue = "30") int days,
|
@RequestParam(defaultValue = "30") int days,
|
||||||
@RequestParam(defaultValue = "10") int top) {
|
@RequestParam(defaultValue = "10") int top,
|
||||||
|
@RequestParam(required = false) String paymentMethod,
|
||||||
|
@RequestParam(required = false) Long storeId,
|
||||||
|
@RequestParam(required = false) String channel,
|
||||||
|
@RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate) {
|
||||||
if (days < 1 || days > 365) {
|
if (days < 1 || days > 365) {
|
||||||
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "days must be between 1 and 365");
|
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "days must be between 1 and 365");
|
||||||
}
|
}
|
||||||
@@ -35,6 +42,7 @@ public class AnalyticsController {
|
|||||||
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "top must be between 1 and 50");
|
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "top must be between 1 and 50");
|
||||||
}
|
}
|
||||||
User user = AuthenticationHelper.getAuthenticatedUser(userRepository);
|
User user = AuthenticationHelper.getAuthenticatedUser(userRepository);
|
||||||
return ResponseEntity.ok(analyticsService.getDashboardData(days, top, user));
|
java.time.LocalDateTime endDateTime = endDate != null ? endDate.plusDays(1).atStartOfDay() : null;
|
||||||
|
return ResponseEntity.ok(analyticsService.getDashboardData(days, top, user, paymentMethod, storeId, channel, endDateTime));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.petshop.backend.repository;
|
|||||||
import com.petshop.backend.entity.Sale;
|
import com.petshop.backend.entity.Sale;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
import org.springframework.data.jpa.repository.Query;
|
import org.springframework.data.jpa.repository.Query;
|
||||||
import org.springframework.data.repository.query.Param;
|
import org.springframework.data.repository.query.Param;
|
||||||
@@ -26,6 +27,19 @@ public interface SaleRepository extends JpaRepository<Sale, Long> {
|
|||||||
"(:customerId IS NULL OR s.customer.id = :customerId)")
|
"(:customerId IS NULL OR s.customer.id = :customerId)")
|
||||||
Page<Sale> searchSales(@Param("q") String query, @Param("paymentMethod") String paymentMethod, @Param("storeId") Long storeId, @Param("isRefund") Boolean isRefund, @Param("customerId") Long customerId, Pageable pageable);
|
Page<Sale> searchSales(@Param("q") String query, @Param("paymentMethod") String paymentMethod, @Param("storeId") Long storeId, @Param("isRefund") Boolean isRefund, @Param("customerId") Long customerId, Pageable pageable);
|
||||||
|
|
||||||
|
long countByCoupon_CouponId(Long couponId);
|
||||||
|
|
||||||
|
@Query("SELECT s FROM Sale s WHERE s.saleDate > :startDate " +
|
||||||
|
"AND (:endDate IS NULL OR s.saleDate <= :endDate) " +
|
||||||
|
"AND (:paymentMethod IS NULL OR LOWER(s.paymentMethod) = LOWER(:paymentMethod)) " +
|
||||||
|
"AND (:storeId IS NULL OR s.store.storeId = :storeId) " +
|
||||||
|
"AND (:channel IS NULL OR s.channel = :channel)")
|
||||||
|
List<Sale> findForAnalytics(@Param("startDate") LocalDateTime startDate,
|
||||||
|
@Param("endDate") LocalDateTime endDate,
|
||||||
|
@Param("paymentMethod") String paymentMethod,
|
||||||
|
@Param("storeId") Long storeId,
|
||||||
|
@Param("channel") String channel);
|
||||||
|
|
||||||
List<Sale> findByOriginalSaleSaleId(Long originalSaleId);
|
List<Sale> findByOriginalSaleSaleId(Long originalSaleId);
|
||||||
|
|
||||||
Optional<Sale> findByCartCartId(Long cartId);
|
Optional<Sale> findByCartCartId(Long cartId);
|
||||||
|
|||||||
@@ -34,10 +34,17 @@ public class AnalyticsService {
|
|||||||
|
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
public DashboardResponse getDashboardData(int days, int top, User user) {
|
public DashboardResponse getDashboardData(int days, int top, User user) {
|
||||||
|
return getDashboardData(days, top, user, null, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
public DashboardResponse getDashboardData(int days, int top, User user,
|
||||||
|
String paymentMethod, Long storeId,
|
||||||
|
String channel, LocalDateTime endDate) {
|
||||||
LocalDateTime startDate = LocalDateTime.now().minusDays(days);
|
LocalDateTime startDate = LocalDateTime.now().minusDays(days);
|
||||||
|
|
||||||
List<Sale> sales = saleRepository.findAll().stream()
|
List<Sale> sales = saleRepository.findForAnalytics(startDate, endDate, paymentMethod, storeId, channel)
|
||||||
.filter(sale -> sale.getSaleDate().isAfter(startDate))
|
.stream()
|
||||||
.filter(sale -> includeSaleForUser(sale, user))
|
.filter(sale -> includeSaleForUser(sale, user))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
|||||||
@@ -206,6 +206,13 @@ public class CartService {
|
|||||||
throw new BusinessException("Minimum order amount of $" + coupon.getMinOrderAmount() + " required");
|
throw new BusinessException("Minimum order amount of $" + coupon.getMinOrderAmount() + " required");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (coupon.getUsageLimit() != null) {
|
||||||
|
long used = saleRepository.countByCoupon_CouponId(coupon.getCouponId());
|
||||||
|
if (used >= coupon.getUsageLimit()) {
|
||||||
|
throw new BusinessException("Coupon usage limit has been reached");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cart.setCoupon(coupon);
|
cart.setCoupon(coupon);
|
||||||
recalculate(cart);
|
recalculate(cart);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user