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.process;
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 ProcessController {
private final ProcessService processService;
private final ProcessImportService importService;
private final OrganizationMapper orgMapper;
public ProcessController(ProcessService processService, ProcessImportService importService,
OrganizationMapper orgMapper) {
this.processService = processService;
this.importService = importService;
this.orgMapper = orgMapper;
}
@PostMapping("/api/orgs/{id}/process/import")
public ProcessImportReport 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);
}
}
/** keyword는 통합검색, site/board/title은 열별 조건(서로 AND). status는 처리상태 필터다. */
@GetMapping("/api/orgs/{id}/process")
public ProcessPage list(@PathVariable("id") Long orgId,
@RequestParam(required = false) String keyword,
@RequestParam(required = false) String site,
@RequestParam(required = false) String board,
@RequestParam(required = false) String title,
@RequestParam(required = false) String status,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "30") int size) {
return processService.list(orgId, keyword, site, board, title, status, page, size);
}
/** 목록에서 체크한 건들에 같은 값을 한 번에 반영한다. */
@PutMapping("/api/orgs/{id}/process/bulk")
public java.util.Map<String, Integer> updateBulk(@PathVariable("id") Long orgId,
@RequestBody BulkProcessingRequest request) {
return java.util.Map.of("updated", processService.updateBulk(orgId, request));
}
/** 목록에서 체크한 건들을 지운다. */
@PostMapping("/api/orgs/{id}/process/bulk-delete")
public java.util.Map<String, Integer> deleteBulk(@PathVariable("id") Long orgId,
@RequestBody java.util.List<Long> ids) {
return java.util.Map.of("deleted", processService.deleteBulk(orgId, ids));
}
@GetMapping("/api/orgs/{id}/process/{itemId}")
public ProcessItem get(@PathVariable("id") Long orgId, @PathVariable Long itemId) {
return processService.get(orgId, itemId);
}
@PutMapping("/api/orgs/{id}/process/{itemId}")
public ProcessItem update(@PathVariable("id") Long orgId, @PathVariable Long itemId,
@RequestBody ProcessingRequest request) {
return processService.updateProcessing(orgId, itemId, request);
}
@ResponseStatus(HttpStatus.NO_CONTENT)
@DeleteMapping("/api/orgs/{id}/process/{itemId}")
public void delete(@PathVariable("id") Long orgId, @PathVariable Long itemId) {
processService.delete(orgId, itemId);
}
/** 한글 파일명이라 ReviewController.download와 동일하게 RFC 5987 인코딩을 쓴다. */
@GetMapping("/api/orgs/{id}/process/download")
public ResponseEntity<byte[]> download(@PathVariable("id") Long orgId) {
Organization org = orgMapper.findById(orgId);
if (org == null) {
throw new OrgNotFoundException("기관을 찾을 수 없습니다: " + orgId);
}
byte[] content = processService.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");
}
}