계약관리 로직 수정

This commit is contained in:
2025-05-26 08:38:27 +00:00
parent 9006d108aa
commit eb523192a1
12 changed files with 265 additions and 26 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -2,6 +2,8 @@ package com.kospo.svcm.controller;
import com.kospo.svcm.config.exception.CustomErrorResponse;
import com.kospo.svcm.dto.req.ContSaveRequest;
import com.kospo.svcm.dto.req.ContUpdateRequest;
import com.kospo.svcm.dto.res.ContDetailResponse;
import com.kospo.svcm.dto.res.ContListResponse;
import com.kospo.svcm.dto.res.ContSaveResponse;
import com.kospo.svcm.dto.res.PrcsResponse;
@@ -82,7 +84,7 @@ public class ContController {
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @Content(mediaType = "application/json", schema = @Schema(oneOf =
{ContListResponse.class})
{ContDetailResponse.class})
)),
@ApiResponse(description = "Not found", responseCode = "404",
content = @Content(mediaType = "text/plain", schema = @Schema(oneOf =
@@ -99,7 +101,7 @@ public class ContController {
return ResponseEntity.ok(contService.findDetail(contNo));
}
@Operation(summary = "계약관리 저장", description = "계약관리, 첨부파일, 전자결재 통합저장")
@Operation(summary = "계약관리 저장", description = "계약관리, 첨부파일 통합저장")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @Content(mediaType = "application/json", schema = @Schema(oneOf =
@@ -118,6 +120,25 @@ public class ContController {
return ResponseEntity.ok(contService.save(contSaveRequest));
}
@Operation(summary = "계약관리 수정", description = "계약관리, 첨부파일 수정")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",
content = @Content(mediaType = "application/json", schema = @Schema(oneOf =
{ContSaveResponse.class}))),
@ApiResponse(description = "Not found", responseCode = "404",
content = @Content(mediaType = "text/plain", schema = @Schema(oneOf =
{String.class}))),
@ApiResponse(description = "Internal Error", responseCode = "500",
content = @Content(mediaType = "application/json", schema = @Schema(oneOf =
{CustomErrorResponse.class })))
})
@PutMapping("/cont")
public ResponseEntity update(
@RequestBody ContUpdateRequest contUpdateRequest
) {
return ResponseEntity.ok(contService.update(contUpdateRequest));
}
@Operation(summary = "계약관리 회수 처리", description = "결재진행중인건에 대한 회수 처리")
@ApiResponses({
@ApiResponse(description = "Success", responseCode = "200",

View File

@@ -27,10 +27,14 @@ public class ContSaveRequest implements Serializable {
String title;
@Schema(name = "compNm", description = "업체명")
String compNm;
@Schema(name = "signDt", description = "체결일")
String signDt;
@Schema(name = "contSdat", description = "계약시작일")
String contSdat;
@Schema(name = "contEdat", description = "계약종료일")
String contEdat;
@Schema(name = "contAmt", description = "계약금액")
int contAmt;
@Schema(name = "excYn", description = "가격조사 예외")
boolean excYn;
@Schema(name = "reason", description = "가격조사 예외사유")
@@ -47,6 +51,8 @@ public class ContSaveRequest implements Serializable {
public static class ContAttSaveRequest implements Serializable {
@Schema(name = "logiFnm", description = "논리파일명")
String logiFnm;
@Schema(name = "fileOrd", description = "파일순서")
int fileOrd;
@Schema(name = "data", description = "base64")
String data;
}

View File

@@ -23,17 +23,25 @@ public class ContUpdateRequest implements Serializable {
String contNo;
@Schema(name = "bizNo", description = "사업자번호")
String bizNo;
@Schema(name = "prcsNo", description = "가겨조사 번호")
String prcsNo;
@Schema(name = "title", description = "계약명")
String title;
@Schema(name = "compNm", description = "업체명")
String compNm;
@Schema(name = "signDt", description = "계약체결일")
@Schema(name = "signDt", description = "체결일")
String signDt;
@Schema(name = "contAmt", description = "계약금액")
Integer contAmt;
@Schema(name = "contSdat", description = "계약시작일")
String contSdat;
@Schema(name = "contEdat", description = "계약종료일")
String contEdat;
List<ContAttUpdateResponse> contAtts;
@Schema(name = "amt", description = "계약금액")
int contAmt;
@Schema(name = "excYn", description = "가격조사 예외")
boolean excYn;
@Schema(name = "reason", description = "가격조사 예외사유")
String reason;
List<ContAttUpdateRequest> contAtts;
@Getter
@Setter
@@ -41,8 +49,8 @@ public class ContUpdateRequest implements Serializable {
@AllArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
@Schema(name = "ContAttUpdateResponse", description = "계약 문서")
public static class ContAttUpdateResponse implements Serializable {
@Schema(name = "ContAttUpdateRequest", description = "계약 문서")
public static class ContAttUpdateRequest implements Serializable {
@Schema(name = "contNo", description = "계약번호")
String contNo;
@Schema(name = "fileOrd", description = "파일순서")

View File

@@ -0,0 +1,80 @@
package com.kospo.svcm.dto.res;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.kospo.svcm.model.Cont;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.io.Serializable;
import java.util.List;
import java.util.stream.Collectors;
/**
* DTO for {@link Cont}
*/
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
@Schema(name = "ContDetailResponse", description = "계약관리 상세")
public class ContDetailResponse implements Serializable {
@Schema(name = "contNo", description = "계약번호")
String contNo;
@Schema(name = "cateCd", description = "분야코드")
String cateCd;
@Schema(name = "cateNm", description = "분야")
String cateNm;
@Schema(name = "bizNo", description = "사업자번호")
String bizNo;
@Schema(name = "title", description = "계약명")
String title;
@Schema(name = "compNm", description = "업체명")
String compNm;
@Schema(name = "signDt", description = "계약체결일")
String signDt;
@Schema(name = "contAmt", description = "계약금액")
Integer contAmt;
@Schema(name = "contSdat", description = "계약시작일")
String contSdat;
@Schema(name = "contEdat", description = "계약종료일")
String contEdat;
@Schema(name = "contStatCd", description = "계약상태코드")
String contStatCd;
@Schema(name = "contStat", description = "계약상태")
String contStat;
@Schema(name = "regSabun", description = "등록사번")
String regSabun;
@Schema(name = "regNm", description = "등록자")
String regNm;
@Schema(name = "regDt", description = "등록일시")
String regDt;
@Schema(name = "docUrl", description = "전자문서url")
String docUrl;
@Schema(name = "excYn", description = "가격조사 예외")
boolean excYn;
@Schema(name = "reason", description = "가격조사 예외사유")
String reason;
List<ContAttResponse> contAtts;
public static ContDetailResponse from(Cont cont) {
return ContDetailResponse.builder()
.contNo(cont.getContNo())
.bizNo(cont.getBizNo())
.title(cont.getTitle())
.compNm(cont.getCompNm())
.signDt(cont.getSignDt())
.contAmt(cont.getContAmt())
.contSdat(cont.getContSdat())
.contEdat(cont.getContEdat())
.contStatCd(cont.getContStatCd())
.contStat(cont.getContStat())
.regSabun(cont.getRegSabun())
.regNm(cont.getRegNm())
.regDt(cont.getRegDt())
.contAtts(cont.getContAtts() == null ? null : cont.getContAtts().stream().map(ContAttResponse::from).collect(Collectors.toList()))
.build();
}
}

View File

@@ -17,6 +17,10 @@ public class ContListResponse {
String contNo;
@Schema(name = "title", description = "제목")
String title;
@Schema(name = "cateCd", description = "분야코드")
String cateCd;
@Schema(name = "cateNm", description = "분야")
String cateNm;
@Schema(name = "compNm", description = "업체명")
String compNm;
@Schema(name = "signDt", description = "계약체결일")
@@ -37,6 +41,8 @@ public class ContListResponse {
public static ContListResponse iFrom(ContRepository.IContResponse cont) {
return ContListResponse.builder()
.contNo(cont.getContNo())
.cateCd(cont.getCateCd())
.cateNm(cont.getCateNm())
.compNm(cont.getCompNm())
.title(cont.getTitle())
.signDt(cont.getSignDt())

View File

@@ -15,6 +15,8 @@ public interface ContRepository extends JpaRepository<Cont, String> {
interface IContResponse {
String getContNo();
String getCateCd();
String getCateNm();
String getCompNm();
String getTitle();
String getSignDt();
@@ -26,8 +28,10 @@ public interface ContRepository extends JpaRepository<Cont, String> {
String getRegSabun();
}
@Query(value = "select c.contNo as contNo, " +
" p.cateCd as cateCd, " +
" p.cateNm as cateNm, " +
" c.compNm as compNm, " +
" p.title as title, " +
" c.title as title, " +
" c.signDt as signDt, " +
" c.contAmt as contAmt, " +
" c.contStatCd as contStatCd, " +

View File

@@ -11,7 +11,7 @@ public interface PrcsBizRepository extends JpaRepository<PrcsBiz, PrcsBizId> {
"inner join PrcsBiz pb on p.prcsNo = pb.id.prcsNo \n" +
"inner join ApprMst am on am.prcsNo = p.prcsNo \n" +
"and pb.id.bizNo = :bizNo " +
"and p.stCd = '0100' and pb.estStatCd = '0000' and am.apprStatCd = '0200' ")
"and p.stCd = '0200' and pb.estStatCd = '0000' and am.apprStatCd = '0200' ")
int countReqByBizNo(String bizNo);
/*입찰 상태 변경*/

View File

@@ -1,6 +1,8 @@
package com.kospo.svcm.service;
import com.kospo.svcm.dto.req.ContSaveRequest;
import com.kospo.svcm.dto.req.ContUpdateRequest;
import com.kospo.svcm.dto.res.ContDetailResponse;
import com.kospo.svcm.dto.res.ContListResponse;
import com.kospo.svcm.dto.res.ContSaveResponse;
import jakarta.transaction.Transactional;
@@ -12,10 +14,13 @@ public interface ContService {
List<ContListResponse> findPage(String sabun, String contStatCd, String signSdt, String signEdt, Pageable pageable);
@Transactional
ContSaveResponse findDetail(String contNo);
ContDetailResponse findDetail(String contNo);
ContSaveResponse save(ContSaveRequest contSaveRequest);
@org.springframework.transaction.annotation.Transactional
ContSaveResponse update(ContUpdateRequest contUpdateRequest);
@org.springframework.transaction.annotation.Transactional
ContSaveResponse retrieve(String contNo);
}

View File

@@ -2,8 +2,11 @@ package com.kospo.svcm.service.impl;
import com.kospo.svcm.config.exception.ErrorCode;
import com.kospo.svcm.config.utils.CommonUtils;
import com.kospo.svcm.config.utils.FileUtils;
import com.kospo.svcm.config.utils.SequenceUtils;
import com.kospo.svcm.dto.req.ContSaveRequest;
import com.kospo.svcm.dto.req.ContUpdateRequest;
import com.kospo.svcm.dto.res.ContDetailResponse;
import com.kospo.svcm.dto.res.ContListResponse;
import com.kospo.svcm.dto.res.ContSaveResponse;
import com.kospo.svcm.exception.CustomException;
@@ -32,6 +35,7 @@ public class ContServiceImpl implements ContService {
private final EstimateRepository estimateRepository;
private final Zwf0011tRepository zwf0011tRepository;
private final SlipRepository slipRepository;
private final FileUtils fileUtils;
@Value("${server.attach}")
private String filePath;
private final ContRepository contRepository;
@@ -48,14 +52,21 @@ public class ContServiceImpl implements ContService {
@Transactional
@Override
public ContSaveResponse findDetail(String contNo) {
ContSaveResponse contSaveResponse = ContSaveResponse.from(contRepository.findById(contNo).get());
ContAppr contAppr = contApprRepository.findByIdContNoOrderByIdTransactionKeyDesc(contNo)
.stream().findFirst().get();
if(contAppr != null) contSaveResponse.setDocUrl(contAppr.getSignDoc().getDocUrl());
public ContDetailResponse findDetail(String contNo) {
Cont cont = contRepository.findById(contNo).get();
Prcs prcs = prcsRepository.findById(cont.getPrcsNo()).get();
ContDetailResponse contDetailResponse = ContDetailResponse.from(cont);
Optional<ContAppr> optionalContAppr = contApprRepository.findByIdContNoOrderByIdTransactionKeyDesc(contNo)
.stream().findFirst();
if(optionalContAppr.isPresent()) {
ContAppr contAppr = optionalContAppr.get();
contDetailResponse.setDocUrl(contAppr.getSignDoc().getDocUrl());
}
contDetailResponse.setCateCd(prcs.getCateCd());
contDetailResponse.setCateNm(prcs.getCateNm());
return contSaveResponse;
return contDetailResponse;
}
@Transactional
@@ -81,8 +92,6 @@ public class ContServiceImpl implements ContService {
String contStatCd = "0000";
AtomicInteger fileOrd = new AtomicInteger(0);
List<Estimate> estimates = estimateRepository.findByBizNoAndPrcsNo(contSaveRequest.getBizNo(), contSaveRequest.getPrcsNo());
Integer sum = estimates.stream().map(estimate -> estimate.getAmt()).reduce(0, Integer::sum);
cont = contRepository.save(Cont.builder()
.contNo(contNo)
@@ -90,8 +99,8 @@ public class ContServiceImpl implements ContService {
.bizNo(contSaveRequest.getBizNo())
.title(contSaveRequest.getTitle())
.compNm(contSaveRequest.getCompNm())
.signDt(CommonUtils.dateFormat("yyyy-MM-dd"))
.contAmt(sum)
.signDt(contSaveRequest.getSignDt())
.contAmt(contSaveRequest.getContAmt())
.contSdat(contSaveRequest.getContSdat())
.contEdat(contSaveRequest.getContEdat())
.contStatCd(contStatCd)
@@ -109,10 +118,11 @@ public class ContServiceImpl implements ContService {
if(contSaveRequest.getContAtts() != null && contSaveRequest.getContAtts().size() > 0){
cont.setContAtts(contAttRepository.saveAll(contSaveRequest.getContAtts().stream().map(contAttSaveRequest -> {
String pNm = CommonUtils.dateFormat("yyyyMMddHHmmssSSS");
fileUtils.fileUpload(filePath + pNm, contAttSaveRequest.getData());
return ContAtt.builder()
.id(ContAttId.builder()
.contNo(contNo)
.fileOrd(fileOrd.incrementAndGet())
.fileOrd(contAttSaveRequest.getFileOrd())
.build()
)
.logiFnm(contAttSaveRequest.getLogiFnm())
@@ -134,6 +144,80 @@ public class ContServiceImpl implements ContService {
}
}
@Transactional
@Override
public ContSaveResponse update(ContUpdateRequest contUpdateRequest) {
Optional<Cont> optionalCont = contRepository.findById(contUpdateRequest.getContNo());
if(optionalCont.isPresent()) {
Cont cont = optionalCont.get();
User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
Prcs prcs = prcsRepository.findByPrcsNoAndRegSabun(contUpdateRequest.getPrcsNo(), user.getSabun());
if(prcs != null) {
if(!prcs.getSvyYn()) throw new CustomException(ErrorCode.No_SVY_NOT_EXECUTE);
} else {
if(!contUpdateRequest.isExcYn() || StringUtil.isBlank(contUpdateRequest.getReason())) throw new CustomMessageException(CustomMessageException.CusMessage.builder()
.code("999999")
.message("가격조사를 안했을 시 예외 사유는 필수 입니다.")
.build());
}
String contNo = cont.getContNo();
cont.setTitle(contUpdateRequest.getTitle());
cont.setCompNm(contUpdateRequest.getCompNm());
cont.setSignDt(contUpdateRequest.getSignDt());
cont.setContAmt(contUpdateRequest.getContAmt());
cont.setContSdat(contUpdateRequest.getContSdat());
cont.setContEdat(contUpdateRequest.getContEdat());
cont.setExcYn(contUpdateRequest.isExcYn());
cont.setReason(contUpdateRequest.getReason());
cont = contRepository.save(cont);
if(contUpdateRequest.getContAtts() != null && contUpdateRequest.getContAtts().size() > 0){
cont.setContAtts(
contAttRepository.saveAll(contUpdateRequest.getContAtts().stream().filter(contAttUpdateRequest -> contAttUpdateRequest.getData() != null).toList()
.stream().map(contAttUpdateRequest -> {
Optional<ContAtt> optionalContAtt = contAttRepository.findById(ContAttId.builder()
.contNo(contUpdateRequest.getContNo())
.fileOrd(contAttUpdateRequest.getFileOrd())
.build());
if(optionalContAtt.isPresent()) {
ContAtt att = optionalContAtt.get();
if(fileUtils.fileDelete(att.getPath())) {
contAttRepository.delete(att);
}
}
String pNm = CommonUtils.dateFormat("yyyyMMddHHmmssSSS");
fileUtils.fileUpload(filePath + pNm, contAttUpdateRequest.getData());
return ContAtt.builder()
.id(ContAttId.builder()
.contNo(contNo)
.fileOrd(contAttUpdateRequest.getFileOrd())
.build()
)
.logiFnm(contAttUpdateRequest.getLogiFnm())
.physFnm(pNm)
.size(contAttUpdateRequest.getData().length())
.path(filePath + pNm)
.build();
}).toList())
);
}
/* 전체 업체 유찰 처리 */
prcsBizRepository.updatePrcsBizByEstStatCd(contUpdateRequest.getPrcsNo(), "0400");
/* 특정 업체 낙찰 처리 */
prcsBizRepository.updatePrcsBizByEstStatCd(contUpdateRequest.getPrcsNo(), contUpdateRequest.getBizNo(), "0300");
return ContSaveResponse.from(cont);
} else {
throw new CustomException(ErrorCode.UPD_ERR);
}
}
@Transactional
@Override
public ContSaveResponse retrieve(String contNo) {

View File

@@ -409,9 +409,9 @@ public class PrcsServiceImpl implements PrcsService {
String pnm = CommonUtils.dateFormat("yyyyMMddHHmmssSSS");
if (fileUtils.fileUpload(filePath + pnm, prcsAttRequest.getData())) {
try {
PrcsAtt.builder()
prcsAttList.add(prcsAttRepository.save(PrcsAtt.builder()
.id(PrcsAttId.builder()
.prcsNo(prcsAttRequest.getPrcsNo())
.prcsNo(prcsRequest.getPrcsNo())
.fileOrd(idx)
.build()
)
@@ -419,7 +419,7 @@ public class PrcsServiceImpl implements PrcsService {
.physFnm(pnm)
.size((int) Files.size(Path.of(filePath + pnm)))
.path(filePath + pnm)
.build();
.build()));
} catch (IOException e) {
throw new RuntimeException(e);
}