[UPDATE] PROJECT 추가

main
bjkim 11 months ago
parent 82e7886096
commit cbfb56ac52

@ -0,0 +1,83 @@
package kr.re.etri.security.jwt.controllers;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag;
import kr.re.etri.security.jwt.entity.ProjectEntity;
import kr.re.etri.security.jwt.payload.request.BaseSearchRequest;
import kr.re.etri.security.jwt.payload.request.ProjectRequest;
import kr.re.etri.security.jwt.service.ProjectService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.data.domain.Page;
import java.util.List;
@Tag(name = "프로젝트 API", description = "Project CRUD 기능 제공")
@RestController
@RequestMapping("/api/projects")
@RequiredArgsConstructor
public class ProjectController {
private final ProjectService projectService;
@Operation(summary = "전체 프로젝트 목록 조회")
@GetMapping
public ResponseEntity<List<ProjectEntity>> getAllProjects() {
return ResponseEntity.ok(projectService.findAll());
}
@Operation(summary = "ID로 프로젝트 조회")
@GetMapping("/{id}")
public ResponseEntity<ProjectEntity> getProjectById(
@Parameter(description = "조회할 프로젝트 ID", required = true, in = ParameterIn.PATH)
@PathVariable("id") Long id) {
return projectService.findById(id)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
@Operation(summary = "검색 및 페이지네이션 프로젝트 목록 조회")
@GetMapping("/search")
public ResponseEntity<Page<ProjectEntity>> searchProjects(BaseSearchRequest request) {
Page<ProjectEntity> page = projectService.search(request);
return ResponseEntity.ok(page);
}
@Operation(summary = "프로젝트 생성")
@PostMapping
public ResponseEntity<?> createProject(@RequestBody ProjectEntity project) {
try {
ProjectEntity saved = projectService.create(project);
return ResponseEntity.ok(saved);
} catch (IllegalArgumentException e) {
return ResponseEntity.badRequest().body(e.getMessage());
}
}
@Operation(summary = "프로젝트 수정")
@PutMapping("/{id}")
public ResponseEntity<ProjectEntity> updateProject(
@Parameter(description = "수정할 프로젝트 ID", required = true, in = ParameterIn.PATH)
@PathVariable("id") Long id,
@RequestBody ProjectRequest dto) {
return projectService.update(id, dto)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
@Operation(summary = "프로젝트 삭제")
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteProject(
@Parameter(description = "삭제할 프로젝트 ID", required = true, in = ParameterIn.PATH)
@PathVariable("id") Long id) {
if (projectService.delete(id)) {
return ResponseEntity.noContent().build();
}
return ResponseEntity.notFound().build();
}
}

@ -1,15 +1,13 @@
package kr.re.etri.security.jwt.entity;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.*;
import org.hibernate.annotations.Comment;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
@Schema(description = "프로젝트")
@Comment("프로젝트")
@Entity
@Table(name = "tb_project")
@ -22,33 +20,58 @@ public class ProjectEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Schema(description = "ID", example = "null")
@Comment("ID")
private Long id;
@Column(unique = true)
@Schema(description = "프로젝트 코드", example = "PRJ001")
@Comment("프로젝트 코드")
private String prjCd;
@Schema(description = "프로젝트 이름", example = "AI 연구 프로젝트")
@Comment("프로젝트 이름")
private String prjNm;
@Schema(description = "프로젝트 설명", example = "ETRI와 함께하는 AI 개발")
@Comment("프로젝트 설명")
private String prjDesc;
@Schema(description = "프로젝트 시작일", example = "2025-08-01")
@Comment("프로젝트 시작일")
private String prjStartDt;
@Schema(description = "프로젝트 종료일", example = "2025-12-31")
@Comment("프로젝트 종료일")
private String prjEndDt;
@Schema(description = "삭제 여부", example = "N")
@Comment("삭제 여부")
private String delYn;
@CreatedDate
@Schema(description = "등록 일자", example = "2025-08-01T12:34:56")
@Comment("등록 일자")
private String regDate;
@Schema(description = "등록 유저 ID", example = "admin")
@Comment("등록 유저 ID")
private String regUserId;
@Schema(description = "등록 유저 이름", example = "관리자")
@Comment("등록 유저 이름")
private String regUserNm;
@LastModifiedDate
@Schema(description = "수정 일자", example = "2025-08-01T13:45:00")
@Comment("수정 일자")
private String modDate;
@Schema(description = "수정 유저 ID", example = "editor")
@Comment("수정 유저 ID")
private String modUserId;
@Schema(description = "수정 유저 이름", example = "에디터")
@Comment("수정 유저 이름")
private String modUserNm;
}

@ -0,0 +1,28 @@
package kr.re.etri.security.jwt.payload.request;
import lombok.Getter;
import lombok.Setter;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDate;
@Getter
@Setter
public class BaseSearchRequest {
private int page = 0; // 페이지 번호 (0부터 시작)
private int size = 10; // 한 페이지당 출력 건수
private String keyword; // 공통 키워드 검색
private String searchType; // 검색 유형 (예: "전체", "제목", "작성자" 등)
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
private LocalDate startDate; // 등록일자 검색 시작
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
private LocalDate endDate; // 등록일자 검색 종료
private String sortField = "id"; // 정렬 기준 필드명
private String sortDirection = "DESC"; // 정렬 방향: ASC / DESC
}

@ -0,0 +1,19 @@
package kr.re.etri.security.jwt.payload.request;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class ProjectRequest {
private String prjCd;
private String prjNm;
private String prjDesc;
private String prjStartDt;
private String prjEndDt;
private String delYn;
private String regUserId;
private String regUserNm;
private String modUserId;
private String modUserNm;
}

@ -0,0 +1,13 @@
package kr.re.etri.security.jwt.repository;
import kr.re.etri.security.jwt.entity.ProjectEntity;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
public interface ProjectRepository extends JpaRepository<ProjectEntity, Long> {
boolean existsByPrjCd(String prjCd);
Page<ProjectEntity> findByPrjNmContainingIgnoreCase(String keyword, Pageable pageable);
}

@ -83,22 +83,38 @@ public class WebSecurityConfig { // extends WebSecurityConfigurerAdapter {
// http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
// }
// @Bean
// public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// http.csrf(AbstractHttpConfigurer::disable)
// .exceptionHandling(exception -> exception.authenticationEntryPoint(unauthorizedHandler))
// .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
// .authorizeHttpRequests(auth ->
// auth.requestMatchers("/api/auth/**").permitAll()
// .requestMatchers("/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html").permitAll()
// .requestMatchers("/api/test/**").permitAll()
// .anyRequest().authenticated()
// );
//
// http.authenticationProvider(authenticationProvider());
//
// http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
//
// return http.build();
// }
// 임시 설정
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf(AbstractHttpConfigurer::disable)
.exceptionHandling(exception -> exception.authenticationEntryPoint(unauthorizedHandler))
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth ->
auth.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html").permitAll()
.requestMatchers("/api/test/**").permitAll()
.anyRequest().authenticated()
);
http.authenticationProvider(authenticationProvider());
.exceptionHandling(exception -> exception.authenticationEntryPoint(unauthorizedHandler))
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth ->
auth.anyRequest().permitAll() // 모든 요청 허용
);
http.authenticationProvider(authenticationProvider());
http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}

@ -0,0 +1,70 @@
package kr.re.etri.security.jwt.service;
import kr.re.etri.security.jwt.entity.ProjectEntity;
import kr.re.etri.security.jwt.payload.request.BaseSearchRequest;
import kr.re.etri.security.jwt.payload.request.ProjectRequest;
import kr.re.etri.security.jwt.repository.ProjectRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Optional;
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class ProjectService {
private final ProjectRepository projectRepository;
public List<ProjectEntity> findAll() {
return projectRepository.findAll();
}
public Optional<ProjectEntity> findById(Long id) {
return projectRepository.findById(id);
}
public Page<ProjectEntity> search(BaseSearchRequest request) {
Pageable pageable = PageRequest.of(
request.getPage(),
request.getSize(),
Sort.by(Sort.Direction.fromString(request.getSortDirection()), request.getSortField())
);
if (request.getKeyword() != null && !request.getKeyword().isEmpty()) {
return projectRepository.findByPrjNmContainingIgnoreCase(request.getKeyword(), pageable);
} else {
return projectRepository.findAll(pageable);
}
}
@Transactional
public ProjectEntity create(ProjectEntity project) {
if (projectRepository.existsByPrjCd(project.getPrjCd())) {
throw new IllegalArgumentException("중복된 프로젝트 코드입니다.");
}
return projectRepository.save(project);
}
@Transactional
public Optional<ProjectEntity> update(Long id, ProjectRequest dto) {
return projectRepository.findById(id)
.map(project -> {
BeanUtils.copyProperties(dto, project);
return projectRepository.save(project);
});
}
@Transactional
public boolean delete(Long id) {
if (!projectRepository.existsById(id)) {
return false;
}
projectRepository.deleteById(id);
return true;
}
}
Loading…
Cancel
Save