feat: add department name uniqueness check and corresponding error message
This commit is contained in:
@@ -44,40 +44,13 @@ public class BizException extends RuntimeException {
|
|||||||
private final String messageCode;
|
private final String messageCode;
|
||||||
private final Object[] messageArgs;
|
private final Object[] messageArgs;
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new business exception with the specified HTTP status and message.
|
|
||||||
*
|
|
||||||
* @param message the detailed error message explaining the business logic violation
|
|
||||||
*/
|
|
||||||
public BizException(String message) {
|
|
||||||
super(message);
|
|
||||||
this.status = HttpStatus.INTERNAL_SERVER_ERROR;
|
|
||||||
this.messageCode = null;
|
|
||||||
this.messageArgs = new Object[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new business exception with the specified HTTP status and message.
|
|
||||||
*
|
|
||||||
* @param status the HTTP status code to associate with this exception
|
|
||||||
* @param message the detailed error message explaining the business logic violation
|
|
||||||
*/
|
|
||||||
public BizException(HttpStatus status, String message) {
|
|
||||||
super(message);
|
|
||||||
this.status = status;
|
|
||||||
this.messageCode = null;
|
|
||||||
this.messageArgs = new Object[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
public BizException(String messageCode, Object... messageArgs) {
|
public BizException(String messageCode, Object... messageArgs) {
|
||||||
super(messageCode);
|
|
||||||
this.status = HttpStatus.INTERNAL_SERVER_ERROR;
|
this.status = HttpStatus.INTERNAL_SERVER_ERROR;
|
||||||
this.messageCode = messageCode;
|
this.messageCode = messageCode;
|
||||||
this.messageArgs = messageArgs == null ? new Object[0] : messageArgs;
|
this.messageArgs = messageArgs == null ? new Object[0] : messageArgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BizException(HttpStatus status, String messageCode, Object... messageArgs) {
|
public BizException(HttpStatus status, String messageCode, Object... messageArgs) {
|
||||||
super(messageCode);
|
|
||||||
this.status = status;
|
this.status = status;
|
||||||
this.messageCode = messageCode;
|
this.messageCode = messageCode;
|
||||||
this.messageArgs = messageArgs == null ? new Object[0] : messageArgs;
|
this.messageArgs = messageArgs == null ? new Object[0] : messageArgs;
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package com.onixbyte.helix.manager;
|
|||||||
import com.onixbyte.helix.domain.entity.Department;
|
import com.onixbyte.helix.domain.entity.Department;
|
||||||
import com.onixbyte.helix.exception.BizException;
|
import com.onixbyte.helix.exception.BizException;
|
||||||
import com.onixbyte.helix.repository.DepartmentRepository;
|
import com.onixbyte.helix.repository.DepartmentRepository;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
@@ -68,4 +70,8 @@ public class DepartmentManager {
|
|||||||
departmentToEdit.setUpdatedAt(updatedAt);
|
departmentToEdit.setUpdatedAt(updatedAt);
|
||||||
return departmentToEdit;
|
return departmentToEdit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean existsByName(String name) {
|
||||||
|
return departmentRepository.existsByName(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,4 +15,6 @@ public interface DepartmentRepository extends JpaRepository<Department, Long> {
|
|||||||
or d.parentId = :parentId
|
or d.parentId = :parentId
|
||||||
""")
|
""")
|
||||||
Integer findMaxSort(Long parentId);
|
Integer findMaxSort(Long parentId);
|
||||||
|
|
||||||
|
boolean existsByName(String name);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,13 @@ import com.onixbyte.helix.domain.common.TreeNode;
|
|||||||
import com.onixbyte.helix.domain.entity.Department;
|
import com.onixbyte.helix.domain.entity.Department;
|
||||||
import com.onixbyte.helix.domain.web.request.DepartmentRequest;
|
import com.onixbyte.helix.domain.web.request.DepartmentRequest;
|
||||||
import com.onixbyte.helix.enumeration.Status;
|
import com.onixbyte.helix.enumeration.Status;
|
||||||
|
import com.onixbyte.helix.exception.BizException;
|
||||||
import com.onixbyte.helix.manager.DepartmentManager;
|
import com.onixbyte.helix.manager.DepartmentManager;
|
||||||
|
import com.onixbyte.helix.shared.MessageName;
|
||||||
import com.onixbyte.helix.utils.TreeUtil;
|
import com.onixbyte.helix.utils.TreeUtil;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
@@ -38,6 +41,10 @@ public class DepartmentService {
|
|||||||
public Department addDepartment(DepartmentRequest request) {
|
public Department addDepartment(DepartmentRequest request) {
|
||||||
var createdAt = LocalDateTime.now();
|
var createdAt = LocalDateTime.now();
|
||||||
|
|
||||||
|
if (departmentManager.existsByName(request.name())) {
|
||||||
|
throw new BizException(HttpStatus.CONFLICT, MessageName.REQUEST_CREATE_DEPARTMENT_NAME_DUPLICATED);
|
||||||
|
}
|
||||||
|
|
||||||
var parentId = request.parentId();
|
var parentId = request.parentId();
|
||||||
var sort = Optional.ofNullable(request.sort())
|
var sort = Optional.ofNullable(request.sort())
|
||||||
.orElseGet(() -> departmentManager.getNextSort(parentId));
|
.orElseGet(() -> departmentManager.getNextSort(parentId));
|
||||||
|
|||||||
@@ -79,4 +79,6 @@ public class MessageName {
|
|||||||
|
|
||||||
public static final String REQUEST_QUERY_ROLE_STATUS_INVALID = "request.query-role.status.invalid";
|
public static final String REQUEST_QUERY_ROLE_STATUS_INVALID = "request.query-role.status.invalid";
|
||||||
public static final String REQUEST_QUERY_USER_STATUS_INVALID = "request.query-user.status.invalid";
|
public static final String REQUEST_QUERY_USER_STATUS_INVALID = "request.query-user.status.invalid";
|
||||||
|
|
||||||
|
public static final String REQUEST_CREATE_DEPARTMENT_NAME_DUPLICATED = "request.create-department.name-duplicated";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,28 +19,58 @@
|
|||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
# SOFTWARE.
|
# SOFTWARE.
|
||||||
#
|
#
|
||||||
tree.multiple-roots=
|
|
||||||
user.not-found=User with ID [{0}] not found.
|
|
||||||
security.context-user-not-found=Cannot retrieve user information from security context.
|
|
||||||
role.not-exists=Role does not exist in database.
|
|
||||||
captcha.generate-failed=
|
|
||||||
auth.provider.password-not-configured=Username or password is incorrect.
|
|
||||||
auth.provider.bad-credentials=Username or password is incorrect.
|
|
||||||
auth.provider.failed=Authentication failed, please try again later.
|
|
||||||
auth.login.failed=Cannot perform login due to server error.
|
|
||||||
auth.login.captcha-incorrect=Captcha is incorrect.
|
|
||||||
auth.login.captcha-not-found=Captcha not found.
|
|
||||||
authority.not-found=Authority with ID [{0}] not found.
|
|
||||||
authority.code-used=Authority code [{0}] is already in use.
|
|
||||||
asset.upload-failed=Failed to upload file: {0}
|
|
||||||
asset.delete-forbidden=You are not able to delete an asset that is not uploaded by you.
|
|
||||||
asset.invalid-prefix=Prefix must not be empty and must not start with '/' or '..'.
|
|
||||||
asset.not-empty = File cannot be empty.
|
asset.not-empty = File cannot be empty.
|
||||||
|
asset.invalid-prefix = Prefix must not be empty and must not start with '/' or '..'.
|
||||||
|
asset.delete-forbidden = You are not able to delete an asset that is not uploaded by you.
|
||||||
|
asset.upload-failed = Failed to upload file: {0}
|
||||||
|
|
||||||
authority.deleted = Authority [{0}] deleted.
|
authority.deleted = Authority [{0}] deleted.
|
||||||
|
authority.code-used = Authority code [{0}] is already in use.
|
||||||
|
authority.not-found = Authority with ID [{0}] not found.
|
||||||
|
|
||||||
|
auth.login.captcha-not-found = Captcha not found.
|
||||||
|
auth.login.captcha-incorrect = Captcha is incorrect.
|
||||||
|
auth.login.failed = Cannot perform login due to server error.
|
||||||
|
|
||||||
|
auth.provider.failed = Authentication failed, please try again later.
|
||||||
|
auth.provider.bad-credentials = Username or password is incorrect.
|
||||||
|
auth.provider.password-not-configured=Username or password is incorrect.
|
||||||
|
|
||||||
|
captcha.generate-failed = Unable to generate captcha image.
|
||||||
|
role.not-exists=Name of the authority cannot be null.
|
||||||
|
role.not-found = Role with ID {0} not found.
|
||||||
|
role.deleted = Role [{0}] deleted.
|
||||||
|
|
||||||
user.password-reset-success = Password has been reset.
|
user.password-reset-success = Password has been reset.
|
||||||
user.deleted = User [{0}] deleted.
|
user.deleted = User [{0}] deleted.
|
||||||
role.not-found=Role with ID {0} not found.
|
user.not-found = User with ID [{0}] not found.
|
||||||
role.deleted=Role [{0}] deleted.
|
|
||||||
|
security.context-user-not-found = Cannot retrieve user information from security context.
|
||||||
|
tree.multiple-roots = Multiple root items found in given values.
|
||||||
|
|
||||||
|
request.add-user.username.not-empty = Username cannot be empty.
|
||||||
|
request.add-user.password.not-empty = Password cannot be empty.
|
||||||
|
request.add-user.full-name.not-empty = Full name cannot be empty.
|
||||||
|
|
||||||
|
request.authority.code.not-editable = Code cannot be edited.
|
||||||
|
request.authority.code.not-null = Code cannot be null.
|
||||||
|
request.authority.name.not-null = Name of the authority cannot be null.
|
||||||
|
|
||||||
|
request.department.name.not-null = Name of the department should not be null.
|
||||||
|
|
||||||
|
request.edit-role.id.not-null = Role ID cannot be null.
|
||||||
|
request.edit-role.status.invalid = Status can only be ACTIVE or INACTIVE.
|
||||||
|
|
||||||
|
request.edit-user.id.not-null = User ID cannot be null.
|
||||||
|
request.edit-user.id.positive = User ID must be positive.
|
||||||
|
|
||||||
|
request.reset-password.password.not-empty = Password cannot be empty.
|
||||||
|
|
||||||
request.role.name.not-empty = Name of the role cannot be empty.
|
request.role.name.not-empty = Name of the role cannot be empty.
|
||||||
|
request.role.code.not-empty = Code of the role cannot be empty.
|
||||||
|
request.role.sort.not-null = Sort number cannot be null.
|
||||||
|
|
||||||
|
request.query-role.status.invalid = Status can only be ACTIVE or INACTIVE.
|
||||||
|
request.query-user.status.invalid = Status can only be ACTIVE, INACTIVE, or LOCKED.
|
||||||
|
request.create-department.name-duplicated=Name of the department already exists.
|
||||||
|
|||||||
@@ -74,3 +74,4 @@ request.role.sort.not-null = Sort number cannot be null.
|
|||||||
|
|
||||||
request.query-role.status.invalid = Status can only be ACTIVE or INACTIVE.
|
request.query-role.status.invalid = Status can only be ACTIVE or INACTIVE.
|
||||||
request.query-user.status.invalid = Status can only be ACTIVE, INACTIVE, or LOCKED.
|
request.query-user.status.invalid = Status can only be ACTIVE, INACTIVE, or LOCKED.
|
||||||
|
request.create-department.name-duplicated=Name of the department already exists.
|
||||||
|
|||||||
@@ -74,3 +74,4 @@ request.role.sort.not-null = 排序编号不能为空。
|
|||||||
|
|
||||||
request.query-role.status.invalid = 状态只能是 ACTIVE 或 INACTIVE。
|
request.query-role.status.invalid = 状态只能是 ACTIVE 或 INACTIVE。
|
||||||
request.query-user.status.invalid = 状态只能是 ACTIVE、INACTIVE 或 LOCKED。
|
request.query-user.status.invalid = 状态只能是 ACTIVE、INACTIVE 或 LOCKED。
|
||||||
|
request.create-department.name-duplicated=部门名称已存在。
|
||||||
|
|||||||
Reference in New Issue
Block a user