diff --git a/src/main/java/com/petshop/backend/controller/EmployeeController.java b/src/main/java/com/petshop/backend/controller/EmployeeController.java new file mode 100644 index 00000000..1c567623 --- /dev/null +++ b/src/main/java/com/petshop/backend/controller/EmployeeController.java @@ -0,0 +1,49 @@ +package com.petshop.backend.controller; + +import com.petshop.backend.dto.employee.EmployeeRequest; +import com.petshop.backend.dto.employee.EmployeeResponse; +import com.petshop.backend.service.EmployeeService; +import jakarta.validation.Valid; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/api/v1/employees") +@PreAuthorize("hasRole('ADMIN')") +public class EmployeeController { + private final EmployeeService employeeService; + + public EmployeeController(EmployeeService employeeService) { + this.employeeService = employeeService; + } + + @GetMapping + public ResponseEntity> getAllEmployees(@RequestParam(required = false) String q, Pageable pageable) { + return ResponseEntity.ok(employeeService.getAllEmployees(q, pageable)); + } + + @GetMapping("/{id}") + public ResponseEntity getEmployeeById(@PathVariable Long id) { + return ResponseEntity.ok(employeeService.getEmployeeById(id)); + } + + @PostMapping + public ResponseEntity createEmployee(@Valid @RequestBody EmployeeRequest request) { + return ResponseEntity.status(HttpStatus.CREATED).body(employeeService.createEmployee(request)); + } + + @PutMapping("/{id}") + public ResponseEntity updateEmployee(@PathVariable Long id, @Valid @RequestBody EmployeeRequest request) { + return ResponseEntity.ok(employeeService.updateEmployee(id, request)); + } + + @DeleteMapping("/{id}") + public ResponseEntity deleteEmployee(@PathVariable Long id) { + employeeService.deleteEmployee(id); + return ResponseEntity.noContent().build(); + } +} diff --git a/src/main/java/com/petshop/backend/dto/customer/CustomerRequest.java b/src/main/java/com/petshop/backend/dto/customer/CustomerRequest.java index d982be81..ded898e3 100644 --- a/src/main/java/com/petshop/backend/dto/customer/CustomerRequest.java +++ b/src/main/java/com/petshop/backend/dto/customer/CustomerRequest.java @@ -14,8 +14,6 @@ public class CustomerRequest { @Email(message = "Invalid email format") private String email; - private String phone; - public String getFirstName() { return firstName; } @@ -40,14 +38,6 @@ public class CustomerRequest { this.email = email; } - public String getPhone() { - return phone; - } - - public void setPhone(String phone) { - this.phone = phone; - } - @Override public boolean equals(Object o) { if (this == o) return true; @@ -55,13 +45,12 @@ public class CustomerRequest { CustomerRequest that = (CustomerRequest) o; return Objects.equals(firstName, that.firstName) && Objects.equals(lastName, that.lastName) && - Objects.equals(email, that.email) && - Objects.equals(phone, that.phone); + Objects.equals(email, that.email); } @Override public int hashCode() { - return Objects.hash(firstName, lastName, email, phone); + return Objects.hash(firstName, lastName, email); } @Override @@ -70,7 +59,6 @@ public class CustomerRequest { "firstName='" + firstName + '\'' + ", lastName='" + lastName + '\'' + ", email='" + email + '\'' + - ", phone='" + phone + '\'' + '}'; } } diff --git a/src/main/java/com/petshop/backend/dto/customer/CustomerResponse.java b/src/main/java/com/petshop/backend/dto/customer/CustomerResponse.java index 7b25f17a..bd05bf76 100644 --- a/src/main/java/com/petshop/backend/dto/customer/CustomerResponse.java +++ b/src/main/java/com/petshop/backend/dto/customer/CustomerResponse.java @@ -8,19 +8,17 @@ public class CustomerResponse { private String firstName; private String lastName; private String email; - private String phone; private LocalDateTime createdAt; private LocalDateTime updatedAt; public CustomerResponse() { } - public CustomerResponse(Long customerId, String firstName, String lastName, String email, String phone, LocalDateTime createdAt, LocalDateTime updatedAt) { + public CustomerResponse(Long customerId, String firstName, String lastName, String email, LocalDateTime createdAt, LocalDateTime updatedAt) { this.customerId = customerId; this.firstName = firstName; this.lastName = lastName; this.email = email; - this.phone = phone; this.createdAt = createdAt; this.updatedAt = updatedAt; } @@ -57,14 +55,6 @@ public class CustomerResponse { this.email = email; } - public String getPhone() { - return phone; - } - - public void setPhone(String phone) { - this.phone = phone; - } - public LocalDateTime getCreatedAt() { return createdAt; } @@ -86,12 +76,12 @@ public class CustomerResponse { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; CustomerResponse that = (CustomerResponse) o; - return Objects.equals(customerId, that.customerId) && Objects.equals(firstName, that.firstName) && Objects.equals(lastName, that.lastName) && Objects.equals(email, that.email) && Objects.equals(phone, that.phone) && Objects.equals(createdAt, that.createdAt) && Objects.equals(updatedAt, that.updatedAt); + return Objects.equals(customerId, that.customerId) && Objects.equals(firstName, that.firstName) && Objects.equals(lastName, that.lastName) && Objects.equals(email, that.email) && Objects.equals(createdAt, that.createdAt) && Objects.equals(updatedAt, that.updatedAt); } @Override public int hashCode() { - return Objects.hash(customerId, firstName, lastName, email, phone, createdAt, updatedAt); + return Objects.hash(customerId, firstName, lastName, email, createdAt, updatedAt); } @Override @@ -101,7 +91,6 @@ public class CustomerResponse { ", firstName='" + firstName + '\'' + ", lastName='" + lastName + '\'' + ", email='" + email + '\'' + - ", phone='" + phone + '\'' + ", createdAt=" + createdAt + ", updatedAt=" + updatedAt + '}'; diff --git a/src/main/java/com/petshop/backend/dto/employee/EmployeeRequest.java b/src/main/java/com/petshop/backend/dto/employee/EmployeeRequest.java new file mode 100644 index 00000000..0dfa25a8 --- /dev/null +++ b/src/main/java/com/petshop/backend/dto/employee/EmployeeRequest.java @@ -0,0 +1,50 @@ +package com.petshop.backend.dto.employee; + +import com.petshop.backend.entity.User; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; + +public class EmployeeRequest { + @NotBlank(message = "Username is required") + @Size(min = 3, max = 50, message = "Username must be between 3 and 50 characters") + private String username; + + @Size(min = 6, message = "Password must be at least 6 characters") + private String password; + + @NotBlank(message = "First name is required") + private String firstName; + + @NotBlank(message = "Last name is required") + private String lastName; + + @Email(message = "Invalid email format") + private String email; + + @Size(max = 20, message = "Phone must not exceed 20 characters") + private String phone; + + @NotNull(message = "Role is required") + private User.Role role; + + private Boolean active = true; + + public String getUsername() { return username; } + public void setUsername(String username) { this.username = username; } + public String getPassword() { return password; } + public void setPassword(String password) { this.password = password; } + public String getFirstName() { return firstName; } + public void setFirstName(String firstName) { this.firstName = firstName; } + public String getLastName() { return lastName; } + public void setLastName(String lastName) { this.lastName = lastName; } + public String getEmail() { return email; } + public void setEmail(String email) { this.email = email; } + public String getPhone() { return phone; } + public void setPhone(String phone) { this.phone = phone; } + public User.Role getRole() { return role; } + public void setRole(User.Role role) { this.role = role; } + public Boolean getActive() { return active; } + public void setActive(Boolean active) { this.active = active; } +} diff --git a/src/main/java/com/petshop/backend/dto/employee/EmployeeResponse.java b/src/main/java/com/petshop/backend/dto/employee/EmployeeResponse.java new file mode 100644 index 00000000..a159fc35 --- /dev/null +++ b/src/main/java/com/petshop/backend/dto/employee/EmployeeResponse.java @@ -0,0 +1,43 @@ +package com.petshop.backend.dto.employee; + +import java.time.LocalDateTime; + +public class EmployeeResponse { + private Long employeeId; + private Long userId; + private String username; + private String firstName; + private String lastName; + private String fullName; + private String email; + private String phone; + private String role; + private Boolean active; + private LocalDateTime createdAt; + private LocalDateTime updatedAt; + + public Long getEmployeeId() { return employeeId; } + public void setEmployeeId(Long employeeId) { this.employeeId = employeeId; } + public Long getUserId() { return userId; } + public void setUserId(Long userId) { this.userId = userId; } + public String getUsername() { return username; } + public void setUsername(String username) { this.username = username; } + public String getFirstName() { return firstName; } + public void setFirstName(String firstName) { this.firstName = firstName; } + public String getLastName() { return lastName; } + public void setLastName(String lastName) { this.lastName = lastName; } + public String getFullName() { return fullName; } + public void setFullName(String fullName) { this.fullName = fullName; } + public String getEmail() { return email; } + public void setEmail(String email) { this.email = email; } + public String getPhone() { return phone; } + public void setPhone(String phone) { this.phone = phone; } + public String getRole() { return role; } + public void setRole(String role) { this.role = role; } + public Boolean getActive() { return active; } + public void setActive(Boolean active) { this.active = active; } + public LocalDateTime getCreatedAt() { return createdAt; } + public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; } + public LocalDateTime getUpdatedAt() { return updatedAt; } + public void setUpdatedAt(LocalDateTime updatedAt) { this.updatedAt = updatedAt; } +} diff --git a/src/main/java/com/petshop/backend/entity/Customer.java b/src/main/java/com/petshop/backend/entity/Customer.java index 1cfa858b..09035619 100644 --- a/src/main/java/com/petshop/backend/entity/Customer.java +++ b/src/main/java/com/petshop/backend/entity/Customer.java @@ -27,9 +27,6 @@ public class Customer { @Column(nullable = false, length = 100) private String email; - @Column(nullable = false, length = 20) - private String phone; - @CreationTimestamp @Column(name = "created_at", updatable = false) private LocalDateTime createdAt; @@ -41,13 +38,12 @@ public class Customer { public Customer() { } - public Customer(Long customerId, Long userId, String firstName, String lastName, String email, String phone, LocalDateTime createdAt, LocalDateTime updatedAt) { + public Customer(Long customerId, Long userId, String firstName, String lastName, String email, LocalDateTime createdAt, LocalDateTime updatedAt) { this.customerId = customerId; this.userId = userId; this.firstName = firstName; this.lastName = lastName; this.email = email; - this.phone = phone; this.createdAt = createdAt; this.updatedAt = updatedAt; } @@ -92,14 +88,6 @@ public class Customer { this.email = email; } - public String getPhone() { - return phone; - } - - public void setPhone(String phone) { - this.phone = phone; - } - public LocalDateTime getCreatedAt() { return createdAt; } @@ -137,7 +125,6 @@ public class Customer { ", firstName='" + firstName + '\'' + ", lastName='" + lastName + '\'' + ", email='" + email + '\'' + - ", phone='" + phone + '\'' + ", createdAt=" + createdAt + ", updatedAt=" + updatedAt + '}'; diff --git a/src/main/java/com/petshop/backend/entity/Employee.java b/src/main/java/com/petshop/backend/entity/Employee.java index 9e825a61..c88216f6 100644 --- a/src/main/java/com/petshop/backend/entity/Employee.java +++ b/src/main/java/com/petshop/backend/entity/Employee.java @@ -27,9 +27,6 @@ public class Employee { @Column(nullable = false, length = 100) private String email; - @Column(nullable = false, length = 20) - private String phone; - @Column(nullable = false, length = 50) private String role; @@ -47,13 +44,12 @@ public class Employee { public Employee() { } - public Employee(Long employeeId, Long userId, 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 role, Boolean isActive, LocalDateTime createdAt, LocalDateTime updatedAt) { this.employeeId = employeeId; this.userId = userId; this.firstName = firstName; this.lastName = lastName; this.email = email; - this.phone = phone; this.role = role; this.isActive = isActive; this.createdAt = createdAt; @@ -100,14 +96,6 @@ public class Employee { this.email = email; } - public String getPhone() { - return phone; - } - - public void setPhone(String phone) { - this.phone = phone; - } - public String getRole() { return role; } @@ -161,7 +149,6 @@ public class Employee { ", firstName='" + firstName + '\'' + ", lastName='" + lastName + '\'' + ", email='" + email + '\'' + - ", phone='" + phone + '\'' + ", role='" + role + '\'' + ", isActive=" + isActive + ", createdAt=" + createdAt + diff --git a/src/main/java/com/petshop/backend/repository/CustomerRepository.java b/src/main/java/com/petshop/backend/repository/CustomerRepository.java index f4baa3f9..56e03dbc 100644 --- a/src/main/java/com/petshop/backend/repository/CustomerRepository.java +++ b/src/main/java/com/petshop/backend/repository/CustomerRepository.java @@ -21,6 +21,6 @@ public interface CustomerRepository extends JpaRepository { "LOWER(c.firstName) LIKE LOWER(CONCAT('%', :q, '%')) OR " + "LOWER(c.lastName) LIKE LOWER(CONCAT('%', :q, '%')) OR " + "LOWER(c.email) LIKE LOWER(CONCAT('%', :q, '%')) OR " + - "LOWER(c.phone) LIKE LOWER(CONCAT('%', :q, '%'))") + "EXISTS (SELECT u FROM User u WHERE u.id = c.userId AND LOWER(COALESCE(u.phone, '')) LIKE LOWER(CONCAT('%', :q, '%')))") Page searchCustomers(@Param("q") String query, Pageable pageable); } diff --git a/src/main/java/com/petshop/backend/repository/EmployeeRepository.java b/src/main/java/com/petshop/backend/repository/EmployeeRepository.java index bcb4b138..cfbf715f 100644 --- a/src/main/java/com/petshop/backend/repository/EmployeeRepository.java +++ b/src/main/java/com/petshop/backend/repository/EmployeeRepository.java @@ -1,7 +1,11 @@ package com.petshop.backend.repository; import com.petshop.backend.entity.Employee; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; import java.util.List; @@ -11,4 +15,14 @@ import java.util.Optional; public interface EmployeeRepository extends JpaRepository { Optional findByUserId(Long userId); List findAllByEmail(String email); + + @Query("SELECT e FROM Employee e WHERE " + + "LOWER(e.firstName) LIKE LOWER(CONCAT('%', :q, '%')) OR " + + "LOWER(e.lastName) LIKE LOWER(CONCAT('%', :q, '%')) OR " + + "LOWER(e.email) LIKE LOWER(CONCAT('%', :q, '%')) OR " + + "LOWER(e.role) LIKE LOWER(CONCAT('%', :q, '%')) OR " + + "EXISTS (SELECT u FROM User u WHERE u.id = e.userId AND (" + + "LOWER(u.username) LIKE LOWER(CONCAT('%', :q, '%')) OR " + + "LOWER(COALESCE(u.phone, '')) LIKE LOWER(CONCAT('%', :q, '%'))))") + Page searchEmployees(@Param("q") String query, Pageable pageable); } diff --git a/src/main/java/com/petshop/backend/service/CustomerService.java b/src/main/java/com/petshop/backend/service/CustomerService.java index 888c7c82..040be22a 100644 --- a/src/main/java/com/petshop/backend/service/CustomerService.java +++ b/src/main/java/com/petshop/backend/service/CustomerService.java @@ -45,7 +45,6 @@ public class CustomerService { customer.setFirstName(request.getFirstName()); customer.setLastName(request.getLastName()); customer.setEmail(request.getEmail()); - customer.setPhone(request.getPhone()); customer = customerRepository.save(customer); syncLinkedUser(customer); @@ -60,7 +59,6 @@ public class CustomerService { customer.setFirstName(request.getFirstName()); customer.setLastName(request.getLastName()); customer.setEmail(request.getEmail()); - customer.setPhone(request.getPhone()); customer = customerRepository.save(customer); syncLinkedUser(customer); @@ -86,7 +84,6 @@ public class CustomerService { customer.getFirstName(), customer.getLastName(), customer.getEmail(), - customer.getPhone(), customer.getCreatedAt(), customer.getUpdatedAt() ); @@ -98,7 +95,6 @@ public class CustomerService { } userRepository.findById(customer.getUserId()).ifPresent(user -> { user.setEmail(customer.getEmail()); - user.setPhone(customer.getPhone()); user.setFullName((customer.getFirstName() + " " + customer.getLastName()).trim()); userRepository.save(user); }); diff --git a/src/main/java/com/petshop/backend/service/EmployeeService.java b/src/main/java/com/petshop/backend/service/EmployeeService.java new file mode 100644 index 00000000..2199e441 --- /dev/null +++ b/src/main/java/com/petshop/backend/service/EmployeeService.java @@ -0,0 +1,175 @@ +package com.petshop.backend.service; + +import com.petshop.backend.dto.employee.EmployeeRequest; +import com.petshop.backend.dto.employee.EmployeeResponse; +import com.petshop.backend.entity.Employee; +import com.petshop.backend.entity.User; +import com.petshop.backend.exception.ResourceNotFoundException; +import com.petshop.backend.repository.EmployeeRepository; +import com.petshop.backend.repository.UserRepository; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.server.ResponseStatusException; + +import static org.springframework.http.HttpStatus.CONFLICT; + +@Service +public class EmployeeService { + private final EmployeeRepository employeeRepository; + private final UserRepository userRepository; + private final PasswordEncoder passwordEncoder; + private final UserBusinessLinkageService userBusinessLinkageService; + + public EmployeeService(EmployeeRepository employeeRepository, UserRepository userRepository, PasswordEncoder passwordEncoder, UserBusinessLinkageService userBusinessLinkageService) { + this.employeeRepository = employeeRepository; + this.userRepository = userRepository; + this.passwordEncoder = passwordEncoder; + this.userBusinessLinkageService = userBusinessLinkageService; + } + + public Page getAllEmployees(String query, Pageable pageable) { + Page employees; + if (query != null && !query.trim().isEmpty()) { + employees = employeeRepository.searchEmployees(query, pageable); + } else { + employees = employeeRepository.findAll(pageable); + } + return employees.map(this::mapToResponse); + } + + public EmployeeResponse getEmployeeById(Long id) { + Employee employee = employeeRepository.findById(id) + .orElseThrow(() -> new ResourceNotFoundException("Employee not found with id: " + id)); + return mapToResponse(employee); + } + + @Transactional + public EmployeeResponse createEmployee(EmployeeRequest request) { + validateRole(request.getRole()); + if (request.getPassword() == null || request.getPassword().trim().length() < 6) { + throw new IllegalArgumentException("Password must be at least 6 characters"); + } + if (userRepository.findByUsername(request.getUsername()).isPresent()) { + throw new ResponseStatusException(CONFLICT, "Username already exists"); + } + if (request.getEmail() != null && userRepository.findByEmail(request.getEmail()).isPresent()) { + throw new ResponseStatusException(CONFLICT, "Email already exists"); + } + String phone = trimToNull(request.getPhone()); + if (phone != null && userRepository.findByPhone(phone).isPresent()) { + throw new ResponseStatusException(CONFLICT, "Phone already exists"); + } + + User user = new User(); + user.setUsername(request.getUsername()); + user.setPassword(passwordEncoder.encode(request.getPassword())); + user.setFullName(fullName(request)); + user.setEmail(request.getEmail()); + user.setPhone(phone); + user.setRole(request.getRole()); + user.setActive(request.getActive() != null ? request.getActive() : true); + user = userRepository.save(user); + + Employee employee = userBusinessLinkageService.ensureLinkedEmployee(user); + return mapToResponse(employee, user); + } + + @Transactional + public EmployeeResponse updateEmployee(Long id, EmployeeRequest request) { + Employee employee = employeeRepository.findById(id) + .orElseThrow(() -> new ResourceNotFoundException("Employee not found with id: " + id)); + User user = requireLinkedUser(employee); + + validateRole(request.getRole()); + if (!user.getUsername().equals(request.getUsername()) && userRepository.findByUsername(request.getUsername()).isPresent()) { + throw new ResponseStatusException(CONFLICT, "Username already exists"); + } + if (!java.util.Objects.equals(user.getEmail(), request.getEmail()) && request.getEmail() != null && userRepository.findByEmail(request.getEmail()).isPresent()) { + throw new ResponseStatusException(CONFLICT, "Email already exists"); + } + String phone = trimToNull(request.getPhone()); + Long currentUserId = user.getId(); + if (!java.util.Objects.equals(user.getPhone(), phone)) { + userRepository.findByPhone(phone) + .filter(existing -> !existing.getId().equals(currentUserId)) + .ifPresent(existing -> { throw new ResponseStatusException(CONFLICT, "Phone already exists"); }); + } + + user.setUsername(request.getUsername()); + if (request.getPassword() != null && !request.getPassword().trim().isEmpty()) { + user.setPassword(passwordEncoder.encode(request.getPassword())); + user.setTokenVersion(user.getTokenVersion() + 1); + } + user.setEmail(request.getEmail()); + user.setPhone(phone); + user.setFullName(fullName(request)); + user.setRole(request.getRole()); + user.setActive(request.getActive() != null ? request.getActive() : true); + user = userRepository.save(user); + + employee = userBusinessLinkageService.ensureLinkedEmployee(user); + return mapToResponse(employee, user); + } + + @Transactional + public void deleteEmployee(Long id) { + Employee employee = employeeRepository.findById(id) + .orElseThrow(() -> new ResourceNotFoundException("Employee not found with id: " + id)); + if (employee.getUserId() != null && userRepository.existsById(employee.getUserId())) { + userRepository.deleteById(employee.getUserId()); + return; + } + employeeRepository.deleteById(id); + } + + private EmployeeResponse mapToResponse(Employee employee) { + User user = requireLinkedUser(employee); + return mapToResponse(employee, user); + } + + private EmployeeResponse mapToResponse(Employee employee, User user) { + EmployeeResponse response = new EmployeeResponse(); + response.setEmployeeId(employee.getEmployeeId()); + response.setUserId(user.getId()); + response.setUsername(user.getUsername()); + response.setFirstName(employee.getFirstName()); + response.setLastName(employee.getLastName()); + response.setFullName(user.getFullName()); + response.setEmail(user.getEmail()); + response.setPhone(user.getPhone()); + response.setRole(user.getRole().name()); + response.setActive(user.getActive()); + response.setCreatedAt(employee.getCreatedAt()); + response.setUpdatedAt(employee.getUpdatedAt()); + return response; + } + + private User requireLinkedUser(Employee employee) { + if (employee.getUserId() == null) { + throw new ResourceNotFoundException("Employee user account not found"); + } + return userRepository.findById(employee.getUserId()) + .orElseThrow(() -> new ResourceNotFoundException("Employee user account not found")); + } + + private void validateRole(User.Role role) { + if (role != User.Role.STAFF && role != User.Role.ADMIN) { + throw new IllegalArgumentException("Employee role must be STAFF or ADMIN"); + } + } + + private String fullName(EmployeeRequest request) { + return (request.getFirstName().trim() + " " + request.getLastName().trim()).trim(); + } + + private String trimToNull(String value) { + if (value == null) { + return null; + } + String trimmed = value.trim(); + return trimmed.isEmpty() ? null : trimmed; + } +} diff --git a/src/main/java/com/petshop/backend/service/UserBusinessLinkageService.java b/src/main/java/com/petshop/backend/service/UserBusinessLinkageService.java index d0a18d3e..05751688 100644 --- a/src/main/java/com/petshop/backend/service/UserBusinessLinkageService.java +++ b/src/main/java/com/petshop/backend/service/UserBusinessLinkageService.java @@ -50,7 +50,6 @@ public class UserBusinessLinkageService { newEmployee.setFirstName(nameParts[0]); newEmployee.setLastName(nameParts[1]); - newEmployee.setPhone(normalizePhone(user.getPhone(), "000-000-0000")); newEmployee.setIsActive(true); if (user.getRole() == User.Role.ADMIN) { @@ -91,8 +90,6 @@ public class UserBusinessLinkageService { newCustomer.setFirstName(nameParts[0]); newCustomer.setLastName(nameParts[1]); - newCustomer.setPhone(normalizePhone(user.getPhone(), "000-000-0001")); - return syncCustomer(newCustomer, user); } @@ -111,7 +108,6 @@ public class UserBusinessLinkageService { String[] nameParts = splitFullName(user.getFullName()); employee.setFirstName(nameParts[0]); employee.setLastName(nameParts[1]); - employee.setPhone(normalizePhone(user.getPhone(), employee.getPhone())); if (user.getRole() == User.Role.ADMIN) { employee.setRole("Manager"); } else { @@ -126,17 +122,9 @@ public class UserBusinessLinkageService { String[] nameParts = splitFullName(user.getFullName()); customer.setFirstName(nameParts[0]); customer.setLastName(nameParts[1]); - customer.setPhone(normalizePhone(user.getPhone(), customer.getPhone())); return customerRepository.save(customer); } - private String normalizePhone(String phone, String fallback) { - if (phone == null || phone.trim().isEmpty()) { - return fallback; - } - return phone.trim(); - } - private String[] splitFullName(String fullName) { if (fullName == null || fullName.trim().isEmpty()) { return new String[]{"System", "User"}; diff --git a/src/main/resources/db/migration/V7__employee_customer_phone_cutover.sql b/src/main/resources/db/migration/V7__employee_customer_phone_cutover.sql new file mode 100644 index 00000000..fa922a82 --- /dev/null +++ b/src/main/resources/db/migration/V7__employee_customer_phone_cutover.sql @@ -0,0 +1,11 @@ +UPDATE users u +LEFT JOIN customer c ON c.user_id = u.id +LEFT JOIN employee e ON e.user_id = u.id +SET u.phone = COALESCE(NULLIF(u.phone, ''), NULLIF(c.phone, ''), NULLIF(e.phone, '')) +WHERE u.phone IS NULL OR u.phone = ''; + +ALTER TABLE customer + DROP COLUMN phone; + +ALTER TABLE employee + DROP COLUMN phone;