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 kr.itn.itnhub.dashboard.DashboardOrgRow;
import kr.itn.itnhub.dashboard.DashboardService;
import kr.itn.itnhub.org.OrgNotFoundException;
import kr.itn.itnhub.org.OrganizationMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 사업관리 화면. 3단계 법률검토로 진행할 기관 현황을 한 곳에 모아 보여주고, 기관마다
* "신청 확인 연락" 이력과 최종 보고서를 관리한다(요청자 요구: 별도 메뉴로 구축 + 연락 부분 이력관리
* + 기관별 최종 보고서 업로드).
*
* <p>기관 현황 숫자는 대시보드와 같은 집계를 그대로 쓴다 - 두 화면이 다른 숫자를 보여주면
* 어느 쪽이 맞는지 확인할 방법이 없기 때문이다.</p>
*/
@Service
public class ProjectService {
private final DashboardService dashboardService;
private final ProjectMapper mapper;
private final OrganizationMapper orgMapper;
public ProjectService(DashboardService dashboardService, ProjectMapper mapper,
OrganizationMapper orgMapper) {
this.dashboardService = dashboardService;
this.mapper = mapper;
this.orgMapper = orgMapper;
}
public List<ProjectRow> rows() {
Map<Long, ProjectMapper.ProjectSideInfo> side = new HashMap<>();
for (ProjectMapper.ProjectSideInfo info : mapper.findSideInfo()) {
side.put(info.orgId(), info);
}
List<DashboardOrgRow> orgs = dashboardService.dashboard().orgs();
List<ProjectRow> rows = new ArrayList<>(orgs.size());
for (DashboardOrgRow org : orgs) {
ProjectMapper.ProjectSideInfo info = side.get(org.id());
rows.add(new ProjectRow(org,
info == null ? null : info.lastContactedOn(),
info == null ? 0 : info.contactCount(),
info == null ? 0 : info.reportCount()));
}
return rows;
}
public List<ContactLog> logs(Long orgId) {
requireOrg(orgId);
return mapper.findLogsByOrg(orgId);
}
@Transactional
public List<ContactLog> addLog(Long orgId, ContactLogRequest request, String author) {
requireOrg(orgId);
mapper.insertLog(orgId, request.contactedOn(), request.method(), request.summary(), author);
return mapper.findLogsByOrg(orgId);
}
@Transactional
public List<ContactLog> updateLog(Long orgId, Long logId, ContactLogRequest request) {
requireOrg(orgId);
if (mapper.updateLog(orgId, logId, request.contactedOn(), request.method(),
request.summary()) == 0) {
throw new OrgNotFoundException("연락 이력을 찾을 수 없습니다: " + logId);
}
return mapper.findLogsByOrg(orgId);
}
@Transactional
public void deleteLog(Long orgId, Long logId) {
requireOrg(orgId);
if (mapper.deleteLog(orgId, logId) == 0) {
throw new OrgNotFoundException("연락 이력을 찾을 수 없습니다: " + logId);
}
}
public List<OrgReport> reports(Long orgId) {
requireOrg(orgId);
return mapper.findReportsByOrg(orgId);
}
/** 같은 기관에 여러 번 올릴 수 있다(개정판). 최신순으로 목록에 쌓인다. */
@Transactional
public List<OrgReport> addReport(Long orgId, String fileName, String contentType,
byte[] content, String uploadedBy) {
requireOrg(orgId);
if (content == null || content.length == 0) {
throw new IllegalArgumentException("빈 파일은 올릴 수 없습니다.");
}
mapper.insertReport(orgId, fileName, contentType, content.length, content, uploadedBy);
return mapper.findReportsByOrg(orgId);
}
/**
* 올려둔 보고서를 새 파일로 바꾼다(요구사항 [25]). 목록에 새 줄이 생기지 않고 그 자리만
* 바뀐다 - 개정판으로 남기고 싶으면 새로 올리면 된다.
*/
@Transactional
public List<OrgReport> replaceReport(Long orgId, Long reportId, String fileName,
String contentType, byte[] content, String uploadedBy) {
requireOrg(orgId);
if (content == null || content.length == 0) {
throw new IllegalArgumentException("빈 파일은 올릴 수 없습니다.");
}
int updated = mapper.updateReport(orgId, reportId, fileName, contentType, content.length,
content, uploadedBy);
if (updated == 0) {
throw new OrgNotFoundException("보고서를 찾을 수 없습니다: " + reportId);
}
return mapper.findReportsByOrg(orgId);
}
public ProjectMapper.ReportContent reportContent(Long orgId, Long reportId) {
requireOrg(orgId);
ProjectMapper.ReportContent content = mapper.findReportContent(orgId, reportId);
if (content == null) {
throw new OrgNotFoundException("보고서를 찾을 수 없습니다: " + reportId);
}
return content;
}
@Transactional
public void deleteReport(Long orgId, Long reportId) {
requireOrg(orgId);
if (mapper.deleteReport(orgId, reportId) == 0) {
throw new OrgNotFoundException("보고서를 찾을 수 없습니다: " + reportId);
}
}
private void requireOrg(Long orgId) {
if (orgMapper.findById(orgId) == null) {
throw new OrgNotFoundException("기관을 찾을 수 없습니다: " + orgId);
}
}
}