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