feat: common code group management (separate table + CRUD)

This commit is contained in:
pray4skylark
2026-06-02 17:41:43 +09:00
parent 016b7475f7
commit 65a82db0e0
10 changed files with 648 additions and 149 deletions
@@ -3,6 +3,7 @@ package com.srsystem.controller;
import com.srsystem.dto.ApiResponse;
import com.srsystem.dto.CommonCodeRequest;
import com.srsystem.entity.CommonCode;
import com.srsystem.entity.CommonCodeGroup;
import com.srsystem.service.CommonCodeService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -13,6 +14,7 @@ import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@Tag(name = "Common Code", description = "공통 코드 관리 API")
@RestController
@@ -33,8 +35,8 @@ public class CommonCodeController {
@Operation(summary = "공통 코드 그룹 목록 조회", description = "모든 공통 코드 그룹 목록을 조회합니다")
@GetMapping("/groups")
@PreAuthorize("hasAnyRole('EMPLOYEE', 'MANAGER', 'ADMIN')")
public ResponseEntity<ApiResponse<List<String>>> getGroups() {
List<String> groups = commonCodeService.getGroupCodes();
public ResponseEntity<ApiResponse<List<CommonCodeGroup>>> getGroups() {
List<CommonCodeGroup> groups = commonCodeService.getGroups();
return ResponseEntity.ok(ApiResponse.ok(groups));
}
@@ -61,4 +63,40 @@ public class CommonCodeController {
commonCodeService.deleteCode(id);
return ResponseEntity.ok(ApiResponse.ok("공통 코드가 삭제되었습니다.", null));
}
// ---- Group CRUD ----
@Operation(summary = "그룹 생성", description = "새로운 공통 코드 그룹을 생성합니다 (ADMIN 전용)")
@PreAuthorize("hasRole('ADMIN')")
@PostMapping("/groups")
public ResponseEntity<ApiResponse<CommonCodeGroup>> createGroup(@RequestBody Map<String, String> body) {
CommonCodeGroup group = commonCodeService.createGroup(
body.get("groupCode"),
body.get("groupName"),
body.get("description"),
body.get("sortOrder") != null ? Integer.parseInt(body.get("sortOrder")) : null
);
return ResponseEntity.ok(ApiResponse.ok("그룹이 생성되었습니다.", group));
}
@Operation(summary = "그룹 수정", description = "공통 코드 그룹을 수정합니다 (ADMIN 전용)")
@PreAuthorize("hasRole('ADMIN')")
@PutMapping("/groups/{groupCode}")
public ResponseEntity<ApiResponse<CommonCodeGroup>> updateGroup(@PathVariable String groupCode, @RequestBody Map<String, String> body) {
CommonCodeGroup group = commonCodeService.updateGroup(
groupCode,
body.get("groupName"),
body.get("description"),
body.get("sortOrder") != null ? Integer.parseInt(body.get("sortOrder")) : null
);
return ResponseEntity.ok(ApiResponse.ok("그룹이 수정되었습니다.", group));
}
@Operation(summary = "그룹 삭제", description = "공통 코드 그룹을 삭제합니다 (ADMIN 전용, 하위 코드가 없을 때만 가능)")
@PreAuthorize("hasRole('ADMIN')")
@DeleteMapping("/groups/{groupCode}")
public ResponseEntity<ApiResponse<Void>> deleteGroup(@PathVariable String groupCode) {
commonCodeService.deleteGroup(groupCode);
return ResponseEntity.ok(ApiResponse.ok("그룹이 삭제되었습니다.", null));
}
}
@@ -0,0 +1,36 @@
package com.srsystem.entity;
import jakarta.persistence.*;
import lombok.*;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.SQLRestriction;
@Entity
@Table(name = "tb_common_code_group")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@SQLDelete(sql = "UPDATE tb_common_code_group SET is_deleted = 'Y' WHERE id = ?")
@SQLRestriction("is_deleted = 'N'")
public class CommonCodeGroup extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sq_common_code_groups")
@SequenceGenerator(name = "sq_common_code_groups", sequenceName = "sq_common_code_groups", allocationSize = 50)
@Column(name = "id")
private Long id;
@Column(name = "group_code", nullable = false, unique = true, length = 50)
private String groupCode;
@Column(name = "group_name", nullable = false, length = 255)
private String groupName;
@Column(name = "description", length = 500)
private String description;
@Column(name = "sort_order")
private Integer sortOrder;
}
@@ -24,6 +24,8 @@ public enum ErrorCode {
DISPATCH_NOT_FOUND(HttpStatus.NOT_FOUND, "DSP_ERR_001", "파견 이력을 찾을 수 없습니다"),
AUTH_INVALID_CREDENTIALS(HttpStatus.BAD_REQUEST, "AUTH_ERR_003", "현재 비밀번호가 일치하지 않습니다"),
CODE_NOT_FOUND(HttpStatus.NOT_FOUND, "COD_ERR_001", "공통코드를 찾을 수 없습니다"),
DUPLICATE_GROUP_CODE(HttpStatus.CONFLICT, "COD_ERR_002", "이미 존재하는 그룹 코드입니다"),
GROUP_HAS_CODES(HttpStatus.BAD_REQUEST, "COD_ERR_003", "그룹에 속한 코드가 있어 삭제할 수 없습니다"),
PLAN_NOT_FOUND(HttpStatus.NOT_FOUND, "PLN_ERR_001", "주간 계획을 찾을 수 없습니다");
private final HttpStatus httpStatus;
@@ -0,0 +1,12 @@
package com.srsystem.repository;
import com.srsystem.entity.CommonCodeGroup;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
import java.util.Optional;
public interface CommonCodeGroupRepository extends JpaRepository<CommonCodeGroup, Long> {
Optional<CommonCodeGroup> findByGroupCode(String groupCode);
List<CommonCodeGroup> findAllByOrderBySortOrderAsc();
boolean existsByGroupCode(String groupCode);
}
@@ -9,4 +9,5 @@ import java.util.List;
@Repository
public interface CommonCodeRepository extends JpaRepository<CommonCode, Long> {
List<CommonCode> findByGroupCodeAndIsActiveOrderBySortOrder(String groupCode, char isActive);
long countByGroupCode(String groupCode);
}
@@ -2,8 +2,10 @@ package com.srsystem.service;
import com.srsystem.dto.CommonCodeRequest;
import com.srsystem.entity.CommonCode;
import com.srsystem.entity.CommonCodeGroup;
import com.srsystem.exception.BusinessException;
import com.srsystem.exception.ErrorCode;
import com.srsystem.repository.CommonCodeGroupRepository;
import com.srsystem.repository.CommonCodeRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@@ -17,6 +19,7 @@ import java.util.List;
public class CommonCodeService {
private final CommonCodeRepository commonCodeRepository;
private final CommonCodeGroupRepository commonCodeGroupRepository;
public List<CommonCode> getCodes(String groupCode) {
if (groupCode != null) {
@@ -73,4 +76,51 @@ public class CommonCodeService {
code.setIsDeleted('Y');
commonCodeRepository.save(code);
}
// ---- Group CRUD ----
public List<CommonCodeGroup> getGroups() {
return commonCodeGroupRepository.findAllByOrderBySortOrderAsc();
}
public CommonCodeGroup getGroup(String groupCode) {
return commonCodeGroupRepository.findByGroupCode(groupCode)
.orElseThrow(() -> new BusinessException(ErrorCode.CODE_NOT_FOUND));
}
@Transactional
public CommonCodeGroup createGroup(String groupCode, String groupName, String description, Integer sortOrder) {
if (commonCodeGroupRepository.existsByGroupCode(groupCode)) {
throw new BusinessException(ErrorCode.DUPLICATE_GROUP_CODE);
}
CommonCodeGroup group = CommonCodeGroup.builder()
.groupCode(groupCode)
.groupName(groupName)
.description(description)
.sortOrder(sortOrder != null ? sortOrder : 0)
.build();
return commonCodeGroupRepository.save(group);
}
@Transactional
public CommonCodeGroup updateGroup(String groupCode, String groupName, String description, Integer sortOrder) {
CommonCodeGroup group = commonCodeGroupRepository.findByGroupCode(groupCode)
.orElseThrow(() -> new BusinessException(ErrorCode.CODE_NOT_FOUND));
if (groupName != null) group.setGroupName(groupName);
if (description != null) group.setDescription(description);
if (sortOrder != null) group.setSortOrder(sortOrder);
return commonCodeGroupRepository.save(group);
}
@Transactional
public void deleteGroup(String groupCode) {
CommonCodeGroup group = commonCodeGroupRepository.findByGroupCode(groupCode)
.orElseThrow(() -> new BusinessException(ErrorCode.CODE_NOT_FOUND));
long codeCount = commonCodeRepository.countByGroupCode(groupCode);
if (codeCount > 0) {
throw new BusinessException(ErrorCode.GROUP_HAS_CODES);
}
group.setIsDeleted('Y');
commonCodeGroupRepository.save(group);
}
}