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.OrganizationMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;
import java.io.InputStream;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Service
public class ReviewImportService {
private final ReviewParser parser;
private final ReviewItemMapper mapper;
private final OrganizationMapper orgMapper;
private final kr.itn.itnhub.stage.StageService stageService;
private final kr.itn.itnhub.code.CodeService codeService;
private final TransactionTemplate transactionTemplate;
public ReviewImportService(ReviewParser parser, ReviewItemMapper mapper, OrganizationMapper orgMapper,
kr.itn.itnhub.stage.StageService stageService,
kr.itn.itnhub.code.CodeService codeService,
PlatformTransactionManager transactionManager) {
this.parser = parser;
this.mapper = mapper;
this.orgMapper = orgMapper;
this.stageService = stageService;
this.codeService = codeService;
this.transactionTemplate = new TransactionTemplate(transactionManager);
}
/** 공공누리 유형의 옛 표기를 표준 표기로 맞춘다(제4유형 → 4유형). */
private String canonicalKogl(String value) {
return codeService.canonical(kr.itn.itnhub.code.Codes.KOGL_TYPE, value);
}
/**
* 엑셀 파싱은 DB와 무관하므로 트랜잭션 밖에서 수행한다(SeedService와 동일한 이유).
*/
public ReviewImportReport importFile(Long orgId, InputStream xlsx) {
if (orgMapper.findById(orgId) == null) {
throw new OrgNotFoundException("기관을 찾을 수 없습니다: " + orgId);
}
List<ReviewRow> rows = parser.parse(xlsx);
ReviewImportReport report = transactionTemplate.execute(status -> importRows(orgId, rows));
// 요구사항 [18]: 권리확인 자료가 올라오면 ⑤법률검토(권리확인)로 저절로 넘어간다.
// 이미 그보다 앞서 있으면 아무 일도 하지 않는다.
if (report != null && report.total() > 0) {
stageService.autoAdvance(orgId, kr.itn.itnhub.stage.AutoStage.REVIEW_STARTED,
kr.itn.itnhub.stage.AutoStage.REASON_REVIEW_STARTED);
}
return report;
}
private ReviewImportReport importRows(Long orgId, List<ReviewRow> rows) {
// 이미 DB에 있는 순번 + 이번 파일에서 먼저 처리된 순번을 모두 "이미 존재함"으로 취급한다
// (SeedService.seedRows와 동일한 관례 - 같은 순번이 파일에 중복돼 있어도 두 번째는 갱신으로 집계).
Set<Integer> seen = new HashSet<>(mapper.findSeqsByOrg(orgId));
int created = 0;
int updated = 0;
for (ReviewRow row : rows) {
if (seen.add(row.seq())) {
created++;
} else {
updated++;
}
mapper.upsertFromFile(toReviewItem(orgId, row));
}
return new ReviewImportReport(created, updated, rows.size());
}
private ReviewItem toReviewItem(Long orgId, ReviewRow row) {
ReviewItem item = new ReviewItem();
item.setOrgId(orgId);
item.setSeq(row.seq());
item.setSiteName(row.siteName());
item.setCategory(row.category());
item.setBoardPath(row.boardPath());
item.setBoardName(row.boardName());
item.setPostTitle(row.postTitle());
item.setUrl(row.url());
item.setPostRegistered(row.postRegistered());
item.setProducedDate(row.producedDate());
item.setPublishedDate(row.publishedDate());
item.setHasAttachment(row.hasAttachment());
item.setKoglAttached(row.koglAttached());
// 옛 표기(제4유형)로 적혀 온 값은 표준 표기(4유형)로 맞춰 넣는다.
item.setKoglType(canonicalKogl(row.koglType()));
item.setAiType(row.aiType());
item.setSurveyorNote(row.surveyorNote());
item.setOpenable(row.openable());
item.setReviewMajor(row.reviewMajor());
item.setReviewMinor(row.reviewMinor());
item.setReviewResult(row.reviewResult());
item.setJudgedKoglType(canonicalKogl(row.judgedKoglType()));
item.setJudgedAiType(row.judgedAiType());
item.setOpinion(row.opinion());
item.setLawyerNote(row.lawyerNote());
item.setNeedsProcessing(row.needsProcessing());
return item;
}
}