use shared StringUtils.trimToNull
This commit is contained in:
@@ -14,8 +14,6 @@ import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.time.LocalDate;
|
||||
@@ -41,17 +39,10 @@ public class AdoptionController {
|
||||
@RequestParam(required = false) Long storeId,
|
||||
@RequestParam(required = false) String date,
|
||||
Pageable pageable) {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
String role = authentication.getAuthorities().stream()
|
||||
.findFirst()
|
||||
.map(authority -> authority.getAuthority().replace("ROLE_", ""))
|
||||
.orElse(null);
|
||||
|
||||
Long effectiveCustomerId = customerId;
|
||||
if (role != null && role.equals("CUSTOMER")) {
|
||||
User user = AuthenticationHelper.getAuthenticatedUser(userRepository);
|
||||
effectiveCustomerId = user.getId();
|
||||
}
|
||||
Long effectiveCustomerId = AuthenticationHelper.isCustomer()
|
||||
? AuthenticationHelper.getAuthenticatedUser(userRepository).getId()
|
||||
: customerId;
|
||||
|
||||
LocalDate adoptionDate = (date != null && !date.isBlank()) ? LocalDate.parse(date) : null;
|
||||
|
||||
@@ -61,18 +52,7 @@ public class AdoptionController {
|
||||
@GetMapping("/{id}")
|
||||
@PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF', 'ADMIN')")
|
||||
public ResponseEntity<AdoptionResponse> getAdoptionById(@PathVariable Long id) {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
String role = authentication.getAuthorities().stream()
|
||||
.findFirst()
|
||||
.map(authority -> authority.getAuthority().replace("ROLE_", ""))
|
||||
.orElse(null);
|
||||
|
||||
Long customerId = null;
|
||||
if (role != null && role.equals("CUSTOMER")) {
|
||||
User user = AuthenticationHelper.getAuthenticatedUser(userRepository);
|
||||
customerId = user.getId();
|
||||
}
|
||||
|
||||
Long customerId = AuthenticationHelper.getCustomerIdOrNull(userRepository);
|
||||
return ResponseEntity.ok(adoptionService.getAdoptionById(id, customerId));
|
||||
}
|
||||
|
||||
@@ -94,18 +74,7 @@ public class AdoptionController {
|
||||
@PatchMapping("/{id}/cancel")
|
||||
@PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF', 'ADMIN')")
|
||||
public ResponseEntity<AdoptionResponse> cancelAdoption(@PathVariable Long id) {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
String role = authentication.getAuthorities().stream()
|
||||
.findFirst()
|
||||
.map(authority -> authority.getAuthority().replace("ROLE_", ""))
|
||||
.orElse(null);
|
||||
|
||||
Long customerId = null;
|
||||
if ("CUSTOMER".equals(role)) {
|
||||
User user = AuthenticationHelper.getAuthenticatedUser(userRepository);
|
||||
customerId = user.getId();
|
||||
}
|
||||
|
||||
Long customerId = AuthenticationHelper.getCustomerIdOrNull(userRepository);
|
||||
return ResponseEntity.ok(adoptionService.cancelAdoption(id, customerId));
|
||||
}
|
||||
|
||||
|
||||
@@ -13,8 +13,6 @@ import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.time.LocalDate;
|
||||
@@ -43,17 +41,9 @@ public class AppointmentController {
|
||||
@RequestParam(required = false) Long employeeId,
|
||||
Pageable pageable) {
|
||||
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
String role = authentication.getAuthorities().stream()
|
||||
.findFirst()
|
||||
.map(authority -> authority.getAuthority().replace("ROLE_", ""))
|
||||
.orElse(null);
|
||||
|
||||
Long effectiveCustomerId = customerId;
|
||||
if ("CUSTOMER".equals(role)) {
|
||||
User user = AuthenticationHelper.getAuthenticatedUser(userRepository);
|
||||
effectiveCustomerId = user.getId();
|
||||
}
|
||||
Long effectiveCustomerId = AuthenticationHelper.isCustomer()
|
||||
? AuthenticationHelper.getAuthenticatedUser(userRepository).getId()
|
||||
: customerId;
|
||||
|
||||
LocalDate appointmentDate = (date != null && !date.isBlank()) ? LocalDate.parse(date) : null;
|
||||
|
||||
@@ -64,31 +54,14 @@ public class AppointmentController {
|
||||
@GetMapping("/{id}")
|
||||
@PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF', 'ADMIN')")
|
||||
public ResponseEntity<AppointmentResponse> getAppointmentById(@PathVariable Long id) {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
String role = authentication.getAuthorities().stream()
|
||||
.findFirst()
|
||||
.map(authority -> authority.getAuthority().replace("ROLE_", ""))
|
||||
.orElse(null);
|
||||
|
||||
Long customerId = null;
|
||||
if (role != null && role.equals("CUSTOMER")) {
|
||||
User user = AuthenticationHelper.getAuthenticatedUser(userRepository);
|
||||
customerId = user.getId();
|
||||
}
|
||||
|
||||
Long customerId = AuthenticationHelper.getCustomerIdOrNull(userRepository);
|
||||
return ResponseEntity.ok(appointmentService.getAppointmentById(id, customerId));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF', 'ADMIN')")
|
||||
public ResponseEntity<AppointmentResponse> createAppointment(@Valid @RequestBody AppointmentRequest request) {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
String role = authentication.getAuthorities().stream()
|
||||
.findFirst()
|
||||
.map(authority -> authority.getAuthority().replace("ROLE_", ""))
|
||||
.orElse(null);
|
||||
|
||||
if ("CUSTOMER".equals(role)) {
|
||||
if (AuthenticationHelper.isCustomer()) {
|
||||
User user = AuthenticationHelper.getAuthenticatedUser(userRepository);
|
||||
if (!request.getCustomerId().equals(user.getId())) {
|
||||
throw new org.springframework.security.access.AccessDeniedException("You can only create appointments for yourself");
|
||||
@@ -101,18 +74,7 @@ public class AppointmentController {
|
||||
@PatchMapping("/{id}/cancel")
|
||||
@PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF', 'ADMIN')")
|
||||
public ResponseEntity<AppointmentResponse> cancelAppointment(@PathVariable Long id) {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
String role = authentication.getAuthorities().stream()
|
||||
.findFirst()
|
||||
.map(authority -> authority.getAuthority().replace("ROLE_", ""))
|
||||
.orElse(null);
|
||||
|
||||
Long customerId = null;
|
||||
if ("CUSTOMER".equals(role)) {
|
||||
User user = AuthenticationHelper.getAuthenticatedUser(userRepository);
|
||||
customerId = user.getId();
|
||||
}
|
||||
|
||||
Long customerId = AuthenticationHelper.getCustomerIdOrNull(userRepository);
|
||||
return ResponseEntity.ok(appointmentService.cancelAppointment(id, customerId));
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.petshop.backend.service.EmailService;
|
||||
import com.petshop.backend.service.PasswordResetService;
|
||||
import com.petshop.backend.util.AuthenticationHelper;
|
||||
import com.petshop.backend.util.PhoneUtils;
|
||||
import com.petshop.backend.util.StringUtils;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -78,10 +79,10 @@ public class AuthController {
|
||||
|
||||
@PostMapping("/register")
|
||||
public ResponseEntity<RegisterResponse> register(@Valid @RequestBody RegisterRequest request) {
|
||||
String username = trimToNull(request.getUsername());
|
||||
String email = trimToNull(request.getEmail());
|
||||
String firstName = trimToNull(request.getFirstName());
|
||||
String lastName = trimToNull(request.getLastName());
|
||||
String username = StringUtils.trimToNull(request.getUsername());
|
||||
String email = StringUtils.trimToNull(request.getEmail());
|
||||
String firstName = StringUtils.trimToNull(request.getFirstName());
|
||||
String lastName = StringUtils.trimToNull(request.getLastName());
|
||||
String phone = normalizePhone(request.getPhone());
|
||||
|
||||
if (userRepository.findByUsername(username).isPresent()) {
|
||||
@@ -191,7 +192,7 @@ public class AuthController {
|
||||
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
|
||||
boolean invalidateToken = false;
|
||||
|
||||
String username = trimToNull(request.getUsername());
|
||||
String username = StringUtils.trimToNull(request.getUsername());
|
||||
if (username != null && !username.equals(user.getUsername())) {
|
||||
if (userRepository.findByUsername(username).isPresent()) {
|
||||
throw new ConflictException("Username already exists");
|
||||
@@ -200,7 +201,7 @@ public class AuthController {
|
||||
invalidateToken = true;
|
||||
}
|
||||
|
||||
String email = trimToNull(request.getEmail());
|
||||
String email = StringUtils.trimToNull(request.getEmail());
|
||||
if (email != null && !email.equals(user.getEmail())) {
|
||||
if (userRepository.findByEmail(email).isPresent()) {
|
||||
throw new ConflictException("Email already exists");
|
||||
@@ -208,11 +209,11 @@ public class AuthController {
|
||||
user.setEmail(email);
|
||||
}
|
||||
|
||||
String firstName = trimToNull(request.getFirstName());
|
||||
String firstName = StringUtils.trimToNull(request.getFirstName());
|
||||
if (firstName != null) {
|
||||
user.setFirstName(firstName);
|
||||
}
|
||||
String lastName = trimToNull(request.getLastName());
|
||||
String lastName = StringUtils.trimToNull(request.getLastName());
|
||||
if (lastName != null) {
|
||||
user.setLastName(lastName);
|
||||
}
|
||||
@@ -275,21 +276,13 @@ public class AuthController {
|
||||
);
|
||||
}
|
||||
|
||||
private String trimToNull(String value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
String trimmed = value.trim();
|
||||
return trimmed.isEmpty() ? null : trimmed;
|
||||
}
|
||||
|
||||
private String normalizePhone(String value) {
|
||||
return trimToNull(PhoneUtils.normalize(trimToNull(value)));
|
||||
return StringUtils.trimToNull(PhoneUtils.normalize(StringUtils.trimToNull(value)));
|
||||
}
|
||||
|
||||
private String joinFullName(String firstName, String lastName) {
|
||||
String first = trimToNull(firstName);
|
||||
String last = trimToNull(lastName);
|
||||
String first = StringUtils.trimToNull(firstName);
|
||||
String last = StringUtils.trimToNull(lastName);
|
||||
if (first == null) {
|
||||
return last == null ? null : last;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.petshop.backend.controller;
|
||||
import com.petshop.backend.dto.refund.RefundRequest;
|
||||
import com.petshop.backend.dto.refund.RefundResponse;
|
||||
import com.petshop.backend.dto.refund.RefundUpdateRequest;
|
||||
import com.petshop.backend.entity.User;
|
||||
import com.petshop.backend.repository.UserRepository;
|
||||
import com.petshop.backend.service.RefundService;
|
||||
import com.petshop.backend.util.AuthenticationHelper;
|
||||
@@ -11,8 +10,6 @@ import jakarta.validation.Valid;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
@@ -32,36 +29,14 @@ public class RefundController {
|
||||
@PostMapping
|
||||
@PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF')")
|
||||
public ResponseEntity<RefundResponse> createRefund(@Valid @RequestBody RefundRequest request) {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
String role = authentication.getAuthorities().stream()
|
||||
.findFirst()
|
||||
.map(authority -> authority.getAuthority().replace("ROLE_", ""))
|
||||
.orElse(null);
|
||||
|
||||
Long customerId = null;
|
||||
if (role != null && role.equals("CUSTOMER")) {
|
||||
User user = AuthenticationHelper.getAuthenticatedUser(userRepository);
|
||||
customerId = user.getId();
|
||||
}
|
||||
|
||||
Long customerId = AuthenticationHelper.getCustomerIdOrNull(userRepository);
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(refundService.createRefund(request, customerId));
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF', 'ADMIN')")
|
||||
public ResponseEntity<List<RefundResponse>> getAllRefunds() {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
String role = authentication.getAuthorities().stream()
|
||||
.findFirst()
|
||||
.map(authority -> authority.getAuthority().replace("ROLE_", ""))
|
||||
.orElse(null);
|
||||
|
||||
Long customerId = null;
|
||||
if (role != null && role.equals("CUSTOMER")) {
|
||||
User user = AuthenticationHelper.getAuthenticatedUser(userRepository);
|
||||
customerId = user.getId();
|
||||
}
|
||||
|
||||
Long customerId = AuthenticationHelper.getCustomerIdOrNull(userRepository);
|
||||
List<RefundResponse> refunds = refundService.getAllRefunds(customerId);
|
||||
return ResponseEntity.ok(refunds);
|
||||
}
|
||||
@@ -69,18 +44,7 @@ public class RefundController {
|
||||
@GetMapping("/{id}")
|
||||
@PreAuthorize("hasAnyRole('CUSTOMER', 'STAFF', 'ADMIN')")
|
||||
public ResponseEntity<RefundResponse> getRefundById(@PathVariable Long id) {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
String role = authentication.getAuthorities().stream()
|
||||
.findFirst()
|
||||
.map(authority -> authority.getAuthority().replace("ROLE_", ""))
|
||||
.orElse(null);
|
||||
|
||||
Long customerId = null;
|
||||
if (role != null && role.equals("CUSTOMER")) {
|
||||
User user = AuthenticationHelper.getAuthenticatedUser(userRepository);
|
||||
customerId = user.getId();
|
||||
}
|
||||
|
||||
Long customerId = AuthenticationHelper.getCustomerIdOrNull(userRepository);
|
||||
return ResponseEntity.ok(refundService.getRefundById(id, customerId));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.petshop.backend.service;
|
||||
|
||||
import com.petshop.backend.dto.adoption.AdoptionRequest;
|
||||
import com.petshop.backend.util.StringUtils;
|
||||
import com.petshop.backend.dto.adoption.AdoptionResponse;
|
||||
import com.petshop.backend.dto.common.BulkDeleteRequest;
|
||||
import com.petshop.backend.entity.Adoption;
|
||||
@@ -56,8 +57,8 @@ public class AdoptionService {
|
||||
}
|
||||
|
||||
public Page<AdoptionResponse> getAllAdoptions(String query, Long customerId, String status, Long storeId, LocalDate date, Pageable pageable) {
|
||||
String normalizedQuery = normalizeFilter(query);
|
||||
String normalizedStatus = normalizeFilter(status);
|
||||
String normalizedQuery = StringUtils.trimToNull(query);
|
||||
String normalizedStatus = StringUtils.trimToNull(status);
|
||||
|
||||
Page<Adoption> adoptions = adoptionRepository.searchAdoptions(
|
||||
normalizedQuery,
|
||||
@@ -248,14 +249,6 @@ public class AdoptionService {
|
||||
}
|
||||
}
|
||||
|
||||
private String normalizeFilter(String value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
String trimmed = value.trim();
|
||||
return trimmed.isEmpty() ? null : trimmed;
|
||||
}
|
||||
|
||||
private AdoptionResponse mapToResponse(Adoption adoption) {
|
||||
StoreLocation sourceStore = adoption.getSourceStore();
|
||||
return new AdoptionResponse(
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.petshop.backend.repository.ServiceRepository;
|
||||
import com.petshop.backend.repository.StoreRepository;
|
||||
import com.petshop.backend.repository.UserRepository;
|
||||
import com.petshop.backend.util.AuthenticationHelper;
|
||||
import com.petshop.backend.util.StringUtils;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
@@ -67,8 +68,8 @@ public class AppointmentService {
|
||||
LocalDate date,
|
||||
Pageable pageable) {
|
||||
|
||||
String normalizedQuery = normalizeFilter(query);
|
||||
String normalizedStatus = normalizeFilter(status);
|
||||
String normalizedQuery = StringUtils.trimToNull(query);
|
||||
String normalizedStatus = StringUtils.trimToNull(status);
|
||||
|
||||
Page<Appointment> appointments = appointmentRepository.searchAppointments(
|
||||
normalizedQuery,
|
||||
@@ -288,14 +289,6 @@ public class AppointmentService {
|
||||
}
|
||||
}
|
||||
|
||||
private String normalizeFilter(String value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
String trimmed = value.trim();
|
||||
return trimmed.isEmpty() ? null : trimmed;
|
||||
}
|
||||
|
||||
private void validatePetServiceCompatibility(Pet pet, com.petshop.backend.entity.Service service) {
|
||||
if (pet == null) return;
|
||||
Set<String> allowed = service.getSpecies();
|
||||
|
||||
@@ -32,6 +32,7 @@ public class CartService {
|
||||
private final StoreRepository storeRepository;
|
||||
private final ProductRepository productRepository;
|
||||
private final CouponRepository couponRepository;
|
||||
private final CouponService couponService;
|
||||
private final SaleRepository saleRepository;
|
||||
private final SaleService saleService;
|
||||
|
||||
@@ -44,6 +45,7 @@ public class CartService {
|
||||
StoreRepository storeRepository,
|
||||
ProductRepository productRepository,
|
||||
CouponRepository couponRepository,
|
||||
CouponService couponService,
|
||||
SaleRepository saleRepository,
|
||||
SaleService saleService) {
|
||||
this.cartRepository = cartRepository;
|
||||
@@ -52,6 +54,7 @@ public class CartService {
|
||||
this.storeRepository = storeRepository;
|
||||
this.productRepository = productRepository;
|
||||
this.couponRepository = couponRepository;
|
||||
this.couponService = couponService;
|
||||
this.saleRepository = saleRepository;
|
||||
this.saleService = saleService;
|
||||
}
|
||||
@@ -188,31 +191,12 @@ public class CartService {
|
||||
Coupon coupon = couponRepository.findByCouponCodeIgnoreCase(couponCode)
|
||||
.orElseThrow(() -> new BusinessException("Invalid coupon code"));
|
||||
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
|
||||
if (!coupon.getActive()) {
|
||||
throw new BusinessException("Coupon is no longer active");
|
||||
}
|
||||
|
||||
if (coupon.getStartsAt() != null && now.isBefore(coupon.getStartsAt())) {
|
||||
throw new BusinessException("Coupon is not yet valid");
|
||||
}
|
||||
|
||||
if (coupon.getEndsAt() != null && now.isAfter(coupon.getEndsAt())) {
|
||||
throw new BusinessException("Coupon has expired");
|
||||
}
|
||||
couponService.validateCouponForUse(coupon);
|
||||
|
||||
if (coupon.getMinOrderAmount() != null && cart.getSubtotalAmount().compareTo(coupon.getMinOrderAmount()) < 0) {
|
||||
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);
|
||||
recalculate(cart);
|
||||
|
||||
@@ -450,73 +434,38 @@ public class CartService {
|
||||
}
|
||||
}
|
||||
|
||||
private void recalculate(Cart cart) {
|
||||
private record CartTotals(BigDecimal subtotal, BigDecimal discount, BigDecimal pointsDiscount, BigDecimal total) {}
|
||||
|
||||
private CartTotals computeTotals(Cart cart) {
|
||||
List<CartItem> items = cartItemRepository.findByCartCartId(cart.getCartId());
|
||||
|
||||
BigDecimal subtotal = items.stream()
|
||||
.map(i -> i.getUnitPrice().multiply(BigDecimal.valueOf(i.getQuantity())))
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
|
||||
cart.setSubtotalAmount(subtotal);
|
||||
|
||||
BigDecimal discount = BigDecimal.ZERO;
|
||||
Coupon coupon = cart.getCoupon();
|
||||
|
||||
if (coupon != null) {
|
||||
if (isPercentageType(coupon.getDiscountType())) {
|
||||
discount = subtotal.multiply(coupon.getDiscountValue())
|
||||
.divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
|
||||
} else if (isFixedType(coupon.getDiscountType())) {
|
||||
discount = coupon.getDiscountValue().min(subtotal);
|
||||
}
|
||||
}
|
||||
|
||||
discount = discount.max(BigDecimal.ZERO).min(subtotal);
|
||||
cart.setDiscountAmount(discount);
|
||||
BigDecimal discount = couponService.calculateDiscount(cart.getCoupon(), subtotal)
|
||||
.max(BigDecimal.ZERO).min(subtotal);
|
||||
|
||||
BigDecimal remainingAfterCoupon = subtotal.subtract(discount).max(BigDecimal.ZERO);
|
||||
BigDecimal pointsDiscount = calculatePointsDiscount(cart.getUser(), remainingAfterCoupon, Boolean.TRUE.equals(cart.getPointsApplied()));
|
||||
cart.setPointsDiscountAmount(pointsDiscount);
|
||||
cart.setTotalAmount(remainingAfterCoupon.subtract(pointsDiscount).max(BigDecimal.ZERO));
|
||||
BigDecimal total = remainingAfterCoupon.subtract(pointsDiscount).max(BigDecimal.ZERO);
|
||||
|
||||
return new CartTotals(subtotal, discount, pointsDiscount, total);
|
||||
}
|
||||
|
||||
private void recalculate(Cart cart) {
|
||||
CartTotals totals = computeTotals(cart);
|
||||
cart.setSubtotalAmount(totals.subtotal());
|
||||
cart.setDiscountAmount(totals.discount());
|
||||
cart.setPointsDiscountAmount(totals.pointsDiscount());
|
||||
cart.setTotalAmount(totals.total());
|
||||
cartRepository.save(cart);
|
||||
}
|
||||
|
||||
private BigDecimal recalculateTotalAmount(Cart cart) {
|
||||
List<CartItem> items = cartItemRepository.findByCartCartId(cart.getCartId());
|
||||
|
||||
BigDecimal subtotal = items.stream()
|
||||
.map(i -> i.getUnitPrice().multiply(BigDecimal.valueOf(i.getQuantity())))
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
|
||||
BigDecimal discount = BigDecimal.ZERO;
|
||||
Coupon coupon = cart.getCoupon();
|
||||
|
||||
if (coupon != null) {
|
||||
if (isPercentageType(coupon.getDiscountType())) {
|
||||
discount = subtotal.multiply(coupon.getDiscountValue())
|
||||
.divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
|
||||
} else if (isFixedType(coupon.getDiscountType())) {
|
||||
discount = coupon.getDiscountValue().min(subtotal);
|
||||
}
|
||||
}
|
||||
|
||||
discount = discount.max(BigDecimal.ZERO).min(subtotal);
|
||||
|
||||
BigDecimal remainingAfterCoupon = subtotal.subtract(discount).max(BigDecimal.ZERO);
|
||||
BigDecimal pointsDiscount = calculatePointsDiscount(cart.getUser(), remainingAfterCoupon, Boolean.TRUE.equals(cart.getPointsApplied()));
|
||||
|
||||
return remainingAfterCoupon.subtract(pointsDiscount).max(BigDecimal.ZERO);
|
||||
return computeTotals(cart).total();
|
||||
}
|
||||
|
||||
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) {
|
||||
return BigDecimal.ZERO;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.petshop.backend.service;
|
||||
|
||||
import com.petshop.backend.dto.category.CategoryRequest;
|
||||
import com.petshop.backend.util.StringUtils;
|
||||
import com.petshop.backend.dto.category.CategoryResponse;
|
||||
import com.petshop.backend.dto.common.BulkDeleteRequest;
|
||||
import com.petshop.backend.entity.Category;
|
||||
@@ -21,7 +22,7 @@ public class CategoryService {
|
||||
}
|
||||
|
||||
public Page<CategoryResponse> getAllCategories(String query, String type, Pageable pageable) {
|
||||
return categoryRepository.searchCategories(normalizeFilter(query), normalizeFilter(type), pageable)
|
||||
return categoryRepository.searchCategories(StringUtils.trimToNull(query), StringUtils.trimToNull(type), pageable)
|
||||
.map(this::mapToResponse);
|
||||
}
|
||||
|
||||
@@ -76,11 +77,4 @@ public class CategoryService {
|
||||
);
|
||||
}
|
||||
|
||||
private String normalizeFilter(String value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
String trimmed = value.trim();
|
||||
return trimmed.isEmpty() ? null : trimmed;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,18 +7,25 @@ import com.petshop.backend.entity.Coupon;
|
||||
import com.petshop.backend.exception.BusinessException;
|
||||
import com.petshop.backend.exception.ResourceNotFoundException;
|
||||
import com.petshop.backend.repository.CouponRepository;
|
||||
import com.petshop.backend.repository.SaleRepository;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Service
|
||||
public class CouponService {
|
||||
|
||||
private final CouponRepository couponRepository;
|
||||
private final SaleRepository saleRepository;
|
||||
|
||||
public CouponService(CouponRepository couponRepository) {
|
||||
public CouponService(CouponRepository couponRepository, SaleRepository saleRepository) {
|
||||
this.couponRepository = couponRepository;
|
||||
this.saleRepository = saleRepository;
|
||||
}
|
||||
|
||||
public Page<CouponResponse> getAllCoupons(String query, Boolean active, Pageable pageable) {
|
||||
@@ -89,6 +96,53 @@ public class CouponService {
|
||||
coupon.setUsageLimit(request.getUsageLimit());
|
||||
}
|
||||
|
||||
public void validateCouponForUse(Coupon coupon) {
|
||||
if (!Boolean.TRUE.equals(coupon.getActive())) {
|
||||
throw new BusinessException("Coupon is no longer active");
|
||||
}
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
if (coupon.getStartsAt() != null && now.isBefore(coupon.getStartsAt())) {
|
||||
throw new BusinessException("Coupon is not yet valid");
|
||||
}
|
||||
if (coupon.getEndsAt() != null && now.isAfter(coupon.getEndsAt())) {
|
||||
throw new BusinessException("Coupon has expired");
|
||||
}
|
||||
if (coupon.getUsageLimit() != null) {
|
||||
long used = saleRepository.countByCoupon_CouponId(coupon.getCouponId());
|
||||
if (used >= coupon.getUsageLimit()) {
|
||||
throw new BusinessException("Coupon usage limit has been reached");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public BigDecimal calculateDiscount(Coupon coupon, BigDecimal subtotal) {
|
||||
if (coupon == null || subtotal.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
if (coupon.getMinOrderAmount() != null && subtotal.compareTo(coupon.getMinOrderAmount()) < 0) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
BigDecimal discount = BigDecimal.ZERO;
|
||||
String type = coupon.getDiscountType();
|
||||
if (isPercentageType(type)) {
|
||||
discount = subtotal.multiply(coupon.getDiscountValue())
|
||||
.divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP);
|
||||
} else if (isFixedType(type)) {
|
||||
discount = coupon.getDiscountValue();
|
||||
}
|
||||
|
||||
return discount.min(subtotal).setScale(2, RoundingMode.HALF_UP);
|
||||
}
|
||||
|
||||
public static boolean isPercentageType(String discountType) {
|
||||
return "PERCENTAGE".equalsIgnoreCase(discountType) || "PERCENT".equalsIgnoreCase(discountType);
|
||||
}
|
||||
|
||||
public static boolean isFixedType(String discountType) {
|
||||
return "FIXED".equalsIgnoreCase(discountType) || "FLAT".equalsIgnoreCase(discountType);
|
||||
}
|
||||
|
||||
private CouponResponse mapToResponse(Coupon coupon) {
|
||||
return new CouponResponse(
|
||||
coupon.getCouponId(),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.petshop.backend.service;
|
||||
|
||||
import com.petshop.backend.dto.common.BulkDeleteRequest;
|
||||
import com.petshop.backend.util.StringUtils;
|
||||
import com.petshop.backend.dto.inventory.InventoryRequest;
|
||||
import com.petshop.backend.dto.inventory.InventoryResponse;
|
||||
import com.petshop.backend.entity.Inventory;
|
||||
@@ -29,7 +30,7 @@ public class InventoryService {
|
||||
}
|
||||
|
||||
public Page<InventoryResponse> getAllInventory(String query, Long storeId, Pageable pageable) {
|
||||
String normalizedQuery = normalizeFilter(query);
|
||||
String normalizedQuery = StringUtils.trimToNull(query);
|
||||
Page<Inventory> inventory = inventoryRepository.searchInventory(normalizedQuery, storeId, pageable);
|
||||
return inventory.map(this::mapToResponse);
|
||||
}
|
||||
@@ -93,14 +94,6 @@ public class InventoryService {
|
||||
inventoryRepository.deleteAllById(request.getIds());
|
||||
}
|
||||
|
||||
private String normalizeFilter(String value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
String trimmed = value.trim();
|
||||
return trimmed.isEmpty() ? null : trimmed;
|
||||
}
|
||||
|
||||
private InventoryResponse mapToResponse(Inventory inventory) {
|
||||
StoreLocation store = inventory.getStore();
|
||||
return new InventoryResponse(
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.petshop.backend.entity.PasswordResetToken;
|
||||
import com.petshop.backend.entity.User;
|
||||
import com.petshop.backend.exception.BusinessException;
|
||||
import com.petshop.backend.repository.PasswordResetTokenRepository;
|
||||
import com.petshop.backend.util.StringUtils;
|
||||
import com.petshop.backend.repository.UserRepository;
|
||||
import com.petshop.backend.security.UserAuthCacheService;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
@@ -47,7 +48,7 @@ public class PasswordResetService {
|
||||
|
||||
@Transactional
|
||||
public ForgotPasswordResponse createResetToken(String usernameOrEmail) {
|
||||
String normalized = trimToNull(usernameOrEmail);
|
||||
String normalized = StringUtils.trimToNull(usernameOrEmail);
|
||||
if (normalized == null) {
|
||||
throw new BusinessException("Username or email is required");
|
||||
}
|
||||
@@ -83,7 +84,7 @@ public class PasswordResetService {
|
||||
|
||||
@Transactional
|
||||
public ResetPasswordResponse resetPassword(String rawToken, String newPassword) {
|
||||
String normalizedToken = trimToNull(rawToken);
|
||||
String normalizedToken = StringUtils.trimToNull(rawToken);
|
||||
if (normalizedToken == null) {
|
||||
throw new BusinessException("Reset token is required");
|
||||
}
|
||||
@@ -136,11 +137,4 @@ public class PasswordResetService {
|
||||
}
|
||||
}
|
||||
|
||||
private String trimToNull(String value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
String trimmed = value.trim();
|
||||
return trimmed.isEmpty() ? null : trimmed;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.petshop.backend.service;
|
||||
|
||||
import com.petshop.backend.dto.common.BulkDeleteRequest;
|
||||
import com.petshop.backend.util.StringUtils;
|
||||
import com.petshop.backend.dto.pet.MyPetRequest;
|
||||
import com.petshop.backend.dto.pet.MyPetResponse;
|
||||
import com.petshop.backend.dto.pet.PetRequest;
|
||||
@@ -53,10 +54,10 @@ public class PetService {
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public Page<PetResponse> getAllPets(String query, String species, String breed, String status, Long storeId, Long customerId, Pageable pageable) {
|
||||
String normalizedQuery = normalizeFilter(query);
|
||||
String normalizedSpecies = normalizeFilter(species);
|
||||
String normalizedBreed = normalizeFilter(breed);
|
||||
String normalizedStatus = normalizeFilter(status);
|
||||
String normalizedQuery = StringUtils.trimToNull(query);
|
||||
String normalizedSpecies = StringUtils.trimToNull(species);
|
||||
String normalizedBreed = StringUtils.trimToNull(breed);
|
||||
String normalizedStatus = StringUtils.trimToNull(status);
|
||||
CurrentViewer viewer = getCurrentViewer();
|
||||
|
||||
Page<Pet> pets;
|
||||
@@ -323,14 +324,6 @@ public class PetService {
|
||||
return status == null || "available".equalsIgnoreCase(status) || "adopted".equalsIgnoreCase(status) || "owned".equalsIgnoreCase(status);
|
||||
}
|
||||
|
||||
private String normalizeFilter(String value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
String trimmed = value.trim();
|
||||
return trimmed.isEmpty() ? null : trimmed;
|
||||
}
|
||||
|
||||
private PetResponse mapToResponse(Pet pet) {
|
||||
User owner = pet.getOwner();
|
||||
StoreLocation store = pet.getStore();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.petshop.backend.service;
|
||||
|
||||
import com.petshop.backend.dto.common.BulkDeleteRequest;
|
||||
import com.petshop.backend.util.StringUtils;
|
||||
import com.petshop.backend.dto.product.ProductRequest;
|
||||
import com.petshop.backend.dto.product.ProductResponse;
|
||||
import com.petshop.backend.entity.Category;
|
||||
@@ -38,7 +39,7 @@ public class ProductService {
|
||||
}
|
||||
|
||||
public Page<ProductResponse> getAllProducts(String query, Long categoryId, Pageable pageable) {
|
||||
return productRepository.searchProducts(normalizeFilter(query), categoryId, pageable)
|
||||
return productRepository.searchProducts(StringUtils.trimToNull(query), categoryId, pageable)
|
||||
.map(this::mapToResponse);
|
||||
}
|
||||
|
||||
@@ -178,11 +179,4 @@ public class ProductService {
|
||||
public record ImagePayload(Resource resource, MediaType mediaType) {
|
||||
}
|
||||
|
||||
private String normalizeFilter(String value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
String trimmed = value.trim();
|
||||
return trimmed.isEmpty() ? null : trimmed;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.petshop.backend.service;
|
||||
|
||||
import com.petshop.backend.dto.productsupplier.BulkDeleteProductSupplierRequest;
|
||||
import com.petshop.backend.util.StringUtils;
|
||||
import com.petshop.backend.dto.productsupplier.ProductSupplierRequest;
|
||||
import com.petshop.backend.dto.productsupplier.ProductSupplierResponse;
|
||||
import com.petshop.backend.entity.Product;
|
||||
@@ -34,7 +35,7 @@ public class ProductSupplierService {
|
||||
}
|
||||
|
||||
public Page<ProductSupplierResponse> getAllProductSuppliers(String query, Long productId, Long supplierId, Pageable pageable) {
|
||||
String normalizedQuery = normalizeFilter(query);
|
||||
String normalizedQuery = StringUtils.trimToNull(query);
|
||||
Pageable mappedPageable = mapSortProperties(pageable);
|
||||
Page<ProductSupplier> productSuppliers = productSupplierRepository.searchProductSuppliers(normalizedQuery, productId, supplierId, mappedPageable);
|
||||
return productSuppliers.map(this::mapToResponse);
|
||||
@@ -97,14 +98,6 @@ public class ProductSupplierService {
|
||||
});
|
||||
}
|
||||
|
||||
private String normalizeFilter(String value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
String trimmed = value.trim();
|
||||
return trimmed.isEmpty() ? null : trimmed;
|
||||
}
|
||||
|
||||
private Pageable mapSortProperties(Pageable pageable) {
|
||||
if (pageable.getSort().isUnsorted()) {
|
||||
return pageable;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.petshop.backend.service;
|
||||
|
||||
import com.petshop.backend.dto.purchaseorder.PurchaseOrderResponse;
|
||||
import com.petshop.backend.util.StringUtils;
|
||||
import com.petshop.backend.entity.PurchaseOrder;
|
||||
import com.petshop.backend.entity.StoreLocation;
|
||||
import com.petshop.backend.exception.ResourceNotFoundException;
|
||||
@@ -19,7 +20,7 @@ public class PurchaseOrderService {
|
||||
}
|
||||
|
||||
public Page<PurchaseOrderResponse> getAllPurchaseOrders(String query, Long storeId, Pageable pageable) {
|
||||
String normalizedQuery = normalizeFilter(query);
|
||||
String normalizedQuery = StringUtils.trimToNull(query);
|
||||
Page<PurchaseOrder> purchaseOrders = purchaseOrderRepository.searchPurchaseOrders(normalizedQuery, storeId, pageable);
|
||||
return purchaseOrders.map(this::mapToResponse);
|
||||
}
|
||||
@@ -30,14 +31,6 @@ public class PurchaseOrderService {
|
||||
return mapToResponse(purchaseOrder);
|
||||
}
|
||||
|
||||
private String normalizeFilter(String value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
String trimmed = value.trim();
|
||||
return trimmed.isEmpty() ? null : trimmed;
|
||||
}
|
||||
|
||||
private PurchaseOrderResponse mapToResponse(PurchaseOrder purchaseOrder) {
|
||||
StoreLocation store = purchaseOrder.getStore();
|
||||
return new PurchaseOrderResponse(
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.petshop.backend.exception.ResourceNotFoundException;
|
||||
import com.petshop.backend.event.SaleReceiptEvent;
|
||||
import com.petshop.backend.repository.*;
|
||||
import com.petshop.backend.util.AuthenticationHelper;
|
||||
import com.petshop.backend.util.StringUtils;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
@@ -32,23 +33,25 @@ public class SaleService {
|
||||
private final InventoryRepository inventoryRepository;
|
||||
private final UserRepository userRepository;
|
||||
private final CouponRepository couponRepository;
|
||||
private final CouponService couponService;
|
||||
private final CartRepository cartRepository;
|
||||
private final ApplicationEventPublisher eventPublisher;
|
||||
|
||||
public SaleService(SaleRepository saleRepository, ProductRepository productRepository, StoreRepository storeRepository, InventoryRepository inventoryRepository, UserRepository userRepository, CouponRepository couponRepository, CartRepository cartRepository, ApplicationEventPublisher eventPublisher) {
|
||||
public SaleService(SaleRepository saleRepository, ProductRepository productRepository, StoreRepository storeRepository, InventoryRepository inventoryRepository, UserRepository userRepository, CouponRepository couponRepository, CouponService couponService, CartRepository cartRepository, ApplicationEventPublisher eventPublisher) {
|
||||
this.saleRepository = saleRepository;
|
||||
this.productRepository = productRepository;
|
||||
this.storeRepository = storeRepository;
|
||||
this.inventoryRepository = inventoryRepository;
|
||||
this.userRepository = userRepository;
|
||||
this.couponRepository = couponRepository;
|
||||
this.couponService = couponService;
|
||||
this.cartRepository = cartRepository;
|
||||
this.eventPublisher = eventPublisher;
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public Page<SaleResponse> getAllSales(String query, String paymentMethod, Long storeId, Boolean isRefund, Long customerId, Pageable pageable) {
|
||||
Page<Sale> sales = saleRepository.searchSales(normalizeFilter(query), normalizeFilter(paymentMethod), storeId, isRefund, customerId, pageable);
|
||||
Page<Sale> sales = saleRepository.searchSales(StringUtils.trimToNull(query), StringUtils.trimToNull(paymentMethod), storeId, isRefund, customerId, pageable);
|
||||
return sales.map(this::mapToResponse);
|
||||
}
|
||||
|
||||
@@ -86,7 +89,7 @@ public class SaleService {
|
||||
if (request.getCouponId() != null) {
|
||||
Coupon coupon = couponRepository.findByIdForUpdate(request.getCouponId())
|
||||
.orElseThrow(() -> new ResourceNotFoundException("Coupon not found with id: " + request.getCouponId()));
|
||||
validateCoupon(coupon);
|
||||
couponService.validateCouponForUse(coupon);
|
||||
sale.setCoupon(coupon);
|
||||
}
|
||||
|
||||
@@ -236,7 +239,7 @@ public class SaleService {
|
||||
}
|
||||
sale.setSubtotalAmount(subtotalAmount);
|
||||
|
||||
BigDecimal couponDiscount = calculateCouponDiscount(sale.getCoupon(), subtotalAmount);
|
||||
BigDecimal couponDiscount = couponService.calculateDiscount(sale.getCoupon(), subtotalAmount);
|
||||
sale.setCouponDiscountAmount(couponDiscount);
|
||||
|
||||
BigDecimal employeeDiscount = calculateEmployeeDiscount(customer, subtotalAmount.subtract(couponDiscount));
|
||||
@@ -282,45 +285,6 @@ public class SaleService {
|
||||
return mapToResponse(savedSale);
|
||||
}
|
||||
|
||||
private void validateCoupon(Coupon coupon) {
|
||||
if (!Boolean.TRUE.equals(coupon.getActive())) {
|
||||
throw new BusinessException("Coupon is not active");
|
||||
}
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
if (coupon.getStartsAt() != null && now.isBefore(coupon.getStartsAt())) {
|
||||
throw new BusinessException("Coupon has not started yet");
|
||||
}
|
||||
if (coupon.getEndsAt() != null && now.isAfter(coupon.getEndsAt())) {
|
||||
throw new BusinessException("Coupon has expired");
|
||||
}
|
||||
if (coupon.getUsageLimit() != null) {
|
||||
long used = saleRepository.countByCoupon_CouponId(coupon.getCouponId());
|
||||
if (used >= coupon.getUsageLimit()) {
|
||||
throw new BusinessException("Coupon usage limit has been reached");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private BigDecimal calculateCouponDiscount(Coupon coupon, BigDecimal subtotal) {
|
||||
if (coupon == null || subtotal.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
if (coupon.getMinOrderAmount() != null && subtotal.compareTo(coupon.getMinOrderAmount()) < 0) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
BigDecimal discount = BigDecimal.ZERO;
|
||||
String type = coupon.getDiscountType().trim().toUpperCase();
|
||||
if ("PERCENTAGE".equals(type) || "PERCENT".equals(type)) {
|
||||
discount = subtotal.multiply(coupon.getDiscountValue().divide(new BigDecimal("100"), 4, RoundingMode.HALF_UP));
|
||||
} else if ("FIXED".equals(type)) {
|
||||
discount = coupon.getDiscountValue();
|
||||
}
|
||||
|
||||
return discount.min(subtotal).setScale(2, RoundingMode.HALF_UP);
|
||||
}
|
||||
|
||||
private BigDecimal calculateEmployeeDiscount(User customer, BigDecimal remainingAmount) {
|
||||
if (customer == null || remainingAmount.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
return BigDecimal.ZERO;
|
||||
@@ -419,14 +383,6 @@ public class SaleService {
|
||||
return response;
|
||||
}
|
||||
|
||||
private String normalizeFilter(String value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
String trimmed = value.trim();
|
||||
return trimmed.isEmpty() ? null : trimmed;
|
||||
}
|
||||
|
||||
String normalizePaymentMethod(String paymentMethod) {
|
||||
if (paymentMethod == null) {
|
||||
return null;
|
||||
|
||||
@@ -10,6 +10,7 @@ import com.petshop.backend.repository.StoreRepository;
|
||||
import com.petshop.backend.repository.UserRepository;
|
||||
import com.petshop.backend.security.UserAuthCacheService;
|
||||
import com.petshop.backend.util.AuthenticationHelper;
|
||||
import com.petshop.backend.util.StringUtils;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
@@ -81,7 +82,7 @@ public class UserService {
|
||||
requireRequestedRole(request.getRole(), requiredRole);
|
||||
|
||||
User user = new User();
|
||||
user.setUsername(trimToNull(request.getUsername()));
|
||||
user.setUsername(StringUtils.trimToNull(request.getUsername()));
|
||||
if (request.getPassword() != null && !request.getPassword().trim().isEmpty()) {
|
||||
user.setPassword(passwordEncoder.encode(request.getPassword()));
|
||||
}
|
||||
@@ -89,9 +90,9 @@ public class UserService {
|
||||
user.setLastName(request.getLastName());
|
||||
user.setFullName(request.getFullName());
|
||||
user.setEmail(request.getEmail());
|
||||
user.setPhone(trimToNull(request.getPhone()));
|
||||
user.setPhone(StringUtils.trimToNull(request.getPhone()));
|
||||
user.setRole(request.getRole());
|
||||
user.setStaffRole(trimToNull(request.getStaffRole()));
|
||||
user.setStaffRole(StringUtils.trimToNull(request.getStaffRole()));
|
||||
user.setPrimaryStore(resolveStore(request.getPrimaryStoreId()));
|
||||
user.setActive(request.getActive() != null ? request.getActive() : true);
|
||||
if (request.getLoyaltyPoints() != null) {
|
||||
@@ -124,7 +125,7 @@ public class UserService {
|
||||
|| user.getRole() != request.getRole()
|
||||
|| !user.getActive().equals(request.getActive() != null ? request.getActive() : true);
|
||||
|
||||
user.setUsername(trimToNull(request.getUsername()));
|
||||
user.setUsername(StringUtils.trimToNull(request.getUsername()));
|
||||
if (request.getPassword() != null && !request.getPassword().trim().isEmpty()) {
|
||||
user.setPassword(passwordEncoder.encode(request.getPassword()));
|
||||
invalidateToken = true;
|
||||
@@ -133,13 +134,13 @@ public class UserService {
|
||||
user.setLastName(request.getLastName());
|
||||
user.setFullName(request.getFullName());
|
||||
user.setEmail(request.getEmail());
|
||||
String phone = trimToNull(request.getPhone());
|
||||
String phone = StringUtils.trimToNull(request.getPhone());
|
||||
if (!Objects.equals(user.getPhone(), phone)) {
|
||||
validateUniquePhone(phone, user.getId());
|
||||
}
|
||||
user.setPhone(phone);
|
||||
user.setRole(request.getRole());
|
||||
user.setStaffRole(trimToNull(request.getStaffRole()));
|
||||
user.setStaffRole(StringUtils.trimToNull(request.getStaffRole()));
|
||||
user.setPrimaryStore(resolveStore(request.getPrimaryStoreId()));
|
||||
user.setActive(request.getActive() != null ? request.getActive() : true);
|
||||
if (request.getLoyaltyPoints() != null) {
|
||||
@@ -277,16 +278,8 @@ public class UserService {
|
||||
});
|
||||
}
|
||||
|
||||
private String trimToNull(String value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
String trimmed = value.trim();
|
||||
return trimmed.isEmpty() ? null : trimmed;
|
||||
}
|
||||
|
||||
private User.Role parseRole(String role) {
|
||||
String normalizedRole = trimToNull(role);
|
||||
String normalizedRole = StringUtils.trimToNull(role);
|
||||
if (normalizedRole == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -33,6 +33,21 @@ public class AuthenticationHelper {
|
||||
return getAuthenticatedPrincipal().getUserId();
|
||||
}
|
||||
|
||||
public static User.Role getAuthenticatedRole() {
|
||||
return getAuthenticatedPrincipal().getRole();
|
||||
}
|
||||
|
||||
public static boolean isCustomer() {
|
||||
return getAuthenticatedPrincipal().getRole() == User.Role.CUSTOMER;
|
||||
}
|
||||
|
||||
public static Long getCustomerIdOrNull(UserRepository userRepository) {
|
||||
if (!isCustomer()) {
|
||||
return null;
|
||||
}
|
||||
return getAuthenticatedUser(userRepository).getId();
|
||||
}
|
||||
|
||||
public static User getAuthenticatedUser(UserRepository userRepository) {
|
||||
Authentication authentication = getAuthentication();
|
||||
Object principal = authentication.getPrincipal();
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.petshop.backend.util;
|
||||
|
||||
import com.petshop.backend.exception.BusinessException;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public final class ImageValidationUtil {
|
||||
|
||||
public static final long MAX_IMAGE_SIZE = 5 * 1024 * 1024;
|
||||
|
||||
private ImageValidationUtil() {}
|
||||
|
||||
public static void validate(MultipartFile file) {
|
||||
if (file.isEmpty()) {
|
||||
throw new BusinessException("Please select an image to upload");
|
||||
}
|
||||
if (file.getSize() > MAX_IMAGE_SIZE) {
|
||||
throw new BusinessException("Image file size must be less than 5MB");
|
||||
}
|
||||
String contentType = file.getContentType();
|
||||
if (contentType == null) {
|
||||
throw new BusinessException("Only JPG, PNG, and GIF images are allowed");
|
||||
}
|
||||
String normalized = contentType.toLowerCase(Locale.ROOT);
|
||||
if (!normalized.equals("image/jpeg") && !normalized.equals("image/png") && !normalized.equals("image/gif")) {
|
||||
throw new BusinessException("Only JPG, PNG, and GIF images are allowed");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.petshop.backend.util;
|
||||
|
||||
public final class StringUtils {
|
||||
|
||||
private StringUtils() {}
|
||||
|
||||
public static String trimToNull(String value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
String trimmed = value.trim();
|
||||
return trimmed.isEmpty() ? null : trimmed;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user