diff --git a/pom.xml b/pom.xml
index 1803f3ec..4357996d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -130,6 +130,7 @@
docker-compose.dev.yml
down
-v
+ --remove-orphans
diff --git a/src/main/java/com/petshop/backend/config/DataInitializer.java b/src/main/java/com/petshop/backend/config/DataInitializer.java
index a9dd4b15..cff00f6c 100644
--- a/src/main/java/com/petshop/backend/config/DataInitializer.java
+++ b/src/main/java/com/petshop/backend/config/DataInitializer.java
@@ -2,6 +2,7 @@ package com.petshop.backend.config;
import com.petshop.backend.entity.User;
import com.petshop.backend.repository.UserRepository;
+import com.petshop.backend.service.StoreAssignmentService;
import com.petshop.backend.service.UserBusinessLinkageService;
import org.springframework.boot.CommandLineRunner;
import org.springframework.security.crypto.password.PasswordEncoder;
@@ -13,11 +14,13 @@ public class DataInitializer implements CommandLineRunner {
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
private final UserBusinessLinkageService userBusinessLinkageService;
+ private final StoreAssignmentService storeAssignmentService;
- public DataInitializer(UserRepository userRepository, PasswordEncoder passwordEncoder, UserBusinessLinkageService userBusinessLinkageService) {
+ public DataInitializer(UserRepository userRepository, PasswordEncoder passwordEncoder, UserBusinessLinkageService userBusinessLinkageService, StoreAssignmentService storeAssignmentService) {
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder;
this.userBusinessLinkageService = userBusinessLinkageService;
+ this.storeAssignmentService = storeAssignmentService;
}
@Override
@@ -62,7 +65,7 @@ public class DataInitializer implements CommandLineRunner {
}
}
// Ensure linked employee
- userBusinessLinkageService.ensureLinkedEmployee(admin);
+ storeAssignmentService.assignStoreIfMissing(userBusinessLinkageService.ensureLinkedEmployee(admin), 1L);
User staff = userRepository.findByUsername("staff").orElse(null);
if (staff == null) {
@@ -102,7 +105,7 @@ public class DataInitializer implements CommandLineRunner {
}
}
// Ensure linked employee
- userBusinessLinkageService.ensureLinkedEmployee(staff);
+ storeAssignmentService.assignStoreIfMissing(userBusinessLinkageService.ensureLinkedEmployee(staff), 1L);
User customer = userRepository.findByUsername("customer").orElse(null);
if (customer == null) {
diff --git a/src/main/java/com/petshop/backend/controller/AuthController.java b/src/main/java/com/petshop/backend/controller/AuthController.java
index 7aa04307..b5bc1900 100644
--- a/src/main/java/com/petshop/backend/controller/AuthController.java
+++ b/src/main/java/com/petshop/backend/controller/AuthController.java
@@ -17,6 +17,7 @@ import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
+import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
@@ -126,6 +127,13 @@ public class AuthController {
Map error = new HashMap<>();
error.put("message", "Invalid username or password");
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(error);
+ } catch (InternalAuthenticationServiceException e) {
+ if (e.getCause() instanceof DisabledException disabledException) {
+ Map error = new HashMap<>();
+ error.put("message", disabledException.getMessage());
+ return ResponseEntity.status(HttpStatus.FORBIDDEN).body(error);
+ }
+ throw e;
} catch (DisabledException e) {
Map error = new HashMap<>();
error.put("message", e.getMessage());
diff --git a/src/main/java/com/petshop/backend/exception/GlobalExceptionHandler.java b/src/main/java/com/petshop/backend/exception/GlobalExceptionHandler.java
index 40e95bbc..bfcfe03d 100644
--- a/src/main/java/com/petshop/backend/exception/GlobalExceptionHandler.java
+++ b/src/main/java/com/petshop/backend/exception/GlobalExceptionHandler.java
@@ -2,6 +2,7 @@ package com.petshop.backend.exception;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
+import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
@@ -71,6 +72,16 @@ public class GlobalExceptionHandler {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(error);
}
+ @ExceptionHandler(DataIntegrityViolationException.class)
+ public ResponseEntity handleDataIntegrityViolationException(DataIntegrityViolationException ex) {
+ ErrorResponse error = new ErrorResponse(
+ HttpStatus.BAD_REQUEST.value(),
+ "Operation violates existing data relationships",
+ LocalDateTime.now()
+ );
+ return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(error);
+ }
+
@ExceptionHandler(Exception.class)
public ResponseEntity handleGenericException(Exception ex) {
ErrorResponse error = new ErrorResponse(
diff --git a/src/main/java/com/petshop/backend/service/StoreAssignmentService.java b/src/main/java/com/petshop/backend/service/StoreAssignmentService.java
new file mode 100644
index 00000000..31cc18d5
--- /dev/null
+++ b/src/main/java/com/petshop/backend/service/StoreAssignmentService.java
@@ -0,0 +1,34 @@
+package com.petshop.backend.service;
+
+import com.petshop.backend.entity.Employee;
+import com.petshop.backend.entity.EmployeeStore;
+import com.petshop.backend.entity.StoreLocation;
+import com.petshop.backend.exception.ResourceNotFoundException;
+import com.petshop.backend.repository.EmployeeStoreRepository;
+import com.petshop.backend.repository.StoreRepository;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Service
+public class StoreAssignmentService {
+
+ private final EmployeeStoreRepository employeeStoreRepository;
+ private final StoreRepository storeRepository;
+
+ public StoreAssignmentService(EmployeeStoreRepository employeeStoreRepository, StoreRepository storeRepository) {
+ this.employeeStoreRepository = employeeStoreRepository;
+ this.storeRepository = storeRepository;
+ }
+
+ @Transactional
+ public void assignStoreIfMissing(Employee employee, Long storeId) {
+ if (employeeStoreRepository.findByEmployeeEmployeeId(employee.getEmployeeId()).isPresent()) {
+ return;
+ }
+
+ StoreLocation store = storeRepository.findById(storeId)
+ .orElseThrow(() -> new ResourceNotFoundException("Store not found with id: " + storeId));
+
+ employeeStoreRepository.save(new EmployeeStore(employee, store));
+ }
+}