expand User entity fields

This commit is contained in:
2026-04-06 19:49:38 -06:00
parent 24b11e4152
commit 824ed7e5eb
4 changed files with 191 additions and 71 deletions

View File

@@ -8,14 +8,20 @@ import jakarta.validation.constraints.Size;
import java.util.Objects; import java.util.Objects;
public class UserRequest { public class UserRequest {
@NotBlank(message = "Username is required")
@Size(min = 3, max = 50, message = "Username must be between 3 and 50 characters") @Size(min = 3, max = 50, message = "Username must be between 3 and 50 characters")
private String username; private String username;
@Size(min = 6, message = "Password must be at least 6 characters") @Size(min = 6, message = "Password must be at least 6 characters")
private String password; private String password;
@NotBlank(message = "Full name is required") @NotBlank(message = "First name is required")
@Size(max = 50)
private String firstName;
@NotBlank(message = "Last name is required")
@Size(max = 50)
private String lastName;
private String fullName; private String fullName;
@Email(message = "Invalid email format") @Email(message = "Invalid email format")
@@ -27,6 +33,10 @@ public class UserRequest {
@NotNull(message = "Role is required") @NotNull(message = "Role is required")
private User.Role role; private User.Role role;
private String staffRole;
private Long primaryStoreId;
private Boolean active = true; private Boolean active = true;
public String getUsername() { public String getUsername() {
@@ -45,6 +55,22 @@ public class UserRequest {
this.password = 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 getFullName() { public String getFullName() {
return fullName; return fullName;
} }
@@ -77,6 +103,22 @@ public class UserRequest {
this.role = role; this.role = role;
} }
public String getStaffRole() {
return staffRole;
}
public void setStaffRole(String staffRole) {
this.staffRole = staffRole;
}
public Long getPrimaryStoreId() {
return primaryStoreId;
}
public void setPrimaryStoreId(Long primaryStoreId) {
this.primaryStoreId = primaryStoreId;
}
public Boolean getActive() { public Boolean getActive() {
return active; return active;
} }
@@ -91,29 +133,20 @@ public class UserRequest {
if (o == null || getClass() != o.getClass()) return false; if (o == null || getClass() != o.getClass()) return false;
UserRequest that = (UserRequest) o; UserRequest that = (UserRequest) o;
return Objects.equals(username, that.username) && return Objects.equals(username, that.username) &&
Objects.equals(password, that.password) && Objects.equals(firstName, that.firstName) &&
Objects.equals(fullName, that.fullName) && Objects.equals(lastName, that.lastName) &&
Objects.equals(email, that.email) && Objects.equals(email, that.email) &&
Objects.equals(phone, that.phone) && role == that.role;
role == that.role &&
Objects.equals(active, that.active);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(username, password, fullName, email, phone, role, active); return Objects.hash(username, firstName, lastName, email, role);
} }
@Override @Override
public String toString() { public String toString() {
return "UserRequest{" + return "UserRequest{username='" + username + "', firstName='" + firstName +
"username='" + username + '\'' + "', lastName='" + lastName + "', role=" + role + '}';
", password='" + password + '\'' +
", fullName='" + fullName + '\'' +
", email='" + email + '\'' +
", phone='" + phone + '\'' +
", role=" + role +
", active=" + active +
'}';
} }
} }

View File

@@ -6,10 +6,15 @@ import java.util.Objects;
public class UserResponse { public class UserResponse {
private Long id; private Long id;
private String username; private String username;
private String firstName;
private String lastName;
private String fullName; private String fullName;
private String email; private String email;
private String phone; private String phone;
private String role; private String role;
private String staffRole;
private Long primaryStoreId;
private Integer loyaltyPoints;
private Boolean active; private Boolean active;
private LocalDateTime createdAt; private LocalDateTime createdAt;
private LocalDateTime updatedAt; private LocalDateTime updatedAt;
@@ -17,18 +22,6 @@ public class UserResponse {
public UserResponse() { public UserResponse() {
} }
public UserResponse(Long id, String username, String fullName, String email, String phone, String role, Boolean active, LocalDateTime createdAt, LocalDateTime updatedAt) {
this.id = id;
this.username = username;
this.fullName = fullName;
this.email = email;
this.phone = phone;
this.role = role;
this.active = active;
this.createdAt = createdAt;
this.updatedAt = updatedAt;
}
public Long getId() { public Long getId() {
return id; return id;
} }
@@ -45,6 +38,22 @@ public class UserResponse {
this.username = 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() { public String getFullName() {
return fullName; return fullName;
} }
@@ -77,6 +86,30 @@ public class UserResponse {
this.role = role; this.role = role;
} }
public String getStaffRole() {
return staffRole;
}
public void setStaffRole(String staffRole) {
this.staffRole = staffRole;
}
public Long getPrimaryStoreId() {
return primaryStoreId;
}
public void setPrimaryStoreId(Long primaryStoreId) {
this.primaryStoreId = primaryStoreId;
}
public Integer getLoyaltyPoints() {
return loyaltyPoints;
}
public void setLoyaltyPoints(Integer loyaltyPoints) {
this.loyaltyPoints = loyaltyPoints;
}
public Boolean getActive() { public Boolean getActive() {
return active; return active;
} }
@@ -106,26 +139,17 @@ public class UserResponse {
if (this == o) return true; if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false; if (o == null || getClass() != o.getClass()) return false;
UserResponse that = (UserResponse) o; UserResponse that = (UserResponse) o;
return Objects.equals(id, that.id) && Objects.equals(username, that.username) && Objects.equals(fullName, that.fullName) && Objects.equals(email, that.email) && Objects.equals(phone, that.phone) && Objects.equals(role, that.role) && Objects.equals(active, that.active) && Objects.equals(createdAt, that.createdAt) && Objects.equals(updatedAt, that.updatedAt); return Objects.equals(id, that.id);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(id, username, fullName, email, phone, role, active, createdAt, updatedAt); return Objects.hash(id);
} }
@Override @Override
public String toString() { public String toString() {
return "UserResponse{" + return "UserResponse{id=" + id + ", username='" + username + "', firstName='" + firstName +
"id=" + id + "', lastName='" + lastName + "', role='" + role + "', active=" + active + '}';
", username='" + username + '\'' +
", fullName='" + fullName + '\'' +
", email='" + email + '\'' +
", phone='" + phone + '\'' +
", role='" + role + '\'' +
", active=" + active +
", createdAt=" + createdAt +
", updatedAt=" + updatedAt +
'}';
} }
} }

View File

@@ -16,15 +16,21 @@ public class User {
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; private Long id;
@Column(nullable = false, unique = true, length = 50) @Column(unique = true, length = 50)
private String username; private String username;
@Column(nullable = false) @Column
private String password; private String password;
@Column(unique = true, length = 100) @Column(unique = true, length = 100)
private String email; private String email;
@Column(nullable = false, length = 50)
private String firstName;
@Column(nullable = false, length = 50)
private String lastName;
@Column(length = 100) @Column(length = 100)
private String fullName; private String fullName;
@@ -38,6 +44,16 @@ public class User {
@Column(nullable = false, length = 20, columnDefinition = "VARCHAR(20)") @Column(nullable = false, length = 20, columnDefinition = "VARCHAR(20)")
private Role role; private Role role;
@Column(length = 50)
private String staffRole;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "primaryStoreId")
private StoreLocation primaryStore;
@Column(nullable = false)
private Integer loyaltyPoints = 0;
@Column(nullable = false) @Column(nullable = false)
private Boolean active = true; private Boolean active = true;
@@ -59,21 +75,6 @@ public class User {
public User() { public User() {
} }
public User(Long id, String username, String password, String email, String fullName, String phone, String avatarUrl, Role role, Boolean active, Integer tokenVersion, LocalDateTime createdAt, LocalDateTime updatedAt) {
this.id = id;
this.username = username;
this.password = password;
this.email = email;
this.fullName = fullName;
this.phone = phone;
this.avatarUrl = avatarUrl;
this.role = role;
this.active = active;
this.tokenVersion = tokenVersion;
this.createdAt = createdAt;
this.updatedAt = updatedAt;
}
public Long getId() { public Long getId() {
return id; return id;
} }
@@ -106,6 +107,22 @@ public class User {
this.email = email; this.email = email;
} }
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() { public String getFullName() {
return fullName; return fullName;
} }
@@ -138,6 +155,30 @@ public class User {
this.role = role; this.role = role;
} }
public String getStaffRole() {
return staffRole;
}
public void setStaffRole(String staffRole) {
this.staffRole = staffRole;
}
public StoreLocation getPrimaryStore() {
return primaryStore;
}
public void setPrimaryStore(StoreLocation primaryStore) {
this.primaryStore = primaryStore;
}
public Integer getLoyaltyPoints() {
return loyaltyPoints;
}
public void setLoyaltyPoints(Integer loyaltyPoints) {
this.loyaltyPoints = loyaltyPoints;
}
public Boolean getActive() { public Boolean getActive() {
return active; return active;
} }
@@ -188,16 +229,12 @@ public class User {
return "User{" + return "User{" +
"id=" + id + "id=" + id +
", username='" + username + '\'' + ", username='" + username + '\'' +
", password='" + password + '\'' +
", email='" + email + '\'' + ", email='" + email + '\'' +
", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", fullName='" + fullName + '\'' + ", fullName='" + fullName + '\'' +
", phone='" + phone + '\'' +
", avatarUrl='" + avatarUrl + '\'' +
", role=" + role + ", role=" + role +
", active=" + active + ", active=" + active +
", tokenVersion=" + tokenVersion +
", createdAt=" + createdAt +
", updatedAt=" + updatedAt +
'}'; '}';
} }
} }

View File

@@ -3,8 +3,10 @@ package com.petshop.backend.service;
import com.petshop.backend.dto.common.BulkDeleteRequest; import com.petshop.backend.dto.common.BulkDeleteRequest;
import com.petshop.backend.dto.user.UserRequest; import com.petshop.backend.dto.user.UserRequest;
import com.petshop.backend.dto.user.UserResponse; import com.petshop.backend.dto.user.UserResponse;
import com.petshop.backend.entity.StoreLocation;
import com.petshop.backend.entity.User; import com.petshop.backend.entity.User;
import com.petshop.backend.exception.ResourceNotFoundException; import com.petshop.backend.exception.ResourceNotFoundException;
import com.petshop.backend.repository.StoreRepository;
import com.petshop.backend.repository.UserRepository; import com.petshop.backend.repository.UserRepository;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
@@ -14,6 +16,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.server.ResponseStatusException; import org.springframework.web.server.ResponseStatusException;
import java.util.Locale; import java.util.Locale;
import java.util.Objects;
import static org.springframework.http.HttpStatus.BAD_REQUEST; import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.CONFLICT; import static org.springframework.http.HttpStatus.CONFLICT;
@@ -24,11 +27,13 @@ public class UserService {
private final UserRepository userRepository; private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder; private final PasswordEncoder passwordEncoder;
private final UserBusinessLinkageService userBusinessLinkageService; private final UserBusinessLinkageService userBusinessLinkageService;
private final StoreRepository storeRepository;
public UserService(UserRepository userRepository, PasswordEncoder passwordEncoder, UserBusinessLinkageService userBusinessLinkageService) { public UserService(UserRepository userRepository, PasswordEncoder passwordEncoder, UserBusinessLinkageService userBusinessLinkageService, StoreRepository storeRepository) {
this.userRepository = userRepository; this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder; this.passwordEncoder = passwordEncoder;
this.userBusinessLinkageService = userBusinessLinkageService; this.userBusinessLinkageService = userBusinessLinkageService;
this.storeRepository = storeRepository;
} }
public Page<UserResponse> getAllUsers(String query, String role, Pageable pageable) { public Page<UserResponse> getAllUsers(String query, String role, Pageable pageable) {
@@ -56,12 +61,18 @@ public class UserService {
@Transactional @Transactional
public UserResponse createUser(UserRequest request) { public UserResponse createUser(UserRequest request) {
User user = new User(); User user = new User();
user.setUsername(request.getUsername()); user.setUsername(trimToNull(request.getUsername()));
user.setPassword(passwordEncoder.encode(request.getPassword())); if (request.getPassword() != null && !request.getPassword().trim().isEmpty()) {
user.setPassword(passwordEncoder.encode(request.getPassword()));
}
user.setFirstName(request.getFirstName());
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(trimToNull(request.getPhone()));
user.setRole(request.getRole()); user.setRole(request.getRole());
user.setStaffRole(trimToNull(request.getStaffRole()));
user.setPrimaryStore(resolveStore(request.getPrimaryStoreId()));
user.setActive(request.getActive() != null ? request.getActive() : true); user.setActive(request.getActive() != null ? request.getActive() : true);
validateUniquePhone(user.getPhone(), null); validateUniquePhone(user.getPhone(), null);
@@ -79,23 +90,27 @@ public class UserService {
.orElseThrow(() -> new ResourceNotFoundException("User not found with id: " + id)); .orElseThrow(() -> new ResourceNotFoundException("User not found with id: " + id));
boolean invalidateToken = boolean invalidateToken =
!user.getUsername().equals(request.getUsername()) !Objects.equals(user.getUsername(), request.getUsername())
|| 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(request.getUsername()); user.setUsername(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;
} }
user.setFirstName(request.getFirstName());
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 = trimToNull(request.getPhone());
if (!java.util.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.setPrimaryStore(resolveStore(request.getPrimaryStoreId()));
user.setActive(request.getActive() != null ? request.getActive() : true); user.setActive(request.getActive() != null ? request.getActive() : true);
if (invalidateToken) { if (invalidateToken) {
user.setTokenVersion(user.getTokenVersion() + 1); user.setTokenVersion(user.getTokenVersion() + 1);
@@ -123,16 +138,27 @@ public class UserService {
UserResponse response = new UserResponse(); UserResponse response = new UserResponse();
response.setId(user.getId()); response.setId(user.getId());
response.setUsername(user.getUsername()); response.setUsername(user.getUsername());
response.setFirstName(user.getFirstName());
response.setLastName(user.getLastName());
response.setFullName(user.getFullName()); response.setFullName(user.getFullName());
response.setEmail(user.getEmail()); response.setEmail(user.getEmail());
response.setPhone(user.getPhone()); response.setPhone(user.getPhone());
response.setRole(user.getRole().toString()); response.setRole(user.getRole().toString());
response.setStaffRole(user.getStaffRole());
response.setPrimaryStoreId(user.getPrimaryStore() != null ? user.getPrimaryStore().getStoreId() : null);
response.setLoyaltyPoints(user.getLoyaltyPoints());
response.setActive(user.getActive()); response.setActive(user.getActive());
response.setCreatedAt(user.getCreatedAt()); response.setCreatedAt(user.getCreatedAt());
response.setUpdatedAt(user.getUpdatedAt()); response.setUpdatedAt(user.getUpdatedAt());
return response; return response;
} }
private StoreLocation resolveStore(Long storeId) {
if (storeId == null) return null;
return storeRepository.findById(storeId)
.orElseThrow(() -> new ResourceNotFoundException("Store not found with id: " + storeId));
}
private void validateUniquePhone(String phone, Long currentUserId) { private void validateUniquePhone(String phone, Long currentUserId) {
if (phone == null || phone.isBlank()) { if (phone == null || phone.isBlank()) {
return; return;