공통코드 중복체크,등록,수정,순서저장 API 커밋

This commit is contained in:
2025-12-05 15:32:47 +09:00
parent bcce56438f
commit 3804582b82
9 changed files with 210 additions and 171 deletions

View File

@@ -89,7 +89,7 @@ public class CommonCodeApiController {
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
})
@PostMapping
public ApiResponseDto<Long> save(
public ApiResponseDto<ApiResponseDto.ResponseObj> save(
@io.swagger.v3.oas.annotations.parameters.RequestBody(
description = "공통코드 생성 요청 정보",
required = true,
@@ -100,7 +100,7 @@ public class CommonCodeApiController {
@RequestBody
@Valid
CommonCodeDto.AddReq req) {
return ApiResponseDto.createOK(commonCodeService.save(req));
return ApiResponseDto.okObject(commonCodeService.save(req));
}
@Operation(summary = "수정", description = "공통코드를 수정 합니다.")
@@ -118,7 +118,7 @@ public class CommonCodeApiController {
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
})
@PutMapping("/{id}")
public ApiResponseDto<Void> update(
public ApiResponseDto<ApiResponseDto.ResponseObj> update(
@io.swagger.v3.oas.annotations.parameters.RequestBody(
description = "공통코드 수정 요청 정보",
required = true,
@@ -129,8 +129,7 @@ public class CommonCodeApiController {
@PathVariable
Long id,
@RequestBody @Valid CommonCodeDto.ModifyReq req) {
commonCodeService.update(id, req);
return ApiResponseDto.deleteOk(null);
return ApiResponseDto.okObject(commonCodeService.update(id, req));
}
@Operation(summary = "삭제", description = "공통코드를 삭제 합니다.")
@@ -172,7 +171,7 @@ public class CommonCodeApiController {
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
})
@PutMapping("/order")
public ApiResponseDto<Void> updateOrder(
public ApiResponseDto<ApiResponseDto.ResponseObj> updateOrder(
@io.swagger.v3.oas.annotations.parameters.RequestBody(
description = "공통코드 순서변경 요청 정보",
required = true,
@@ -183,8 +182,8 @@ public class CommonCodeApiController {
@RequestBody
@Valid
CommonCodeDto.OrderReq req) {
commonCodeService.updateOrder(req);
return ApiResponseDto.deleteOk(null);
return ApiResponseDto.okObject(commonCodeService.updateOrder(req));
}
@Operation(summary = "code 기반 조회", description = "code 기반 조회")
@@ -192,7 +191,7 @@ public class CommonCodeApiController {
value = {
@ApiResponse(
responseCode = "200",
description = "공통코드 순서 변경 성공",
description = "code 기반 조회 성공",
content =
@Content(
mediaType = "application/json",
@@ -222,4 +221,26 @@ public class CommonCodeApiController {
return ApiResponseDto.ok(list);
}
@Operation(summary = "공통코드 중복여부 체크", description = "공통코드 중복여부 체크")
@ApiResponses(
value = {
@ApiResponse(
responseCode = "200",
description = "조회 성공",
content =
@Content(
mediaType = "application/json",
schema = @Schema(implementation = CommonCodeDto.Basic.class))),
@ApiResponse(responseCode = "404", description = "코드를 찾을 수 없음", content = @Content),
@ApiResponse(responseCode = "500", description = "서버 오류", content = @Content)
})
@GetMapping("/check-duplicate")
public ApiResponseDto<ApiResponseDto.ResponseObj> getCodeCheckDuplicate(
@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "단건 조회", required = true)
@RequestParam
Long parentId,
@RequestParam String code) {
return ApiResponseDto.okObject(commonCodeService.getCodeCheckDuplicate(parentId, code));
}
}

View File

@@ -2,7 +2,6 @@ package com.kamco.cd.kamcoback.code.dto;
import com.kamco.cd.kamcoback.common.utils.interfaces.JsonFormatDttm;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import java.time.ZonedDateTime;
@@ -39,10 +38,8 @@ public class CommonCodeDto {
@NoArgsConstructor
@AllArgsConstructor
public static class ModifyReq {
@NotEmpty private String code;
@NotEmpty private String name;
private String description;
private int order;
private boolean used;
private String props1;
@@ -56,7 +53,8 @@ public class CommonCodeDto {
@NoArgsConstructor
@AllArgsConstructor
public static class OrderReq {
@Valid List<OrderReqDetail> orders;
@NotNull private Long id;
@NotNull private Integer order;
}
@Getter
@@ -65,7 +63,6 @@ public class CommonCodeDto {
@AllArgsConstructor
public static class OrderReqDetail {
@NotNull private Long id;
@NotNull private Integer order;
}
@@ -90,8 +87,7 @@ public class CommonCodeDto {
private String props2;
private String props3;
@JsonFormatDttm
private ZonedDateTime deletedDttm;
@JsonFormatDttm private ZonedDateTime deletedDttm;
public Basic(
Long id,
@@ -107,8 +103,7 @@ public class CommonCodeDto {
String props1,
String props2,
String props3,
ZonedDateTime deletedDttm
) {
ZonedDateTime deletedDttm) {
this.id = id;
this.code = code;
this.description = description;

View File

@@ -44,8 +44,8 @@ public class CommonCodeService {
* @return 생성된 코드 id
*/
@Transactional
public Long save(AddReq req) {
return commonCodeCoreService.save(req).getId();
public ApiResponseDto.ResponseObj save(AddReq req) {
return commonCodeCoreService.save(req);
}
/**
@@ -55,8 +55,8 @@ public class CommonCodeService {
* @param req 수정요청 정보
*/
@Transactional
public void update(Long id, ModifyReq req) {
commonCodeCoreService.update(id, req);
public ApiResponseDto.ResponseObj update(Long id, ModifyReq req) {
return commonCodeCoreService.update(id, req);
}
/**
@@ -75,8 +75,8 @@ public class CommonCodeService {
* @param req id, order 정보를 가진 List
*/
@Transactional
public void updateOrder(OrderReq req) {
commonCodeCoreService.updateOrder(req);
public ApiResponseDto.ResponseObj updateOrder(OrderReq req) {
return commonCodeCoreService.updateOrder(req);
}
/**
@@ -88,4 +88,15 @@ public class CommonCodeService {
public List<Basic> findByCode(String code) {
return commonCodeCoreService.findByCode(code);
}
/**
* 중복 체크
*
* @param parentId
* @param code
* @return
*/
public ApiResponseDto.ResponseObj getCodeCheckDuplicate(Long parentId, String code) {
return commonCodeCoreService.getCodeCheckDuplicate(parentId, code);
}
}

View File

@@ -15,7 +15,6 @@ import java.nio.file.AccessDeniedException;
import java.time.ZonedDateTime;
import java.util.Arrays;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
@@ -376,15 +375,16 @@ public class GlobalExceptionHandler {
Long userid = null;
/**
* servletRequest.getUserPrincipal() instanceof UsernamePasswordAuthenticationToken auth
* 이 요청이 JWT 인증을 통과한 요청인가? 그리고 Spring Security Authentication 객체가 UsernamePasswordAuthenticationToken 타입인가? 체크
* servletRequest.getUserPrincipal() instanceof UsernamePasswordAuthenticationToken auth 이 요청이
* JWT 인증을 통과한 요청인가? 그리고 Spring Security Authentication 객체가 UsernamePasswordAuthenticationToken
* 타입인가? 체크
*/
/**
* auth.getPrincipal() instanceof CustomUserDetails customUserDetails
* principal 안에 들어있는 객체가 내가 만든 CustomUserDetails 타입인가? 체크
* auth.getPrincipal() instanceof CustomUserDetails customUserDetails principal 안에 들어있는 객체가 내가
* 만든 CustomUserDetails 타입인가? 체크
*/
if (request.getUserPrincipal() instanceof UsernamePasswordAuthenticationToken auth
&& auth.getPrincipal() instanceof CustomUserDetails customUserDetails) {
&& auth.getPrincipal() instanceof CustomUserDetails customUserDetails) {
// audit 에는 long 타입 user_id가 들어가지만 토큰 sub은 uuid여서 user_id 가져오기
userid = customUserDetails.getMember().getId();

View File

@@ -70,7 +70,7 @@ public class ApiResponseDto<T> {
public static <T> ApiResponseDto<ResponseObj> okObject(ResponseObj data) {
if (data.getFlag().equals(SuccFailCode.SUCCESS)) {
return new ApiResponseDto<>(data, HttpStatus.OK);
} else{
} else {
return new ApiResponseDto<>(data.getCode(), data.getMessage(), HttpStatus.OK);
}
}
@@ -114,6 +114,7 @@ public class ApiResponseDto<T> {
}
}
/** Error가 아닌 Business상 성공이거나 실패인 경우, 메세지 함께 전달하기 위한 object */
@Getter
public static class ResponseObj {

View File

@@ -10,13 +10,11 @@ import com.kamco.cd.kamcoback.postgres.entity.CommonCodeEntity;
import com.kamco.cd.kamcoback.postgres.repository.code.CommonCodeRepository;
import com.kamco.cd.kamcoback.zoo.dto.AnimalDto.SearchReq;
import jakarta.persistence.EntityNotFoundException;
import lombok.RequiredArgsConstructor;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
@@ -25,38 +23,35 @@ public class CommonCodeCoreService
private final CommonCodeRepository commonCodeRepository;
/**
* 모두 조회
*
* @return
*/
public List<CommonCodeDto.Basic> findAll() {
return commonCodeRepository.findByAll().stream().map(CommonCodeEntity::toDto).toList();
}
public CommonCodeDto.Basic save(CommonCodeDto.AddReq req) {
if (req.getParentId() != null) {
CommonCodeEntity parentCommonCodeEntity =
commonCodeRepository
.findById(req.getParentId())
.orElseThrow(
() ->
new EntityNotFoundException(
"parent id 를 찾을 수 없습니다. id : " + req.getParentId()));
/**
* 등록
*
* @param req
* @return
*/
public ResponseObj save(CommonCodeDto.AddReq req) {
Long existsCount =
commonCodeRepository.findByParentIdCodeExists(req.getParentId(), req.getCode());
if (existsCount > 0) {
throw new DuplicateKeyException("이미 등록되어 있습니다.");
}
String regex = "^[A-Z0-9_]+$";
boolean isValid = req.getCode().matches(regex);
if (!isValid) {
return new ResponseObj(
SuccFailCode.FAIL, ApiResponseCode.CONFLICT, "공통코드에 영문 대문자, 숫자, 언더바(_)만 입력 가능합니다.");
}
CommonCodeEntity entity =
new CommonCodeEntity(
req.getCode(),
req.getName(),
req.getDescription(),
req.getOrder(),
req.isUsed(),
req.getProps1(),
req.getProps2(),
req.getProps3());
entity.addParent(parentCommonCodeEntity);
return commonCodeRepository.save(entity).toDto();
Long existsCount =
commonCodeRepository.findByParentIdCodeExists(req.getParentId(), req.getCode());
if (existsCount > 0) {
return new ResponseObj(
SuccFailCode.FAIL, ApiResponseCode.DUPLICATE_DATA, "이미 사용중인 공통코드ID 입니다.");
}
CommonCodeEntity entity =
@@ -69,42 +64,64 @@ public class CommonCodeCoreService
req.getProps1(),
req.getProps2(),
req.getProps3());
return commonCodeRepository.save(entity).toDto();
if (req.getParentId() != null) {
CommonCodeEntity parentCommonCodeEntity =
commonCodeRepository
.findById(req.getParentId())
.orElseThrow(
() ->
new EntityNotFoundException(
"parent id 를 찾을 수 없습니다. id : " + req.getParentId()));
entity.addParent(parentCommonCodeEntity);
}
commonCodeRepository.save(entity).toDto();
return new ResponseObj(SuccFailCode.SUCCESS, ApiResponseCode.OK, "등록되었습니다.");
}
public CommonCodeDto.Basic update(Long id, CommonCodeDto.ModifyReq req) {
/**
* 수정
*
* @param id
* @param req
* @return
*/
public ResponseObj update(Long id, CommonCodeDto.ModifyReq req) {
CommonCodeEntity found =
commonCodeRepository
.findByCodeId(id)
.orElseThrow(() -> new EntityNotFoundException("common code 를 찾을 수 없습니다. id : " + id));
Long parentId = found.getParent() == null ? null : found.getParent().getId();
Long existsCount =
commonCodeRepository.findByParentIdCodeExiststoUpdate(id, parentId, req.getCode());
if (existsCount > 0) {
throw new DuplicateKeyException("이미 등록되어 있습니다.");
}
found.update(
req.getName(),
req.getDescription(),
req.isUsed(),
req.getProps1(),
req.getProps2(),
req.getProps3());
CommonCodeEntity entity =
new CommonCodeEntity(
id,
req.getCode(),
req.getName(),
req.getDescription(),
req.getOrder(),
req.isUsed(),
found.getDeleted(),
req.getProps1(),
req.getProps2(),
req.getProps3(),
null
);
return commonCodeRepository.save(entity).toDto();
return new ResponseObj(SuccFailCode.SUCCESS, ApiResponseCode.OK, "수정되었습니다.");
}
public void updateOrder(CommonCodeDto.OrderReq req) {
commonCodeRepository.updateOrder(req);
/**
* 순서 변경
*
* @param req
* @return
*/
public ResponseObj updateOrder(CommonCodeDto.OrderReq req) {
CommonCodeEntity found =
commonCodeRepository
.findByCodeId(req.getId())
.orElseThrow(
() -> new EntityNotFoundException("common code 를 찾을 수 없습니다. id : " + req.getId()));
found.updateOrder(req.getOrder());
return new ResponseObj(SuccFailCode.SUCCESS, ApiResponseCode.OK, "수정되었습니다.");
}
public List<CommonCodeDto.Basic> findByCode(String code) {
@@ -124,6 +141,7 @@ public class CommonCodeCoreService
/**
* 공통코드 삭제
*
* @param id
* @return
*/
@@ -134,8 +152,11 @@ public class CommonCodeCoreService
.orElseThrow(() -> new EntityNotFoundException("code를 찾을 수 없습니다. id " + id));
// 하위코드가 있으면 삭제 불가
if(!entity.getChildren().isEmpty()){
return new ResponseObj(SuccFailCode.FAIL, ApiResponseCode.UNPROCESSABLE_ENTITY,"하위에 다른 공통코드를 가지고 있습니다.<br/>하위공통 코드를 이동한 후 삭제할 수 있습니다.");
if (!entity.getChildren().isEmpty()) {
return new ResponseObj(
SuccFailCode.FAIL,
ApiResponseCode.UNPROCESSABLE_ENTITY,
"하위에 다른 공통코드를 가지고 있습니다.<br/>하위공통 코드를 이동한 후 삭제할 수 있습니다.");
}
// id 코드 deleted = false 업데이트
@@ -145,9 +166,15 @@ public class CommonCodeCoreService
@Override
public void remove(Long aLong) {
//미사용
// 미사용
}
/**
* id 로 단건 조회
*
* @param id
* @return
*/
@Override
public Basic getOneById(Long id) {
CommonCodeEntity entity =
@@ -161,4 +188,29 @@ public class CommonCodeCoreService
public Page<Basic> search(SearchReq searchReq) {
return null;
}
/**
* 중복 체크
*
* @param parentId
* @param code
* @return
*/
public ResponseObj getCodeCheckDuplicate(Long parentId, String code) {
Long existsCount = commonCodeRepository.findByParentIdCodeExists(parentId, code);
String regex = "^[A-Z0-9_]+$";
boolean isValid = code.matches(regex);
if (!isValid) {
return new ResponseObj(
SuccFailCode.FAIL, ApiResponseCode.CONFLICT, "공통코드에 영문 대문자, 숫자, 언더바(_)만 입력 가능합니다.");
}
if (existsCount > 0) {
return new ResponseObj(
SuccFailCode.FAIL, ApiResponseCode.DUPLICATE_DATA, "이미 사용중인 공통코드ID 입니다.");
}
return new ResponseObj(SuccFailCode.SUCCESS, ApiResponseCode.OK, "사용할 수 있는 공통코드ID 입니다.");
}
}

View File

@@ -15,7 +15,6 @@ import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.List;
@@ -97,32 +96,6 @@ public class CommonCodeEntity extends CommonDateEntity {
this.props3 = props3;
}
public CommonCodeEntity(
Long id,
String code,
String name,
String description,
Integer order,
Boolean used,
Boolean deleted,
String props1,
String props2,
String props3,
ZonedDateTime deletedDttm
) {
this.id = id;
this.code = code;
this.name = name;
this.description = description;
this.order = order;
this.used = used;
this.deleted = deleted;
this.props1 = props1;
this.props2 = props2;
this.props3 = props3;
this.deletedDttm = deletedDttm;
}
public CommonCodeDto.Basic toDto() {
return new CommonCodeDto.Basic(
this.id,
@@ -138,8 +111,7 @@ public class CommonCodeEntity extends CommonDateEntity {
this.props1,
this.props2,
this.props3,
this.deletedDttm
);
this.deletedDttm);
}
public void addParent(CommonCodeEntity parent) {
@@ -158,4 +130,14 @@ public class CommonCodeEntity extends CommonDateEntity {
public void updateOrder(int order) {
this.order = order;
}
public void update(
String name, String description, boolean used, String props1, String props2, String props3) {
this.name = name;
this.description = description;
this.used = used;
this.props1 = props1;
this.props2 = props2;
this.props3 = props3;
}
}

View File

@@ -1,6 +1,5 @@
package com.kamco.cd.kamcoback.postgres.repository.code;
import com.kamco.cd.kamcoback.code.dto.CommonCodeDto;
import com.kamco.cd.kamcoback.postgres.entity.CommonCodeEntity;
import jakarta.validation.constraints.NotEmpty;
import java.util.List;
@@ -13,11 +12,7 @@ public interface CommonCodeRepositoryCustom {
List<CommonCodeEntity> findByAll();
void updateOrder(CommonCodeDto.OrderReq req);
Optional<String> getCode(String parentCodeCd, String childCodeCd);
Long findByParentIdCodeExists(Long parentId, @NotEmpty String code);
Long findByParentIdCodeExiststoUpdate(Long id, Long parentId, @NotEmpty String code);
}

View File

@@ -2,16 +2,12 @@ package com.kamco.cd.kamcoback.postgres.repository.code;
import static com.kamco.cd.kamcoback.postgres.entity.QCommonCodeEntity.commonCodeEntity;
import com.kamco.cd.kamcoback.code.dto.CommonCodeDto;
import com.kamco.cd.kamcoback.code.dto.CommonCodeDto.OrderReqDetail;
import com.kamco.cd.kamcoback.postgres.entity.CommonCodeEntity;
import com.kamco.cd.kamcoback.postgres.entity.QCommonCodeEntity;
import com.querydsl.jpa.impl.JPAQueryFactory;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
@@ -30,10 +26,9 @@ public class CommonCodeRepositoryImpl implements CommonCodeRepositoryCustom {
.leftJoin(commonCodeEntity.children, child)
.fetchJoin()
.where(
commonCodeEntity.id.eq(id),
commonCodeEntity.deleted.isFalse().or(commonCodeEntity.deleted.isNull()),
child.deleted.isFalse().or(child.deleted.isNull())
)
commonCodeEntity.id.eq(id),
commonCodeEntity.deleted.isFalse().or(commonCodeEntity.deleted.isNull()),
child.deleted.isFalse().or(child.deleted.isNull()))
.orderBy(commonCodeEntity.order.asc(), child.order.asc())
.fetchOne());
}
@@ -51,8 +46,7 @@ public class CommonCodeRepositoryImpl implements CommonCodeRepositoryCustom {
commonCodeEntity.code.eq(code),
commonCodeEntity.used.isTrue(),
commonCodeEntity.deleted.isFalse().or(commonCodeEntity.deleted.isNull()),
child.deleted.isFalse().or(child.deleted.isNull())
)
child.deleted.isFalse().or(child.deleted.isNull()))
.orderBy(child.order.asc())
.fetchOne());
}
@@ -65,30 +59,29 @@ public class CommonCodeRepositoryImpl implements CommonCodeRepositoryCustom {
.leftJoin(commonCodeEntity.children, child)
.fetchJoin()
.where(
commonCodeEntity.parent.isNull(),
commonCodeEntity.deleted.isFalse().or(commonCodeEntity.deleted.isNull()),
child.deleted.isFalse().or(child.deleted.isNull())
)
commonCodeEntity.parent.isNull(),
commonCodeEntity.deleted.isFalse().or(commonCodeEntity.deleted.isNull()),
child.deleted.isFalse().or(child.deleted.isNull()))
.orderBy(commonCodeEntity.order.asc(), child.order.asc())
.fetch();
}
@Override
public void updateOrder(CommonCodeDto.OrderReq req) {
Map<Long, Integer> orderMap =
req.getOrders().stream()
.collect(Collectors.toMap(OrderReqDetail::getId, OrderReqDetail::getOrder));
List<CommonCodeEntity> entity = findAllByIds(orderMap.keySet());
entity.forEach(
commonCodeEntity -> {
Integer order = orderMap.get(commonCodeEntity.getId());
if (order != null) {
commonCodeEntity.updateOrder(order);
}
});
}
// @Override
// public void updateOrder(CommonCodeDto.OrderReq req) {
// Map<Long, Integer> orderMap =
// req.getOrders().stream()
// .collect(Collectors.toMap(OrderReqDetail::getId, OrderReqDetail::getOrder));
//
// List<CommonCodeEntity> entity = findAllByIds(orderMap.keySet());
//
// entity.forEach(
// commonCodeEntity -> {
// Integer order = orderMap.get(commonCodeEntity.getId());
// if (order != null) {
// commonCodeEntity.updateOrder(order);
// }
// });
// }
@Override
public Optional<String> getCode(String parentCodeCd, String childCodeCd) {
@@ -101,9 +94,8 @@ public class CommonCodeRepositoryImpl implements CommonCodeRepositoryCustom {
.from(child)
.join(child.parent, parent)
.where(
parent.code.eq(parentCodeCd).and(child.code.eq(childCodeCd)),
child.deleted.isFalse().or(child.deleted.isNull())
)
parent.code.eq(parentCodeCd).and(child.code.eq(childCodeCd)),
child.deleted.isFalse().or(child.deleted.isNull()))
.fetchFirst(); // 단일 결과만
return Optional.ofNullable(result);
@@ -118,22 +110,12 @@ public class CommonCodeRepositoryImpl implements CommonCodeRepositoryCustom {
.fetchOne();
}
@Override
public Long findByParentIdCodeExiststoUpdate(Long id, Long parentId, String code) {
return queryFactory
.select(commonCodeEntity.code.count())
.from(commonCodeEntity)
.where(
commonCodeEntity.parent.id.eq(parentId),
commonCodeEntity.code.eq(code),
commonCodeEntity.id.ne(id))
.fetchOne();
}
private List<CommonCodeEntity> findAllByIds(Set<Long> ids) {
return queryFactory
.selectFrom(commonCodeEntity)
.where(commonCodeEntity.id.in(ids), commonCodeEntity.deleted.isFalse().or(commonCodeEntity.deleted.isNull()))
.where(
commonCodeEntity.id.in(ids),
commonCodeEntity.deleted.isFalse().or(commonCodeEntity.deleted.isNull()))
.fetch();
}
}