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.review;
import kr.itn.itnhub.org.OrgNotFoundException;
import kr.itn.itnhub.org.Organization;
import kr.itn.itnhub.org.OrganizationMapper;
import kr.itn.itnhub.seed.SeedParseException;
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.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.RequestParam;
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.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
/** 기관관리 상세의 권리확인 탭이 부르는 엔드포인트. */
@RestController
public class ReviewController {
private final ReviewService reviewService;
private final ReviewImportService importService;
private final OrganizationMapper orgMapper;
public ReviewController(ReviewService reviewService, ReviewImportService importService,
OrganizationMapper orgMapper) {
this.reviewService = reviewService;
this.importService = importService;
this.orgMapper = orgMapper;
}
@PostMapping("/api/orgs/{id}/review/import")
public ReviewImportReport upload(@PathVariable("id") Long orgId, @RequestParam("file") MultipartFile file) {
if (file.isEmpty()) {
throw new SeedParseException("업로드된 파일이 비어 있습니다.");
}
String filename = file.getOriginalFilename();
if (filename == null || !hasAllowedExtension(filename)) {
throw new SeedParseException("엑셀 파일(.xlsx 또는 .xlsm)만 업로드할 수 있습니다.");
}
try (InputStream in = file.getInputStream()) {
return importService.importFile(orgId, in);
} catch (IOException e) {
throw new SeedParseException("엑셀 파일을 읽지 못했습니다.", e);
}
}
@GetMapping("/api/orgs/{id}/review")
public ReviewPage list(@PathVariable("id") Long orgId,
@RequestParam(required = false) String keyword,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "30") int size) {
return reviewService.list(orgId, keyword, page, size);
}
@GetMapping("/api/orgs/{id}/review/{itemId}")
public ReviewItem get(@PathVariable("id") Long orgId, @PathVariable Long itemId) {
return reviewService.get(orgId, itemId);
}
@PutMapping("/api/orgs/{id}/review/{itemId}")
public ReviewItem update(@PathVariable("id") Long orgId, @PathVariable Long itemId,
@RequestBody JudgmentRequest request) {
return reviewService.updateJudgment(orgId, itemId, request);
}
@ResponseStatus(HttpStatus.NO_CONTENT)
@DeleteMapping("/api/orgs/{id}/review/{itemId}")
public void delete(@PathVariable("id") Long orgId, @PathVariable Long itemId) {
reviewService.delete(orgId, itemId);
}
/** 한글 파일명이라 ChannelFeedController.download와 동일하게 RFC 5987 인코딩을 쓴다. */
@GetMapping("/api/orgs/{id}/review/download")
public ResponseEntity<byte[]> download(@PathVariable("id") Long orgId) {
Organization org = orgMapper.findById(orgId);
if (org == null) {
throw new OrgNotFoundException("기관을 찾을 수 없습니다: " + orgId);
}
byte[] content = reviewService.downloadWorkbook(orgId);
String filename = "권리확인_" + org.getOrgName() + ".xlsx";
String encodedName = URLEncoder.encode(filename, StandardCharsets.UTF_8).replace("+", "%20");
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + encodedName)
.contentType(MediaType.parseMediaType(
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"))
.body(content);
}
private static boolean hasAllowedExtension(String filename) {
String lower = filename.toLowerCase();
return lower.endsWith(".xlsx") || lower.endsWith(".xlsm");
}
}