From a0d14e493f96414202b72ef7e665900df7f66124 Mon Sep 17 00:00:00 2001 From: Harkamal Randhawa Date: Sun, 8 Mar 2026 21:56:04 -0600 Subject: [PATCH] Fix backend user contract and add User-Employee-Customer linkage - Add active field to User entity and users table - Add userId linkage to Employee and Customer entities with unique constraints and FKs - Add repository methods findByUserId and findAllByEmail - Create UserBusinessLinkageService for shared employee/customer creation logic - Create AuthenticationHelper utility for resolving authenticated users - Update UserService to persist all user fields and create linked business entities - Update AuthController register to set active and create linked customer - Update DataInitializer to be idempotent and use shared linkage service - Update Postman collection user endpoints with fullName, email, and active --- petshop-api.postman_collection.json | 4 +- .../backend/config/DataInitializer.java | 101 +++++++++++-- .../backend/controller/AuthController.java | 9 +- .../com/petshop/backend/entity/Customer.java | 15 +- .../com/petshop/backend/entity/Employee.java | 15 +- .../java/com/petshop/backend/entity/User.java | 15 +- .../repository/CustomerRepository.java | 6 + .../repository/EmployeeRepository.java | 5 + .../service/UserBusinessLinkageService.java | 138 ++++++++++++++++++ .../petshop/backend/service/UserService.java | 23 ++- .../backend/util/AuthenticationHelper.java | 38 +++++ src/main/resources/schema.sql | 13 +- 12 files changed, 363 insertions(+), 19 deletions(-) create mode 100644 src/main/java/com/petshop/backend/service/UserBusinessLinkageService.java create mode 100644 src/main/java/com/petshop/backend/util/AuthenticationHelper.java diff --git a/petshop-api.postman_collection.json b/petshop-api.postman_collection.json index 340eeb2c..abc9124c 100644 --- a/petshop-api.postman_collection.json +++ b/petshop-api.postman_collection.json @@ -1435,7 +1435,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"username\": \"newuser\",\n \"password\": \"password123\",\n \"role\": \"STAFF\"\n}" + "raw": "{\n \"username\": \"newuser\",\n \"password\": \"password123\",\n \"fullName\": \"New User\",\n \"email\": \"newuser@petshop.com\",\n \"role\": \"STAFF\",\n \"active\": true\n}" } } }, @@ -1457,7 +1457,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"username\": \"user1\",\n \"role\": \"STAFF\"\n}" + "raw": "{\n \"username\": \"user1\",\n \"password\": \"newpassword123\",\n \"fullName\": \"Updated User\",\n \"email\": \"user1@petshop.com\",\n \"role\": \"STAFF\",\n \"active\": true\n}" } } }, diff --git a/src/main/java/com/petshop/backend/config/DataInitializer.java b/src/main/java/com/petshop/backend/config/DataInitializer.java index 0d9c9395..a9dd4b15 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.UserBusinessLinkageService; import org.springframework.boot.CommandLineRunner; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Component; @@ -11,57 +12,137 @@ public class DataInitializer implements CommandLineRunner { private final UserRepository userRepository; private final PasswordEncoder passwordEncoder; + private final UserBusinessLinkageService userBusinessLinkageService; - public DataInitializer(UserRepository userRepository, PasswordEncoder passwordEncoder) { + public DataInitializer(UserRepository userRepository, PasswordEncoder passwordEncoder, UserBusinessLinkageService userBusinessLinkageService) { this.userRepository = userRepository; this.passwordEncoder = passwordEncoder; + this.userBusinessLinkageService = userBusinessLinkageService; } @Override public void run(String... args) { System.out.println("==== DataInitializer: Starting user creation ===="); - if (userRepository.findByUsername("admin").isEmpty()) { + User admin = userRepository.findByUsername("admin").orElse(null); + if (admin == null) { System.out.println("Creating admin user..."); - User admin = new User(); + admin = new User(); admin.setUsername("admin"); admin.setPassword(passwordEncoder.encode("admin123")); admin.setEmail("admin@petshop.com"); admin.setFullName("Admin User"); admin.setRole(User.Role.ADMIN); - userRepository.save(admin); + admin.setActive(true); + admin = userRepository.save(admin); System.out.println("Admin user created successfully"); } else { System.out.println("Admin user already exists"); + // Normalize missing fields if needed + boolean updated = false; + if (admin.getFullName() == null || admin.getFullName().isEmpty()) { + admin.setFullName("Admin User"); + updated = true; + } + if (admin.getEmail() == null || admin.getEmail().isEmpty()) { + admin.setEmail("admin@petshop.com"); + updated = true; + } + if (admin.getActive() == null) { + admin.setActive(true); + updated = true; + } + if (admin.getRole() == null) { + admin.setRole(User.Role.ADMIN); + updated = true; + } + if (updated) { + admin = userRepository.save(admin); + System.out.println("Admin user normalized"); + } } + // Ensure linked employee + userBusinessLinkageService.ensureLinkedEmployee(admin); - if (userRepository.findByUsername("staff").isEmpty()) { + User staff = userRepository.findByUsername("staff").orElse(null); + if (staff == null) { System.out.println("Creating staff user..."); - User staff = new User(); + staff = new User(); staff.setUsername("staff"); staff.setPassword(passwordEncoder.encode("staff123")); staff.setEmail("staff@petshop.com"); staff.setFullName("Staff User"); staff.setRole(User.Role.STAFF); - userRepository.save(staff); + staff.setActive(true); + staff = userRepository.save(staff); System.out.println("Staff user created successfully"); } else { System.out.println("Staff user already exists"); + // Normalize missing fields if needed + boolean updated = false; + if (staff.getFullName() == null || staff.getFullName().isEmpty()) { + staff.setFullName("Staff User"); + updated = true; + } + if (staff.getEmail() == null || staff.getEmail().isEmpty()) { + staff.setEmail("staff@petshop.com"); + updated = true; + } + if (staff.getActive() == null) { + staff.setActive(true); + updated = true; + } + if (staff.getRole() == null) { + staff.setRole(User.Role.STAFF); + updated = true; + } + if (updated) { + staff = userRepository.save(staff); + System.out.println("Staff user normalized"); + } } + // Ensure linked employee + userBusinessLinkageService.ensureLinkedEmployee(staff); - if (userRepository.findByUsername("customer").isEmpty()) { + User customer = userRepository.findByUsername("customer").orElse(null); + if (customer == null) { System.out.println("Creating customer user..."); - User customer = new User(); + customer = new User(); customer.setUsername("customer"); customer.setPassword(passwordEncoder.encode("customer123")); customer.setEmail("customer@petshop.com"); customer.setFullName("Test Customer"); customer.setRole(User.Role.CUSTOMER); - userRepository.save(customer); + customer.setActive(true); + customer = userRepository.save(customer); System.out.println("Customer user created successfully"); } else { System.out.println("Customer user already exists"); + // Normalize missing fields if needed + boolean updated = false; + if (customer.getFullName() == null || customer.getFullName().isEmpty()) { + customer.setFullName("Test Customer"); + updated = true; + } + if (customer.getEmail() == null || customer.getEmail().isEmpty()) { + customer.setEmail("customer@petshop.com"); + updated = true; + } + if (customer.getActive() == null) { + customer.setActive(true); + updated = true; + } + if (customer.getRole() == null) { + customer.setRole(User.Role.CUSTOMER); + updated = true; + } + if (updated) { + customer = userRepository.save(customer); + System.out.println("Customer user normalized"); + } } + // Ensure linked customer + userBusinessLinkageService.ensureLinkedCustomer(customer); System.out.println("==== DataInitializer: Completed ===="); } diff --git a/src/main/java/com/petshop/backend/controller/AuthController.java b/src/main/java/com/petshop/backend/controller/AuthController.java index ae28d126..22f53420 100644 --- a/src/main/java/com/petshop/backend/controller/AuthController.java +++ b/src/main/java/com/petshop/backend/controller/AuthController.java @@ -10,6 +10,7 @@ import com.petshop.backend.dto.auth.UserInfoResponse; import com.petshop.backend.entity.User; import com.petshop.backend.repository.UserRepository; import com.petshop.backend.security.JwtUtil; +import com.petshop.backend.service.UserBusinessLinkageService; import jakarta.validation.Valid; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -42,12 +43,14 @@ public class AuthController { private final UserRepository userRepository; private final JwtUtil jwtUtil; private final PasswordEncoder passwordEncoder; + private final UserBusinessLinkageService userBusinessLinkageService; - public AuthController(AuthenticationManager authenticationManager, UserRepository userRepository, JwtUtil jwtUtil, PasswordEncoder passwordEncoder) { + public AuthController(AuthenticationManager authenticationManager, UserRepository userRepository, JwtUtil jwtUtil, PasswordEncoder passwordEncoder, UserBusinessLinkageService userBusinessLinkageService) { this.authenticationManager = authenticationManager; this.userRepository = userRepository; this.jwtUtil = jwtUtil; this.passwordEncoder = passwordEncoder; + this.userBusinessLinkageService = userBusinessLinkageService; } @PostMapping("/register") @@ -70,9 +73,13 @@ public class AuthController { user.setEmail(request.getEmail()); user.setFullName(request.getFullName()); user.setRole(User.Role.CUSTOMER); + user.setActive(true); User savedUser = userRepository.save(user); + // Create or link customer record + userBusinessLinkageService.ensureLinkedCustomer(savedUser); + UserDetails userDetails = new org.springframework.security.core.userdetails.User( savedUser.getUsername(), savedUser.getPassword(), diff --git a/src/main/java/com/petshop/backend/entity/Customer.java b/src/main/java/com/petshop/backend/entity/Customer.java index 661f9d80..1cfa858b 100644 --- a/src/main/java/com/petshop/backend/entity/Customer.java +++ b/src/main/java/com/petshop/backend/entity/Customer.java @@ -15,6 +15,9 @@ public class Customer { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long customerId; + @Column(name = "user_id") + private Long userId; + @Column(nullable = false, length = 50) private String firstName; @@ -38,8 +41,9 @@ public class Customer { public Customer() { } - public Customer(Long customerId, String firstName, String lastName, String email, String phone, LocalDateTime createdAt, LocalDateTime updatedAt) { + public Customer(Long customerId, Long userId, String firstName, String lastName, String email, String phone, LocalDateTime createdAt, LocalDateTime updatedAt) { this.customerId = customerId; + this.userId = userId; this.firstName = firstName; this.lastName = lastName; this.email = email; @@ -56,6 +60,14 @@ public class Customer { this.customerId = customerId; } + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + public String getFirstName() { return firstName; } @@ -121,6 +133,7 @@ public class Customer { public String toString() { return "Customer{" + "customerId=" + customerId + + ", userId=" + userId + ", firstName='" + firstName + '\'' + ", lastName='" + lastName + '\'' + ", email='" + email + '\'' + diff --git a/src/main/java/com/petshop/backend/entity/Employee.java b/src/main/java/com/petshop/backend/entity/Employee.java index 573a446f..9e825a61 100644 --- a/src/main/java/com/petshop/backend/entity/Employee.java +++ b/src/main/java/com/petshop/backend/entity/Employee.java @@ -15,6 +15,9 @@ public class Employee { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long employeeId; + @Column(name = "user_id") + private Long userId; + @Column(nullable = false, length = 50) private String firstName; @@ -44,8 +47,9 @@ public class Employee { public Employee() { } - public Employee(Long employeeId, String firstName, String lastName, String email, String phone, String role, Boolean isActive, LocalDateTime createdAt, LocalDateTime updatedAt) { + public Employee(Long employeeId, Long userId, String firstName, String lastName, String email, String phone, String role, Boolean isActive, LocalDateTime createdAt, LocalDateTime updatedAt) { this.employeeId = employeeId; + this.userId = userId; this.firstName = firstName; this.lastName = lastName; this.email = email; @@ -64,6 +68,14 @@ public class Employee { this.employeeId = employeeId; } + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + public String getFirstName() { return firstName; } @@ -145,6 +157,7 @@ public class Employee { public String toString() { return "Employee{" + "employeeId=" + employeeId + + ", userId=" + userId + ", firstName='" + firstName + '\'' + ", lastName='" + lastName + '\'' + ", email='" + email + '\'' + diff --git a/src/main/java/com/petshop/backend/entity/User.java b/src/main/java/com/petshop/backend/entity/User.java index 6ef37551..7a2cf43a 100644 --- a/src/main/java/com/petshop/backend/entity/User.java +++ b/src/main/java/com/petshop/backend/entity/User.java @@ -34,6 +34,9 @@ public class User { @Column(nullable = false, length = 20, columnDefinition = "VARCHAR(20)") private Role role; + @Column(nullable = false) + private Boolean active = true; + @CreationTimestamp @Column(name = "created_at", updatable = false) private LocalDateTime createdAt; @@ -49,7 +52,7 @@ public class User { public User() { } - public User(Long id, String username, String password, String email, String fullName, String avatarUrl, Role role, LocalDateTime createdAt, LocalDateTime updatedAt) { + public User(Long id, String username, String password, String email, String fullName, String avatarUrl, Role role, Boolean active, LocalDateTime createdAt, LocalDateTime updatedAt) { this.id = id; this.username = username; this.password = password; @@ -57,6 +60,7 @@ public class User { this.fullName = fullName; this.avatarUrl = avatarUrl; this.role = role; + this.active = active; this.createdAt = createdAt; this.updatedAt = updatedAt; } @@ -117,6 +121,14 @@ public class User { this.role = role; } + public Boolean getActive() { + return active; + } + + public void setActive(Boolean active) { + this.active = active; + } + public LocalDateTime getCreatedAt() { return createdAt; } @@ -156,6 +168,7 @@ public class User { ", fullName='" + fullName + '\'' + ", avatarUrl='" + avatarUrl + '\'' + ", role=" + role + + ", active=" + active + ", createdAt=" + createdAt + ", updatedAt=" + updatedAt + '}'; diff --git a/src/main/java/com/petshop/backend/repository/CustomerRepository.java b/src/main/java/com/petshop/backend/repository/CustomerRepository.java index a1885993..f4baa3f9 100644 --- a/src/main/java/com/petshop/backend/repository/CustomerRepository.java +++ b/src/main/java/com/petshop/backend/repository/CustomerRepository.java @@ -8,9 +8,15 @@ import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; +import java.util.List; +import java.util.Optional; + @Repository public interface CustomerRepository extends JpaRepository { + Optional findByUserId(Long userId); + List findAllByEmail(String email); + @Query("SELECT c FROM Customer c WHERE " + "LOWER(c.firstName) LIKE LOWER(CONCAT('%', :q, '%')) OR " + "LOWER(c.lastName) LIKE LOWER(CONCAT('%', :q, '%')) OR " + diff --git a/src/main/java/com/petshop/backend/repository/EmployeeRepository.java b/src/main/java/com/petshop/backend/repository/EmployeeRepository.java index 4c5aa9d8..bcb4b138 100644 --- a/src/main/java/com/petshop/backend/repository/EmployeeRepository.java +++ b/src/main/java/com/petshop/backend/repository/EmployeeRepository.java @@ -4,6 +4,11 @@ import com.petshop.backend.entity.Employee; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.List; +import java.util.Optional; + @Repository public interface EmployeeRepository extends JpaRepository { + Optional findByUserId(Long userId); + List findAllByEmail(String email); } diff --git a/src/main/java/com/petshop/backend/service/UserBusinessLinkageService.java b/src/main/java/com/petshop/backend/service/UserBusinessLinkageService.java new file mode 100644 index 00000000..81b4738f --- /dev/null +++ b/src/main/java/com/petshop/backend/service/UserBusinessLinkageService.java @@ -0,0 +1,138 @@ +package com.petshop.backend.service; + +import com.petshop.backend.entity.Customer; +import com.petshop.backend.entity.Employee; +import com.petshop.backend.entity.User; +import com.petshop.backend.repository.CustomerRepository; +import com.petshop.backend.repository.EmployeeRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +public class UserBusinessLinkageService { + + private final EmployeeRepository employeeRepository; + private final CustomerRepository customerRepository; + + @Autowired + public UserBusinessLinkageService(EmployeeRepository employeeRepository, CustomerRepository customerRepository) { + this.employeeRepository = employeeRepository; + this.customerRepository = customerRepository; + } + + @Transactional + public Employee ensureLinkedEmployee(User user) { + // Check if already linked + if (user.getId() != null) { + var existing = employeeRepository.findByUserId(user.getId()); + if (existing.isPresent()) { + return existing.get(); + } + } + + // Check for email matches + List emailMatches = employeeRepository.findAllByEmail(user.getEmail()); + + // If exactly one match exists and has no userId, link it + if (emailMatches.size() == 1) { + Employee employee = emailMatches.get(0); + if (employee.getUserId() == null) { + employee.setUserId(user.getId()); + return employeeRepository.save(employee); + } + } + + // Otherwise create a new linked Employee + Employee newEmployee = new Employee(); + newEmployee.setUserId(user.getId()); + newEmployee.setEmail(user.getEmail()); + + // Split fullName into firstName and lastName + String[] nameParts = splitFullName(user.getFullName()); + newEmployee.setFirstName(nameParts[0]); + newEmployee.setLastName(nameParts[1]); + + // Set required fields with deterministic values + newEmployee.setPhone("000-000-0000"); + newEmployee.setIsActive(true); + + // Map role based on user role + if (user.getRole() == User.Role.ADMIN) { + newEmployee.setRole("Manager"); + } else if (user.getRole() == User.Role.STAFF) { + newEmployee.setRole("Staff"); + } else { + newEmployee.setRole("Staff"); // fallback + } + + return employeeRepository.save(newEmployee); + } + + @Transactional + public Customer ensureLinkedCustomer(User user) { + // Check if already linked + if (user.getId() != null) { + var existing = customerRepository.findByUserId(user.getId()); + if (existing.isPresent()) { + return existing.get(); + } + } + + // Check for email matches + List emailMatches = customerRepository.findAllByEmail(user.getEmail()); + + // If exactly one match exists and has no userId, link it + if (emailMatches.size() == 1) { + Customer customer = emailMatches.get(0); + if (customer.getUserId() == null) { + customer.setUserId(user.getId()); + return customerRepository.save(customer); + } + } + + // Otherwise create a new linked Customer + Customer newCustomer = new Customer(); + newCustomer.setUserId(user.getId()); + newCustomer.setEmail(user.getEmail()); + + // Split fullName into firstName and lastName + String[] nameParts = splitFullName(user.getFullName()); + newCustomer.setFirstName(nameParts[0]); + newCustomer.setLastName(nameParts[1]); + + // Set required fields with deterministic values + newCustomer.setPhone("000-000-0001"); + + return customerRepository.save(newCustomer); + } + + private String[] splitFullName(String fullName) { + if (fullName == null || fullName.trim().isEmpty()) { + return new String[]{"System", "User"}; + } + + String trimmed = fullName.trim(); + int spaceIndex = trimmed.indexOf(' '); + + if (spaceIndex == -1) { + // Single token + return new String[]{trimmed, "User"}; + } + + // Multiple tokens + String firstName = trimmed.substring(0, spaceIndex).trim(); + String lastName = trimmed.substring(spaceIndex + 1).trim(); + + if (firstName.isEmpty()) { + firstName = "System"; + } + if (lastName.isEmpty()) { + lastName = "User"; + } + + return new String[]{firstName, lastName}; + } +} diff --git a/src/main/java/com/petshop/backend/service/UserService.java b/src/main/java/com/petshop/backend/service/UserService.java index 183d05d9..3e8d36a1 100644 --- a/src/main/java/com/petshop/backend/service/UserService.java +++ b/src/main/java/com/petshop/backend/service/UserService.java @@ -17,10 +17,12 @@ public class UserService { private final UserRepository userRepository; private final PasswordEncoder passwordEncoder; + private final UserBusinessLinkageService userBusinessLinkageService; - public UserService(UserRepository userRepository, PasswordEncoder passwordEncoder) { + public UserService(UserRepository userRepository, PasswordEncoder passwordEncoder, UserBusinessLinkageService userBusinessLinkageService) { this.userRepository = userRepository; this.passwordEncoder = passwordEncoder; + this.userBusinessLinkageService = userBusinessLinkageService; } public Page getAllUsers(String query, Pageable pageable) { @@ -44,9 +46,20 @@ public class UserService { User user = new User(); user.setUsername(request.getUsername()); user.setPassword(passwordEncoder.encode(request.getPassword())); + user.setFullName(request.getFullName()); + user.setEmail(request.getEmail()); user.setRole(request.getRole()); + user.setActive(request.getActive() != null ? request.getActive() : true); user = userRepository.save(user); + + // Create or link business entity based on role + if (user.getRole() == User.Role.STAFF || user.getRole() == User.Role.ADMIN) { + userBusinessLinkageService.ensureLinkedEmployee(user); + } else if (user.getRole() == User.Role.CUSTOMER) { + userBusinessLinkageService.ensureLinkedCustomer(user); + } + return mapToResponse(user); } @@ -59,7 +72,10 @@ public class UserService { if (request.getPassword() != null && !request.getPassword().trim().isEmpty()) { user.setPassword(passwordEncoder.encode(request.getPassword())); } + user.setFullName(request.getFullName()); + user.setEmail(request.getEmail()); user.setRole(request.getRole()); + user.setActive(request.getActive() != null ? request.getActive() : true); user = userRepository.save(user); return mapToResponse(user); @@ -82,7 +98,12 @@ public class UserService { UserResponse response = new UserResponse(); response.setId(user.getId()); response.setUsername(user.getUsername()); + response.setFullName(user.getFullName()); + response.setEmail(user.getEmail()); response.setRole(user.getRole().toString()); + response.setActive(user.getActive()); + response.setCreatedAt(user.getCreatedAt()); + response.setUpdatedAt(user.getUpdatedAt()); return response; } } diff --git a/src/main/java/com/petshop/backend/util/AuthenticationHelper.java b/src/main/java/com/petshop/backend/util/AuthenticationHelper.java new file mode 100644 index 00000000..26468202 --- /dev/null +++ b/src/main/java/com/petshop/backend/util/AuthenticationHelper.java @@ -0,0 +1,38 @@ +package com.petshop.backend.util; + +import com.petshop.backend.entity.Customer; +import com.petshop.backend.entity.Employee; +import com.petshop.backend.entity.User; +import com.petshop.backend.repository.CustomerRepository; +import com.petshop.backend.repository.EmployeeRepository; +import com.petshop.backend.repository.UserRepository; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; + +@Component +public class AuthenticationHelper { + + public static User getAuthenticatedUser(UserRepository userRepository) { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + if (authentication == null || !authentication.isAuthenticated()) { + throw new RuntimeException("No authenticated user found"); + } + + String username = authentication.getName(); + return userRepository.findByUsername(username) + .orElseThrow(() -> new RuntimeException("User not found: " + username)); + } + + public static Employee getAuthenticatedEmployee(UserRepository userRepository, EmployeeRepository employeeRepository) { + User user = getAuthenticatedUser(userRepository); + return employeeRepository.findByUserId(user.getId()) + .orElseThrow(() -> new RuntimeException("Employee record not found for user: " + user.getUsername())); + } + + public static Customer getAuthenticatedCustomer(UserRepository userRepository, CustomerRepository customerRepository) { + User user = getAuthenticatedUser(userRepository); + return customerRepository.findByUserId(user.getId()) + .orElseThrow(() -> new RuntimeException("Customer record not found for user: " + user.getUsername())); + } +} diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index 76e63b85..097a7328 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -12,6 +12,7 @@ CREATE TABLE IF NOT EXISTS storeLocation ( CREATE TABLE IF NOT EXISTS employee ( employeeId BIGINT AUTO_INCREMENT PRIMARY KEY, + user_id BIGINT NULL, firstName VARCHAR(50) NOT NULL, lastName VARCHAR(50) NOT NULL, email VARCHAR(100) NOT NULL, @@ -19,7 +20,8 @@ CREATE TABLE IF NOT EXISTS employee ( role VARCHAR(50) NOT NULL, isActive BOOLEAN DEFAULT TRUE NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + CONSTRAINT uk_employee_user_id UNIQUE (user_id) ); CREATE TABLE IF NOT EXISTS employeeStore ( @@ -32,12 +34,14 @@ CREATE TABLE IF NOT EXISTS employeeStore ( CREATE TABLE IF NOT EXISTS customer ( customerId BIGINT AUTO_INCREMENT PRIMARY KEY, + user_id BIGINT NULL, firstName VARCHAR(50) NOT NULL, lastName VARCHAR(50) NOT NULL, email VARCHAR(100) NOT NULL, phone VARCHAR(20) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + CONSTRAINT uk_customer_user_id UNIQUE (user_id) ); CREATE TABLE IF NOT EXISTS pet ( @@ -201,6 +205,7 @@ CREATE TABLE IF NOT EXISTS users ( fullName VARCHAR(100), avatarUrl VARCHAR(255), role VARCHAR(20) NOT NULL, + active BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ); @@ -239,3 +244,7 @@ CREATE TABLE IF NOT EXISTS message ( FOREIGN KEY (conversationId) REFERENCES conversation(id), FOREIGN KEY (senderId) REFERENCES users(id) ); + +-- Add foreign keys for user_id linkage +ALTER TABLE employee ADD CONSTRAINT fk_employee_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL; +ALTER TABLE customer ADD CONSTRAINT fk_customer_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL;