Merge pull request #304 from RecentRunner/web-coupons

web coupons
This commit was merged in pull request #304.
This commit is contained in:
2026-04-15 01:39:43 -06:00
committed by GitHub
10 changed files with 295 additions and 35 deletions

View File

@@ -267,7 +267,8 @@ public class AuthController {
user.getRole().name(),
customerId,
primaryStore != null ? primaryStore.getStoreId() : null,
primaryStore != null ? primaryStore.getStoreName() : null
primaryStore != null ? primaryStore.getStoreName() : null,
user.getLoyaltyPoints()
);
}

View File

@@ -75,6 +75,14 @@ public class CartController {
return ResponseEntity.ok(cartService.applyCoupon(userId, storeId, request.getCouponCode()));
}
@DeleteMapping("/coupon")
@PreAuthorize("isAuthenticated()")
public ResponseEntity<CartResponse> removeCoupon(@RequestParam Long storeId) {
Long userId = AuthenticationHelper.getAuthenticatedUserId();
return ResponseEntity.ok(cartService.removeCoupon(userId, storeId));
}
@PostMapping("/checkout")
@PreAuthorize("isAuthenticated()")
public ResponseEntity<CheckoutResponse> checkout(@Valid @RequestBody CheckoutRequest request) {

View File

@@ -15,11 +15,12 @@ public class UserInfoResponse {
private Long customerId;
private Long storeId;
private String storeName;
private Integer loyaltyPoints;
public UserInfoResponse() {
}
public UserInfoResponse(Long id, String username, String firstName, String lastName, String email, String fullName, String phone, String avatarUrl, String role, Long customerId, Long storeId, String storeName) {
public UserInfoResponse(Long id, String username, String firstName, String lastName, String email, String fullName, String phone, String avatarUrl, String role, Long customerId, Long storeId, String storeName, Integer loyaltyPoints) {
this.id = id;
this.username = username;
this.firstName = firstName;
@@ -32,6 +33,7 @@ public class UserInfoResponse {
this.customerId = customerId;
this.storeId = storeId;
this.storeName = storeName;
this.loyaltyPoints = loyaltyPoints;
}
public Long getId() {
@@ -131,6 +133,14 @@ public class UserInfoResponse {
this.storeName = storeName;
}
public Integer getLoyaltyPoints() {
return loyaltyPoints;
}
public void setLoyaltyPoints(Integer loyaltyPoints) {
this.loyaltyPoints = loyaltyPoints;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;

View File

@@ -14,6 +14,8 @@ public class CartResponse {
private BigDecimal pointsDiscountAmount;
private BigDecimal totalAmount;
private String couponCode;
private String couponDiscountType;
private BigDecimal couponDiscountValue;
private Boolean pointsApplied;
private Integer availableLoyaltyPoints;
private Boolean checkoutPending;
@@ -45,6 +47,12 @@ public class CartResponse {
public String getCouponCode() { return couponCode; }
public void setCouponCode(String couponCode) { this.couponCode = couponCode; }
public String getCouponDiscountType() { return couponDiscountType; }
public void setCouponDiscountType(String couponDiscountType) { this.couponDiscountType = couponDiscountType; }
public BigDecimal getCouponDiscountValue() { return couponDiscountValue; }
public void setCouponDiscountValue(BigDecimal couponDiscountValue) { this.couponDiscountValue = couponDiscountValue; }
public BigDecimal getPointsDiscountAmount() { return pointsDiscountAmount; }
public void setPointsDiscountAmount(BigDecimal pointsDiscountAmount) { this.pointsDiscountAmount = pointsDiscountAmount; }

View File

@@ -212,6 +212,19 @@ public class CartService {
return toResponse(cart);
}
@Transactional
public CartResponse removeCoupon(Long userId, Long storeId) {
Cart cart = cartRepository
.findActiveCartByUserAndStore(userId, storeId, "ACTIVE")
.orElseThrow(() -> new BusinessException("No active cart found"));
requireNotCheckoutPending(cart);
cart.setCoupon(null);
recalculate(cart);
return toResponse(cart);
}
@Transactional
public CartResponse applyPoints(Long userId, Long storeId, Boolean useLoyaltyPoints) {
Cart cart = cartRepository
@@ -411,12 +424,10 @@ public class CartService {
Coupon coupon = cart.getCoupon();
if (coupon != null) {
if ("PERCENTAGE".equalsIgnoreCase(coupon.getDiscountType())) {
if (isPercentageType(coupon.getDiscountType())) {
discount = subtotal.multiply(coupon.getDiscountValue())
.divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
}
else if ("FIXED".equalsIgnoreCase(coupon.getDiscountType())) {
} else if (isFixedType(coupon.getDiscountType())) {
discount = coupon.getDiscountValue().min(subtotal);
}
}
@@ -442,12 +453,10 @@ public class CartService {
Coupon coupon = cart.getCoupon();
if (coupon != null) {
if ("PERCENTAGE".equalsIgnoreCase(coupon.getDiscountType())) {
if (isPercentageType(coupon.getDiscountType())) {
discount = subtotal.multiply(coupon.getDiscountValue())
.divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
}
else if ("FIXED".equalsIgnoreCase(coupon.getDiscountType())) {
} else if (isFixedType(coupon.getDiscountType())) {
discount = coupon.getDiscountValue().min(subtotal);
}
}
@@ -460,6 +469,14 @@ public class CartService {
return remainingAfterCoupon.subtract(pointsDiscount).max(BigDecimal.ZERO);
}
private boolean isPercentageType(String discountType) {
return "PERCENTAGE".equalsIgnoreCase(discountType) || "PERCENT".equalsIgnoreCase(discountType);
}
private boolean isFixedType(String discountType) {
return "FIXED".equalsIgnoreCase(discountType) || "FLAT".equalsIgnoreCase(discountType);
}
private BigDecimal calculatePointsDiscount(User user, BigDecimal remainingAmount, boolean pointsApplied) {
if (!pointsApplied || user == null || remainingAmount.compareTo(BigDecimal.ZERO) <= 0) {
@@ -509,6 +526,8 @@ public class CartService {
response.setPointsDiscountAmount(cart.getPointsDiscountAmount());
response.setTotalAmount(cart.getTotalAmount());
response.setCouponCode(cart.getCoupon() != null ? cart.getCoupon().getCouponCode() : null);
response.setCouponDiscountType(cart.getCoupon() != null ? cart.getCoupon().getDiscountType() : null);
response.setCouponDiscountValue(cart.getCoupon() != null ? cart.getCoupon().getDiscountValue() : null);
response.setPointsApplied(cart.getPointsApplied());
response.setAvailableLoyaltyPoints(cart.getUser() != null ? cart.getUser().getLoyaltyPoints() : null);
response.setCheckoutPending(cart.getCheckoutPending());