11
This commit is contained in:
@@ -4,6 +4,7 @@ import com.nbport.zgwl.common.PageResult;
|
||||
import com.nbport.zgwl.common.R;
|
||||
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchApproveDto;
|
||||
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchArchiveDto;
|
||||
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchCollectSaveDto;
|
||||
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchDto;
|
||||
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchLawCallbackDto;
|
||||
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchLawCallbackRequestDto;
|
||||
@@ -299,6 +300,32 @@ public class ContractLaunchController {
|
||||
return R.success(contractLaunchService.mockCollect(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存采集信息(用印信息 + 签订信息)。
|
||||
*
|
||||
* 签署完成后,在「合同采集」阶段(pending_collect),
|
||||
* 用户通过采集弹窗补充/修改用印信息和签订信息后保存到合同记录。
|
||||
* 与 mock-collect 分开,允许用户在触发采集前先保存草稿。
|
||||
*
|
||||
* 请求体 ContractLaunchCollectSaveDto 字段:
|
||||
* sealIsSeal - 是否用印
|
||||
* sealApproveSame - 用印和审批文本是否一致
|
||||
* sealQuantity - 用印数量
|
||||
* sealDate - 用印时间
|
||||
* signDate - 签订日期
|
||||
* activeDate - 合同生效日期
|
||||
* executorAccount - 合同履行执行人
|
||||
* signedFileName - 签署文件名
|
||||
* signedFilePath - 签署文件路径
|
||||
* signedFileType - 签署文件类型
|
||||
* signedFileSize - 签署文件大小
|
||||
*/
|
||||
@PostMapping("/{id}/collect/save")
|
||||
public R<ContractLaunchDto> saveCollectInfo(@PathVariable("id") Long id,
|
||||
@RequestBody ContractLaunchCollectSaveDto collectDto) {
|
||||
return R.success(contractLaunchService.saveCollectInfo(id, collectDto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 合同归档。
|
||||
*
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.nbport.zgwl.contractlaunch.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 合同采集信息保存参数。
|
||||
*
|
||||
* 签署完成后,在「合同采集」阶段(pending_collect → pending_archive),
|
||||
* 用户通过采集弹窗补充用印信息、签订信息后保存到合同记录,
|
||||
* 再调用 dataCollectionPushService.collectContract 推送到法务系统。
|
||||
*/
|
||||
@Data
|
||||
public class ContractLaunchCollectSaveDto implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 是否用印(1-是,0-否) */
|
||||
private String sealIsSeal;
|
||||
|
||||
/** 用印和审批文本是否一致(1-是,0-否) */
|
||||
private String sealApproveSame;
|
||||
|
||||
/** 用印数量 */
|
||||
private Integer sealQuantity;
|
||||
|
||||
/** 用印时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private LocalDateTime sealDate;
|
||||
|
||||
/** 签订日期 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private LocalDateTime signDate;
|
||||
|
||||
/** 合同生效日期 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private LocalDateTime activeDate;
|
||||
|
||||
/** 合同履行执行人(账号) */
|
||||
private String executorAccount;
|
||||
|
||||
/** 签署文件名 */
|
||||
private String signedFileName;
|
||||
|
||||
/** 签署文件路径 */
|
||||
private String signedFilePath;
|
||||
|
||||
/** 签署文件类型 */
|
||||
private String signedFileType;
|
||||
|
||||
/** 签署文件大小 */
|
||||
private Long signedFileSize;
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package com.nbport.zgwl.contractlaunch.service;
|
||||
import com.nbport.zgwl.common.PageResult;
|
||||
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchApproveDto;
|
||||
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchArchiveDto;
|
||||
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchCollectSaveDto;
|
||||
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchDto;
|
||||
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchLawCallbackDto;
|
||||
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchLawCallbackSampleDto;
|
||||
@@ -50,6 +51,9 @@ public interface ContractLaunchService {
|
||||
/** 签署完成回调(回写签署文件路径,状态变更为待采集) */
|
||||
ContractLaunchDto markSealCompleted(Long id, ContractLaunchSealDto sealDto);
|
||||
|
||||
/** 保存采集信息(用印+签订信息),用于采集弹窗保存草稿 */
|
||||
ContractLaunchDto saveCollectInfo(Long id, ContractLaunchCollectSaveDto collectDto);
|
||||
|
||||
/** 模拟合同采集(调用数据采集 collectContract 接口,TODO:替换为真实调用) */
|
||||
ContractLaunchDto mockCollect(Long id);
|
||||
|
||||
|
||||
+110
-23
@@ -11,6 +11,7 @@ import com.nbport.zgwl.contractlaunch.dto.ContractLaunchApproveDto;
|
||||
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchArchiveDto;
|
||||
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchArchiveEleDto;
|
||||
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchArchivePaperDto;
|
||||
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchCollectSaveDto;
|
||||
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchDto;
|
||||
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchFileDto;
|
||||
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchLawCallbackDto;
|
||||
@@ -125,15 +126,11 @@ public class ContractLaunchServiceImpl implements ContractLaunchService {
|
||||
if (securityManager.isSuperAdmin()) {
|
||||
return "admin";
|
||||
}
|
||||
String permissionScope = resolveScopeByDataPermission(currentUser.getDataPermission());
|
||||
if (permissionScope != null) {
|
||||
return permissionScope;
|
||||
}
|
||||
if (authManager.isUserCanAccessSys(currentUser.getId(), SysEnum.MANAGE)) {
|
||||
return isAdminUser(currentUser) ? "company" : "personal";
|
||||
return "company";
|
||||
}
|
||||
if (authManager.isUserCanAccessSys(currentUser.getId(), SysEnum.BUSINESS)) {
|
||||
return isAdminUser(currentUser) ? "company" : "personal";
|
||||
return "company";
|
||||
}
|
||||
return "personal";
|
||||
}
|
||||
@@ -278,6 +275,10 @@ public class ContractLaunchServiceImpl implements ContractLaunchService {
|
||||
}
|
||||
SysUserEntity currentUser = adminSecurityManage.getUser();
|
||||
boolean singleAgreement = isSingleAgreement(contract);
|
||||
// 非单方协议:提交法务前做严格校验
|
||||
if (!singleAgreement) {
|
||||
validateSubmitForLaw(contract);
|
||||
}
|
||||
contract.setStatus(ContractLaunchConstants.STATUS_REVIEWING);
|
||||
contract.setApproveStatus(ContractLaunchConstants.APPROVE_STATUS_PENDING);
|
||||
contract.setApproveMessage(singleAgreement ? "已提交内部审批,等待审批" : "已提交法务,等待审批");
|
||||
@@ -551,6 +552,54 @@ public class ContractLaunchServiceImpl implements ContractLaunchService {
|
||||
* requestDTO.setPayload(payload);
|
||||
* dataCollectionPushService.collectContract(requestDTO);
|
||||
*/
|
||||
|
||||
/**
|
||||
* 保存采集信息(用印+签订信息)。
|
||||
*
|
||||
* 在 pending_collect 状态时,用户通过采集弹窗补充/修改
|
||||
* 用印信息和签订信息后保存到合同记录。
|
||||
* 不触发状态变更,可多次保存;后续再通过 mockCollect(或真实联调的 collect)推送法务。
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ContractLaunchDto saveCollectInfo(Long id, ContractLaunchCollectSaveDto collectDto) {
|
||||
ContractLaunchDto contract = getDetail(id);
|
||||
if (isSingleAgreement(contract)) {
|
||||
throw new ServiceException("单方协议无需执行法务采集");
|
||||
}
|
||||
if (!ContractLaunchConstants.STATUS_PENDING_COLLECT.equals(contract.getStatus())) {
|
||||
throw new ServiceException("仅待采集状态允许保存采集信息");
|
||||
}
|
||||
SysUserEntity currentUser = adminSecurityManage.getUser();
|
||||
|
||||
// 用印信息
|
||||
contract.setSealIsSeal(collectDto.getSealIsSeal());
|
||||
contract.setSealApproveSame(collectDto.getSealApproveSame());
|
||||
contract.setSealQuantity(collectDto.getSealQuantity());
|
||||
contract.setSealDate(collectDto.getSealDate());
|
||||
// 签订信息
|
||||
contract.setSignDate(collectDto.getSignDate());
|
||||
contract.setActiveDate(collectDto.getActiveDate());
|
||||
contract.setExecutorAccount(collectDto.getExecutorAccount());
|
||||
// 签署文件
|
||||
if (collectDto.getSignedFilePath() != null && !collectDto.getSignedFilePath().isBlank()) {
|
||||
contract.setSignedFileName(collectDto.getSignedFileName());
|
||||
contract.setSignedFilePath(collectDto.getSignedFilePath());
|
||||
contract.setSignedFileType(collectDto.getSignedFileType());
|
||||
contract.setSignedFileSize(collectDto.getSignedFileSize());
|
||||
}
|
||||
contract.setUpdateBy(currentUser.getUsername());
|
||||
contract.setUpdateTime(LocalDateTime.now());
|
||||
contractLaunchMapper.updateContract(contract);
|
||||
|
||||
insertLog(id, ContractLaunchConstants.ACTION_COLLECT, "保存采集信息",
|
||||
ContractLaunchConstants.ACTION_STATUS_SUCCESS, "用户通过采集弹窗保存用印/签订信息", null, currentUser);
|
||||
return getDetail(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 【测试按钮】模拟合同采集。
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ContractLaunchDto mockCollect(Long id) {
|
||||
@@ -1159,7 +1208,11 @@ public class ContractLaunchServiceImpl implements ContractLaunchService {
|
||||
} else if (isOppositeParty(item)) {
|
||||
item.setRoleName("相对方");
|
||||
}
|
||||
item.setSubjectCode(trim(item.getSubjectCode()));
|
||||
if (isOppositeParty(item)) {
|
||||
item.setSubjectCode(null);
|
||||
} else {
|
||||
item.setSubjectCode(trim(item.getSubjectCode()));
|
||||
}
|
||||
item.setCompanyName(trim(item.getCompanyName()));
|
||||
item.setCreditCode(trim(item.getCreditCode()));
|
||||
item.setOppositeId(trim(item.getOppositeId()));
|
||||
@@ -1284,21 +1337,7 @@ public class ContractLaunchServiceImpl implements ContractLaunchService {
|
||||
if (contract.getContractType() == null || contract.getContractType().isBlank()) {
|
||||
contract.setContractType(contract.getContractTypeCode());
|
||||
}
|
||||
if (contract.getValuationMode() == null || contract.getValuationMode().isBlank()) {
|
||||
throw new ServiceException("计价方式不能为空");
|
||||
}
|
||||
if (contract.getCurrencyName() == null || contract.getCurrencyName().isBlank()) {
|
||||
throw new ServiceException("币种不能为空");
|
||||
}
|
||||
if (contract.getPaymentMethod() == null || contract.getPaymentMethod().isBlank()) {
|
||||
throw new ServiceException("付款方式不能为空");
|
||||
}
|
||||
if (contract.getSealType() == null || contract.getSealType().isBlank()) {
|
||||
throw new ServiceException("签订方式不能为空");
|
||||
}
|
||||
if (contract.getSealQuantity() != null && contract.getSealQuantity() < 1) {
|
||||
throw new ServiceException("用印数量必须大于等于1");
|
||||
}
|
||||
// 以下字段在提交法务时才强制必填(validateSubmitForLaw),草稿保存时放宽
|
||||
if (contract.getContractPeriodType() == null || contract.getContractPeriodType().isBlank()) {
|
||||
throw new ServiceException("合同期限类型不能为空");
|
||||
}
|
||||
@@ -1313,7 +1352,7 @@ public class ContractLaunchServiceImpl implements ContractLaunchService {
|
||||
// if (contract.getActiveDate() == null) {
|
||||
// throw new ServiceException("合同生效日期不能为空");
|
||||
// }
|
||||
validateActiveDateWithinTerm(contract);
|
||||
// activeDate 已移至采集阶段,草稿保存时不校验
|
||||
if (contract.getPartyList() == null || contract.getPartyList().isEmpty()) {
|
||||
throw new ServiceException("至少需要维护一个合同方");
|
||||
}
|
||||
@@ -1364,6 +1403,7 @@ public class ContractLaunchServiceImpl implements ContractLaunchService {
|
||||
&& !item.getFilePath().isBlank()))) {
|
||||
throw new ServiceException("当前签订方式必须上传授权委托书附件");
|
||||
}
|
||||
// 履行计划在草稿和提交法务时均必填
|
||||
validatePerformancePlans(contract, false);
|
||||
}
|
||||
|
||||
@@ -1833,6 +1873,53 @@ public class ContractLaunchServiceImpl implements ContractLaunchService {
|
||||
validatePerformancePlans(contract, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交法务前的严格校验:草稿校验 + pushContract 必填项补全 + 履行计划校验
|
||||
*/
|
||||
private void validateSubmitForLaw(ContractLaunchDto contract) {
|
||||
// 先跑草稿基本校验(不含已移除的采集字段)
|
||||
validateDraft(contract);
|
||||
// 补全 pushContract 必填项
|
||||
if (contract.getValuationMode() == null || contract.getValuationMode().isBlank()) {
|
||||
throw new ServiceException("计价方式不能为空");
|
||||
}
|
||||
if (contract.getCurrencyName() == null || contract.getCurrencyName().isBlank()) {
|
||||
throw new ServiceException("币种不能为空");
|
||||
}
|
||||
if (contract.getSealType() == null || contract.getSealType().isBlank()) {
|
||||
throw new ServiceException("签订方式不能为空");
|
||||
}
|
||||
if (contract.getIsElectron() == null || contract.getIsElectron().isBlank()) {
|
||||
throw new ServiceException("签署方式不能为空");
|
||||
}
|
||||
if (contract.getPaymentDirection() == null || contract.getPaymentDirection().isBlank()) {
|
||||
throw new ServiceException("收支方向不能为空");
|
||||
}
|
||||
if (contract.getTextSource() == null || contract.getTextSource().isBlank()) {
|
||||
throw new ServiceException("文本来源不能为空");
|
||||
}
|
||||
if (contract.getContractSource() == null || contract.getContractSource().isBlank()) {
|
||||
throw new ServiceException("合同来源不能为空");
|
||||
}
|
||||
if (contract.getExecutorAccount() == null || contract.getExecutorAccount().isBlank()) {
|
||||
throw new ServiceException("合同执行人不能为空");
|
||||
}
|
||||
if (contract.getIsMajorContract() == null) {
|
||||
throw new ServiceException("是否重大合同不能为空");
|
||||
}
|
||||
if (contract.getIsOpenBidding() == null) {
|
||||
throw new ServiceException("是否公开招标不能为空");
|
||||
}
|
||||
if (contract.getIsSgat() == null || contract.getIsSgat().isBlank()) {
|
||||
throw new ServiceException("是否涉及港澳台不能为空");
|
||||
}
|
||||
if (contract.getNeedAmendments() == null || contract.getNeedAmendments().isBlank()) {
|
||||
throw new ServiceException("是否需修订条款不能为空");
|
||||
}
|
||||
// 履行计划校验(提交法务时必填)
|
||||
validatePerformancePlans(contract, false);
|
||||
}
|
||||
|
||||
private void validatePerformancePlans(ContractLaunchDto contract, boolean requirePlanId) {
|
||||
if (contract.getPerformancePlans() == null || contract.getPerformancePlans().isEmpty()) {
|
||||
throw new ServiceException("履行计划不能为空");
|
||||
|
||||
Reference in New Issue
Block a user