계약관리 로직 수정

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

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);
}