File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
package kr.itn.itnhub.project;
import jakarta.validation.Valid;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.Principal;
import java.util.List;
import java.util.Map;
/** 사업관리 화면이 쓰는 엔드포인트. 기관 현황 목록 + 연락 이력 + 최종 보고서. */
@RestController
public class ProjectController {
private final ProjectService projectService;
public ProjectController(ProjectService projectService) {
this.projectService = projectService;
}
@GetMapping("/api/projects")
public List<ProjectRow> rows() {
return projectService.rows();
}
@GetMapping("/api/orgs/{id}/contact-logs")
public List<ContactLog> logs(@PathVariable("id") Long orgId) {
return projectService.logs(orgId);
}
/** 작성자는 업무메모와 마찬가지로 로그인 사용자를 서버가 기록한다. */
@PostMapping("/api/orgs/{id}/contact-logs")
public List<ContactLog> addLog(@PathVariable("id") Long orgId,
@Valid @RequestBody ContactLogRequest request,
Principal principal) {
return projectService.addLog(orgId, request, principal.getName());
}
@PutMapping("/api/orgs/{id}/contact-logs/{logId}")
public List<ContactLog> updateLog(@PathVariable("id") Long orgId, @PathVariable Long logId,
@Valid @RequestBody ContactLogRequest request) {
return projectService.updateLog(orgId, logId, request);
}
@ResponseStatus(HttpStatus.NO_CONTENT)
@DeleteMapping("/api/orgs/{id}/contact-logs/{logId}")
public void deleteLog(@PathVariable("id") Long orgId, @PathVariable Long logId) {
projectService.deleteLog(orgId, logId);
}
@GetMapping("/api/orgs/{id}/reports")
public List<OrgReport> reports(@PathVariable("id") Long orgId) {
return projectService.reports(orgId);
}
@PostMapping("/api/orgs/{id}/reports")
public List<OrgReport> addReport(@PathVariable("id") Long orgId,
@RequestPart("file") MultipartFile file,
Principal principal) throws IOException {
String name = file.getOriginalFilename() == null ? "report" : file.getOriginalFilename();
return projectService.addReport(orgId, name, file.getContentType(), file.getBytes(),
principal.getName());
}
/** 한글 파일명이 깨지지 않게 ChannelFeedController.download와 같은 RFC 5987 인코딩을 쓴다. */
@GetMapping("/api/orgs/{id}/reports/{reportId}")
public ResponseEntity<byte[]> downloadReport(@PathVariable("id") Long orgId,
@PathVariable Long reportId) {
ProjectMapper.ReportContent report = projectService.reportContent(orgId, reportId);
String encodedName = URLEncoder.encode(report.fileName(), StandardCharsets.UTF_8)
.replace("+", "%20");
MediaType type = report.contentType() == null || report.contentType().isBlank()
? MediaType.APPLICATION_OCTET_STREAM
: MediaType.parseMediaType(report.contentType());
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + encodedName)
.contentType(type)
.body(report.content());
}
@ResponseStatus(HttpStatus.NO_CONTENT)
@DeleteMapping("/api/orgs/{id}/reports/{reportId}")
public void deleteReport(@PathVariable("id") Long orgId, @PathVariable Long reportId) {
projectService.deleteReport(orgId, reportId);
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(IllegalArgumentException.class)
public Map<String, String> handleBadRequest(IllegalArgumentException e) {
return Map.of("message", e.getMessage());
}
}