+228
@@ -0,0 +1,228 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.transport.pojo.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.FieldStrategy;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.springblade.core.tenant.mp.TenantEntity;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 合同变更实体类
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("blade_contract_change")
|
||||
@Schema(description = "合同变更")
|
||||
public class ContractChange extends TenantEntity {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "原合同ID")
|
||||
private Long contractId;
|
||||
|
||||
@Schema(description = "变更编号")
|
||||
private String changeNo;
|
||||
|
||||
@Schema(description = "变更类型")
|
||||
private String changeType;
|
||||
|
||||
@Schema(description = "变更日期")
|
||||
private LocalDate changeDate;
|
||||
|
||||
@Schema(description = "变更内容")
|
||||
private String changeContent;
|
||||
|
||||
@Schema(description = "变更原因")
|
||||
private String changeReason;
|
||||
|
||||
@Schema(description = "变更附件JSON")
|
||||
private String changeAttachmentsJson;
|
||||
|
||||
@Schema(description = "变更前快照JSON")
|
||||
private String beforeDataJson;
|
||||
|
||||
@Schema(description = "合同编号")
|
||||
private String contractNo;
|
||||
|
||||
@Schema(description = "合同名称")
|
||||
private String contractName;
|
||||
|
||||
@Schema(description = "所属项目ID")
|
||||
private Long projectId;
|
||||
|
||||
@Schema(description = "所属项目")
|
||||
private String projectName;
|
||||
|
||||
@Schema(description = "合同负责部门ID")
|
||||
private Long organizationId;
|
||||
|
||||
@Schema(description = "合同负责部门")
|
||||
private String organizationName;
|
||||
|
||||
@Schema(description = "合同类别")
|
||||
private String contractCategory;
|
||||
|
||||
@Schema(description = "签约类型")
|
||||
private String signType;
|
||||
|
||||
@Schema(description = "甲方")
|
||||
private String partyA;
|
||||
|
||||
@Schema(description = "乙方")
|
||||
private String partyB;
|
||||
|
||||
@Schema(description = "开始日期")
|
||||
private LocalDate startDate;
|
||||
|
||||
@Schema(description = "结束日期")
|
||||
private LocalDate endDate;
|
||||
|
||||
@Schema(description = "临时效力起")
|
||||
private LocalDate temporaryStartDate;
|
||||
|
||||
@Schema(description = "临时效力止")
|
||||
private LocalDate temporaryEndDate;
|
||||
|
||||
@Schema(description = "经办人ID")
|
||||
private Long handlerUserId;
|
||||
|
||||
@Schema(description = "经办人")
|
||||
private String handlerUserName;
|
||||
|
||||
@Schema(description = "签订日期")
|
||||
private LocalDate signDate;
|
||||
|
||||
@Schema(description = "申请日期")
|
||||
private LocalDate applyDate;
|
||||
|
||||
@Schema(description = "结算方式")
|
||||
private String settlementMode;
|
||||
|
||||
@Schema(description = "合同格式")
|
||||
private String contractFormat;
|
||||
|
||||
@Schema(description = "是否需要加盖法人章")
|
||||
@TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS)
|
||||
private Integer legalSealFlag;
|
||||
|
||||
@Schema(description = "一式份数")
|
||||
@TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS)
|
||||
private Integer copyCount;
|
||||
|
||||
@Schema(description = "结算币种")
|
||||
private String settlementCurrency;
|
||||
|
||||
@Schema(description = "开票周期(天)")
|
||||
@TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS)
|
||||
private Integer invoiceCycle;
|
||||
|
||||
@Schema(description = "回款账期(天)")
|
||||
@TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS)
|
||||
private Integer paymentDays;
|
||||
|
||||
@Schema(description = "合同金额")
|
||||
@TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS)
|
||||
private BigDecimal contractAmount;
|
||||
|
||||
@Schema(description = "是否范本")
|
||||
@TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS)
|
||||
private Integer templateFlag;
|
||||
|
||||
@Schema(description = "原件合同编号")
|
||||
@TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS)
|
||||
private String originalContractNo;
|
||||
|
||||
@Schema(description = "是否电子章")
|
||||
@TableField(insertStrategy = FieldStrategy.ALWAYS, updateStrategy = FieldStrategy.ALWAYS)
|
||||
private Integer electronicSealFlag;
|
||||
|
||||
@Schema(description = "计费信息开关")
|
||||
private Integer billingEnabled;
|
||||
|
||||
@Schema(description = "费用生成模式")
|
||||
private String feeGenerationMode;
|
||||
|
||||
@Schema(description = "合同主文件JSON")
|
||||
private String contractFileJson;
|
||||
|
||||
@Schema(description = "其它附件JSON")
|
||||
private String attachmentsJson;
|
||||
|
||||
@Schema(description = "计费方案JSON")
|
||||
private String billingPlanJson;
|
||||
|
||||
@Schema(description = "结算生成规则JSON")
|
||||
private String settlementRuleJson;
|
||||
|
||||
@Schema(description = "预结算配置JSON")
|
||||
private String preSettlementConfigJson;
|
||||
|
||||
@Schema(description = "正式结算配置JSON")
|
||||
private String formalSettlementConfigJson;
|
||||
|
||||
@Schema(description = "付款比例设置JSON")
|
||||
private String paymentRatioJson;
|
||||
|
||||
@Schema(description = "对账配置JSON")
|
||||
private String reconciliationJson;
|
||||
|
||||
@Schema(description = "合同主要内容")
|
||||
private String mainContent;
|
||||
|
||||
@Schema(description = "其他事项说明")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "合规客商风险等级(展示用)")
|
||||
private String hcsRiskLevel;
|
||||
|
||||
@Schema(description = "合规客商黑名单状态(展示用)")
|
||||
private String hcsBlackStatus;
|
||||
|
||||
@Schema(description = "审批状态")
|
||||
private String approvalStatus;
|
||||
|
||||
@Schema(description = "当前节点")
|
||||
private String currentNode;
|
||||
|
||||
@Schema(description = "当前处理人")
|
||||
private String currentProcessor;
|
||||
|
||||
@Schema(description = "审核通过时间")
|
||||
private LocalDateTime approvedTime;
|
||||
|
||||
@Schema(description = "同步状态")
|
||||
private String syncStatus;
|
||||
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.transport.pojo.vo;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.springblade.transport.pojo.entity.ContractChange;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* 合同变更视图实体类
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Schema(description = "合同变更")
|
||||
public class ContractChangeVO extends ContractChange {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableField(exist = false)
|
||||
@Schema(description = "是否查看全部组织")
|
||||
private Integer allDept;
|
||||
|
||||
@TableField(exist = false)
|
||||
@Schema(description = "是否只读")
|
||||
private Boolean readonly;
|
||||
|
||||
@TableField(exist = false)
|
||||
@Schema(description = "创建人姓名")
|
||||
private String createUserName;
|
||||
|
||||
@TableField(exist = false)
|
||||
@Schema(description = "更新人姓名")
|
||||
private String updateUserName;
|
||||
|
||||
@TableField(exist = false)
|
||||
@Schema(description = "审批状态名称")
|
||||
private String approvalStatusName;
|
||||
|
||||
@TableField(exist = false)
|
||||
@Schema(description = "同步状态名称")
|
||||
private String syncStatusName;
|
||||
|
||||
}
|
||||
+157
@@ -0,0 +1,157 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.transport.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springblade.core.boot.ctrl.BladeController;
|
||||
import org.springblade.core.mp.support.Condition;
|
||||
import org.springblade.core.mp.support.Query;
|
||||
import org.springblade.core.secure.annotation.PreAuth;
|
||||
import org.springblade.core.tool.api.R;
|
||||
import org.springblade.transport.pojo.entity.ContractChange;
|
||||
import org.springblade.transport.pojo.vo.ContractChangeVO;
|
||||
import org.springblade.transport.service.IContractChangeService;
|
||||
import org.springblade.transport.support.hcs.HcsImmediatePushSupport;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* 合同变更 控制器
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
@PreAuth(menu = "contract_change")
|
||||
@RequestMapping("/contract-change")
|
||||
@Tag(name = "合同变更", description = "合同变更")
|
||||
public class ContractChangeController extends BladeController {
|
||||
|
||||
private final IContractChangeService contractChangeService;
|
||||
private final HcsImmediatePushSupport hcsImmediatePushSupport;
|
||||
|
||||
@GetMapping("/detail")
|
||||
@ApiOperationSupport(order = 1)
|
||||
@Operation(summary = "详情", description = "传入id")
|
||||
public R<ContractChangeVO> detail(@Parameter(description = "主键", required = true) @RequestParam Long id) {
|
||||
return R.data(contractChangeService.detail(id));
|
||||
}
|
||||
|
||||
@GetMapping("/list")
|
||||
@ApiOperationSupport(order = 2)
|
||||
@Operation(summary = "分页", description = "传入contractChange")
|
||||
public R<IPage<ContractChangeVO>> list(ContractChangeVO contractChange, Query query) {
|
||||
return R.data(contractChangeService.selectContractChangePage(Condition.getPage(query), contractChange));
|
||||
}
|
||||
|
||||
@PostMapping("/create-from-contract")
|
||||
@ApiOperationSupport(order = 3)
|
||||
@Operation(summary = "基于合同创建变更草稿", description = "传入contractId、changeType")
|
||||
public R<ContractChangeVO> createFromContract(@Parameter(description = "合同ID", required = true) @RequestParam Long contractId,
|
||||
@RequestParam(required = false) String changeType) {
|
||||
return R.data(contractChangeService.createFromContract(contractId, changeType));
|
||||
}
|
||||
|
||||
@PostMapping("/save-draft")
|
||||
@ApiOperationSupport(order = 4)
|
||||
@Operation(summary = "保存草稿", description = "传入contractChange")
|
||||
public R saveDraft(@RequestBody ContractChange contractChange) {
|
||||
return R.status(contractChangeService.saveDraft(contractChange));
|
||||
}
|
||||
|
||||
@PostMapping("/submit")
|
||||
@ApiOperationSupport(order = 5)
|
||||
@Operation(summary = "保存并提交审批", description = "传入contractChange")
|
||||
public R submit(@RequestBody ContractChange contractChange) {
|
||||
return contractChangeService.submit(contractChange) ? R.data(contractChange) : R.fail("提交失败");
|
||||
}
|
||||
|
||||
@PostMapping("/submit-approval")
|
||||
@ApiOperationSupport(order = 6)
|
||||
@Operation(summary = "提交审批", description = "传入id")
|
||||
public R submitApproval(@Parameter(description = "主键", required = true) @RequestParam Long id) {
|
||||
return R.status(contractChangeService.submitApproval(id));
|
||||
}
|
||||
|
||||
@PostMapping("/approve")
|
||||
@ApiOperationSupport(order = 7)
|
||||
@Operation(summary = "审批通过", description = "传入id,通过后回写原合同并推送合规")
|
||||
public R approve(@Parameter(description = "主键", required = true) @RequestParam Long id) {
|
||||
Long contractId = contractChangeService.approve(id);
|
||||
hcsImmediatePushSupport.pushContractAndWait(contractId);
|
||||
String syncFailure = HcsImmediatePushSupport.pollSyncFailure();
|
||||
if (syncFailure != null) {
|
||||
ContractChange contractChange = contractChangeService.getById(id);
|
||||
if (contractChange != null) {
|
||||
contractChange.setSyncStatus("failed");
|
||||
contractChangeService.updateById(contractChange);
|
||||
}
|
||||
return R.data(Boolean.FALSE, "审批通过,但合规推送失败:" + syncFailure);
|
||||
}
|
||||
ContractChange contractChange = contractChangeService.getById(id);
|
||||
if (contractChange != null) {
|
||||
contractChange.setSyncStatus("synced");
|
||||
contractChangeService.updateById(contractChange);
|
||||
}
|
||||
return R.success("审批通过");
|
||||
}
|
||||
|
||||
@PostMapping("/reject")
|
||||
@ApiOperationSupport(order = 8)
|
||||
@Operation(summary = "审批驳回", description = "传入id")
|
||||
public R reject(@Parameter(description = "主键", required = true) @RequestParam Long id) {
|
||||
return R.status(contractChangeService.reject(id));
|
||||
}
|
||||
|
||||
@PostMapping("/withdraw")
|
||||
@ApiOperationSupport(order = 9)
|
||||
@Operation(summary = "撤回审批", description = "传入id")
|
||||
public R withdraw(@Parameter(description = "主键", required = true) @RequestParam Long id) {
|
||||
return R.status(contractChangeService.withdraw(id));
|
||||
}
|
||||
|
||||
@PostMapping("/remove")
|
||||
@ApiOperationSupport(order = 10)
|
||||
@Operation(summary = "逻辑删除", description = "传入ids")
|
||||
public R remove(@Parameter(description = "主键集合", required = true) @RequestParam String ids) {
|
||||
return R.status(contractChangeService.removeDraft(ids));
|
||||
}
|
||||
|
||||
@PostMapping("/mark-sync-status")
|
||||
@ApiOperationSupport(order = 11)
|
||||
@Operation(summary = "标记同步状态", description = "传入ids和syncStatus")
|
||||
public R markSyncStatus(@Parameter(description = "主键集合", required = true) @RequestParam String ids,
|
||||
@Parameter(description = "同步状态", required = true) @RequestParam String syncStatus) {
|
||||
return R.status(contractChangeService.markSyncStatus(ids, syncStatus));
|
||||
}
|
||||
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.transport.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.springblade.transport.pojo.entity.ContractChange;
|
||||
|
||||
/**
|
||||
* 合同变更 Mapper 接口
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public interface ContractChangeMapper extends BaseMapper<ContractChange> {
|
||||
}
|
||||
+74
@@ -10,6 +10,7 @@ import org.springblade.transport.pojo.dto.InvoiceApplicationStatusRequest;
|
||||
import org.springblade.transport.pojo.dto.InvoiceReceiptStatusRequest;
|
||||
import org.springblade.transport.pojo.dto.PaymentApplicationStatusRequest;
|
||||
import org.springblade.transport.pojo.entity.BillPayment;
|
||||
import org.springblade.transport.pojo.entity.ContractChange;
|
||||
import org.springblade.transport.pojo.entity.ContractManage;
|
||||
import org.springblade.transport.pojo.entity.FormalSettlement;
|
||||
import org.springblade.transport.pojo.entity.InvoiceApplication;
|
||||
@@ -19,6 +20,7 @@ import org.springblade.transport.pojo.entity.PreSettlement;
|
||||
import org.springblade.transport.pojo.entity.ProjectApply;
|
||||
import org.springblade.transport.pojo.entity.ProjectChange;
|
||||
import org.springblade.transport.service.IBillPaymentService;
|
||||
import org.springblade.transport.service.IContractChangeService;
|
||||
import org.springblade.transport.service.IContractManageService;
|
||||
import org.springblade.transport.service.ICustomerArchiveService;
|
||||
import org.springblade.transport.service.IFormalSettlementService;
|
||||
@@ -224,6 +226,78 @@ public final class MkProcessBizHandlers {
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
@TenantIgnore
|
||||
@RequiredArgsConstructor
|
||||
public static class ContractChangeHandler implements IMkProcessBizHandler {
|
||||
private final IContractChangeService service;
|
||||
private final HcsImmediatePushSupport hcsImmediatePushSupport;
|
||||
|
||||
@Override
|
||||
public String bizType() {
|
||||
return "contract-change";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object publicDetail(Long id) {
|
||||
return service.publicDetail(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean syncFromProcessInfo(Long id, Object processInfo) {
|
||||
ContractChange entity = service.getById(id);
|
||||
if (entity == null) {
|
||||
return false;
|
||||
}
|
||||
String node = MkProcessNodeHelper.currentNode(processInfo);
|
||||
String processor = MkProcessNodeHelper.currentProcessor(processInfo);
|
||||
if (Func.isEmpty(node) && Func.isEmpty(processor)) {
|
||||
return false;
|
||||
}
|
||||
if (Func.isNotEmpty(node)) {
|
||||
entity.setCurrentNode(node);
|
||||
}
|
||||
if (Func.isNotEmpty(processor)) {
|
||||
entity.setCurrentProcessor(processor);
|
||||
}
|
||||
entity.setApprovalStatus("reviewing");
|
||||
return service.updateById(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean approveFromProcess(Long id, String processorName) {
|
||||
ContractChange entity = service.getById(id);
|
||||
if (entity == null || "approved".equals(entity.getApprovalStatus())) {
|
||||
return entity != null;
|
||||
}
|
||||
Long contractId = service.approve(id);
|
||||
entity = service.getById(id);
|
||||
if (entity != null) {
|
||||
entity.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统"));
|
||||
service.updateById(entity);
|
||||
}
|
||||
if (contractId != null) {
|
||||
hcsImmediatePushSupport.pushContractAfterCommit(contractId);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean rejectFromProcess(Long id, String processorName) {
|
||||
ContractChange entity = service.getById(id);
|
||||
if (entity == null || "rejected".equals(entity.getApprovalStatus())) {
|
||||
return entity != null;
|
||||
}
|
||||
boolean rejected = service.reject(id);
|
||||
entity = service.getById(id);
|
||||
if (entity != null) {
|
||||
entity.setCurrentProcessor(MkProcessNodeHelper.text(processorName, "系统"));
|
||||
service.updateById(entity);
|
||||
}
|
||||
return rejected;
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
@TenantIgnore
|
||||
@RequiredArgsConstructor
|
||||
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.transport.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import org.springblade.core.mp.base.BaseService;
|
||||
import org.springblade.transport.pojo.entity.ContractChange;
|
||||
import org.springblade.transport.pojo.vo.ContractChangeVO;
|
||||
|
||||
/**
|
||||
* 合同变更 服务类
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public interface IContractChangeService extends BaseService<ContractChange> {
|
||||
|
||||
IPage<ContractChangeVO> selectContractChangePage(IPage<ContractChange> page, ContractChangeVO contractChange);
|
||||
|
||||
ContractChangeVO detail(Long id);
|
||||
|
||||
/**
|
||||
* 公开详情(MK 回调/公开页)
|
||||
*/
|
||||
ContractChangeVO publicDetail(Long id);
|
||||
|
||||
/**
|
||||
* 基于正式合同创建变更草稿
|
||||
*/
|
||||
ContractChangeVO createFromContract(Long contractId, String changeType);
|
||||
|
||||
boolean saveDraft(ContractChange contractChange);
|
||||
|
||||
boolean submit(ContractChange contractChange);
|
||||
|
||||
boolean submitApproval(Long id);
|
||||
|
||||
/**
|
||||
* 审批通过:回写原合同并标记同步
|
||||
*
|
||||
* @return 原合同ID,供 Controller 推送合规
|
||||
*/
|
||||
Long approve(Long id);
|
||||
|
||||
boolean reject(Long id);
|
||||
|
||||
boolean withdraw(Long id);
|
||||
|
||||
boolean removeDraft(String ids);
|
||||
|
||||
/**
|
||||
* 批量标记同步状态(用于列表批量同步后回写)
|
||||
*/
|
||||
boolean markSyncStatus(String ids, String syncStatus);
|
||||
|
||||
}
|
||||
+10
@@ -25,6 +25,7 @@ package org.springblade.transport.service;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import org.springblade.core.mp.base.BaseService;
|
||||
import org.springblade.transport.excel.ContractManageExcel;
|
||||
import org.springblade.transport.pojo.entity.ContractChange;
|
||||
import org.springblade.transport.pojo.entity.ContractManage;
|
||||
import org.springblade.transport.pojo.vo.ContractManageVO;
|
||||
|
||||
@@ -57,6 +58,15 @@ public interface IContractManageService extends BaseService<ContractManage> {
|
||||
boolean withdraw(Long id);
|
||||
boolean startChange(Long id, String changeContent, String changeReason);
|
||||
boolean submitChange(ContractManage contractManage);
|
||||
|
||||
/**
|
||||
* 将独立合同变更单回写到原合同(审批通过后调用,不改写原合同为 change_reviewing)
|
||||
*
|
||||
* @param change 合同变更单
|
||||
* @return 是否成功
|
||||
*/
|
||||
boolean applyChangeFromRecord(ContractChange change);
|
||||
|
||||
boolean updateAttachments(ContractManage contractManage);
|
||||
boolean terminate(Long id, String reason);
|
||||
boolean removeDraft(String ids);
|
||||
|
||||
+461
@@ -0,0 +1,461 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.transport.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springblade.core.log.exception.ServiceException;
|
||||
import org.springblade.core.mp.base.BaseServiceImpl;
|
||||
import org.springblade.core.secure.utils.AuthUtil;
|
||||
import org.springblade.core.tenant.annotation.TenantIgnore;
|
||||
import org.springblade.core.tool.jackson.JsonUtil;
|
||||
import org.springblade.core.tool.utils.BeanUtil;
|
||||
import org.springblade.core.tool.utils.Func;
|
||||
import org.springblade.transport.constant.HcsSyncConstant;
|
||||
import org.springblade.transport.mapper.ContractChangeMapper;
|
||||
import org.springblade.transport.pojo.entity.ContractChange;
|
||||
import org.springblade.transport.pojo.entity.ContractManage;
|
||||
import org.springblade.transport.pojo.vo.ContractChangeVO;
|
||||
import org.springblade.transport.pojo.vo.ContractManageVO;
|
||||
import org.springblade.transport.service.IContractChangeService;
|
||||
import org.springblade.transport.service.IContractManageService;
|
||||
import org.springblade.transport.support.TransportBusinessSupport;
|
||||
import org.springblade.transport.wrapper.ContractChangeWrapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 合同变更 服务实现类
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class ContractChangeServiceImpl extends BaseServiceImpl<ContractChangeMapper, ContractChange> implements IContractChangeService {
|
||||
|
||||
private static final String STATUS_DRAFT = "draft";
|
||||
private static final String STATUS_REVIEWING = "reviewing";
|
||||
private static final String STATUS_WITHDRAWN = "withdrawn";
|
||||
private static final String STATUS_APPROVED = "approved";
|
||||
private static final String STATUS_REJECTED = "rejected";
|
||||
private static final String STAGE_FORMAL = "formal";
|
||||
private static final String CHANGE_TYPE_INFO = "合同信息变更";
|
||||
private static final String CHANGE_TYPE_SETTLEMENT = "结算规则变更";
|
||||
private static final DateTimeFormatter CODE_DATE = DateTimeFormatter.ofPattern("yyyyMMdd");
|
||||
|
||||
private final IContractManageService contractManageService;
|
||||
|
||||
@Override
|
||||
public IPage<ContractChangeVO> selectContractChangePage(IPage<ContractChange> page, ContractChangeVO contractChange) {
|
||||
IPage<ContractChange> entityPage = page(page, buildQuery(contractChange).orderByDesc(ContractChange::getCreateTime));
|
||||
IPage<ContractChangeVO> voPage = ContractChangeWrapper.build().pageVO(entityPage);
|
||||
voPage.getRecords().forEach(this::fillReadonly);
|
||||
return voPage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContractChangeVO detail(Long id) {
|
||||
ContractChangeVO contractChangeVO = ContractChangeWrapper.build().entityVO(loadExists(id));
|
||||
fillReadonly(contractChangeVO);
|
||||
return contractChangeVO;
|
||||
}
|
||||
|
||||
@Override
|
||||
@TenantIgnore
|
||||
public ContractChangeVO publicDetail(Long id) {
|
||||
ContractChangeVO contractChangeVO = ContractChangeWrapper.build().entityVO(loadExists(id));
|
||||
contractChangeVO.setReadonly(Boolean.TRUE);
|
||||
return contractChangeVO;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ContractChangeVO createFromContract(Long contractId, String changeType) {
|
||||
ContractManageVO contractManage = contractManageService.detail(contractId);
|
||||
validateContractChangeable(contractManage);
|
||||
ContractChange reviewing = findLatestByStatuses(contractId, List.of(STATUS_REVIEWING));
|
||||
if (reviewing != null) {
|
||||
throw new ServiceException("该合同已有审批中的变更单,请先完成后再发起");
|
||||
}
|
||||
ContractChange unfinished = findLatestByStatuses(contractId, List.of(STATUS_DRAFT, STATUS_WITHDRAWN, STATUS_REJECTED));
|
||||
if (unfinished != null) {
|
||||
// 已有未完结变更单时复用,避免重复建单
|
||||
return detail(unfinished.getId());
|
||||
}
|
||||
String resolvedType = Func.isBlank(changeType) ? CHANGE_TYPE_INFO : changeType.trim();
|
||||
if (!List.of(CHANGE_TYPE_INFO, CHANGE_TYPE_SETTLEMENT).contains(resolvedType)) {
|
||||
throw new ServiceException("请选择变更类型");
|
||||
}
|
||||
ContractChange contractChange = copyFromContract(contractManage);
|
||||
contractChange.setId(null);
|
||||
contractChange.setContractId(contractManage.getId());
|
||||
contractChange.setChangeNo(nextChangeNo());
|
||||
contractChange.setChangeType(resolvedType);
|
||||
contractChange.setChangeDate(LocalDate.now());
|
||||
contractChange.setChangeContent(null);
|
||||
contractChange.setChangeReason(null);
|
||||
contractChange.setChangeAttachmentsJson(null);
|
||||
contractChange.setBeforeDataJson(JsonUtil.toJson(buildSnapshot(contractManage)));
|
||||
contractChange.setApprovalStatus(STATUS_DRAFT);
|
||||
contractChange.setCurrentNode("草稿");
|
||||
contractChange.setCurrentProcessor(AuthUtil.getUserName());
|
||||
contractChange.setApprovedTime(null);
|
||||
contractChange.setSyncStatus(null);
|
||||
save(contractChange);
|
||||
return detail(contractChange.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean saveDraft(ContractChange contractChange) {
|
||||
ContractChange oldRecord = loadEditable(contractChange.getId());
|
||||
prepareEditableFields(oldRecord, contractChange);
|
||||
validateDraft(oldRecord);
|
||||
if (Func.isEmpty(oldRecord.getApprovalStatus()) || STATUS_REVIEWING.equals(oldRecord.getApprovalStatus())) {
|
||||
oldRecord.setApprovalStatus(STATUS_DRAFT);
|
||||
}
|
||||
if (List.of(STATUS_WITHDRAWN, STATUS_REJECTED).contains(oldRecord.getApprovalStatus())) {
|
||||
// 驳回/撤回后编辑仍保持原状态,提交时再进入审批中
|
||||
} else {
|
||||
oldRecord.setApprovalStatus(STATUS_DRAFT);
|
||||
oldRecord.setCurrentNode("草稿");
|
||||
}
|
||||
return updateById(oldRecord);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean submit(ContractChange contractChange) {
|
||||
ContractChange oldRecord = loadEditable(contractChange.getId());
|
||||
prepareEditableFields(oldRecord, contractChange);
|
||||
validateSubmit(oldRecord);
|
||||
oldRecord.setApprovalStatus(STATUS_REVIEWING);
|
||||
oldRecord.setCurrentNode(resolveApprovalNode(oldRecord));
|
||||
oldRecord.setCurrentProcessor("待处理");
|
||||
oldRecord.setApprovedTime(null);
|
||||
return updateById(oldRecord);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean submitApproval(Long id) {
|
||||
ContractChange contractChange = loadEditable(id);
|
||||
validateSubmit(contractChange);
|
||||
contractChange.setApprovalStatus(STATUS_REVIEWING);
|
||||
contractChange.setCurrentNode(resolveApprovalNode(contractChange));
|
||||
contractChange.setCurrentProcessor("待处理");
|
||||
contractChange.setApprovedTime(null);
|
||||
return updateById(contractChange);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long approve(Long id) {
|
||||
ContractChange contractChange = loadReviewing(id);
|
||||
contractChange.setApprovalStatus(STATUS_APPROVED);
|
||||
contractChange.setCurrentNode("审批通过");
|
||||
String processor = TransportBusinessSupport.trimToNull(AuthUtil.getUserName());
|
||||
contractChange.setCurrentProcessor(processor == null ? "系统" : processor);
|
||||
contractChange.setApprovedTime(LocalDateTime.now());
|
||||
contractChange.setSyncStatus(HcsSyncConstant.HCS_STATUS_UNSYNCED);
|
||||
updateById(contractChange);
|
||||
contractManageService.applyChangeFromRecord(contractChange);
|
||||
return contractChange.getContractId();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean reject(Long id) {
|
||||
ContractChange contractChange = loadReviewing(id);
|
||||
contractChange.setApprovalStatus(STATUS_REJECTED);
|
||||
contractChange.setCurrentNode("审核不通过");
|
||||
String processor = TransportBusinessSupport.trimToNull(AuthUtil.getUserName());
|
||||
contractChange.setCurrentProcessor(processor == null ? "系统" : processor);
|
||||
return updateById(contractChange);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean withdraw(Long id) {
|
||||
ContractChange contractChange = loadReviewing(id);
|
||||
contractChange.setApprovalStatus(STATUS_WITHDRAWN);
|
||||
contractChange.setCurrentNode("已撤回");
|
||||
contractChange.setCurrentProcessor(AuthUtil.getUserName());
|
||||
return updateById(contractChange);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean removeDraft(String ids) {
|
||||
List<Long> idList = Func.toLongList(ids);
|
||||
if (Func.isEmpty(idList)) {
|
||||
throw new ServiceException("请选择需要删除的数据");
|
||||
}
|
||||
for (ContractChange contractChange : listByIds(idList)) {
|
||||
if (!List.of(STATUS_DRAFT, STATUS_WITHDRAWN, STATUS_REJECTED).contains(contractChange.getApprovalStatus())) {
|
||||
throw new ServiceException("仅草稿、已撤回、已驳回的合同变更允许删除");
|
||||
}
|
||||
}
|
||||
return deleteLogic(idList);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean markSyncStatus(String ids, String syncStatus) {
|
||||
List<Long> idList = Func.toLongList(ids);
|
||||
if (Func.isEmpty(idList)) {
|
||||
throw new ServiceException("请选择需要同步的数据");
|
||||
}
|
||||
if (!List.of(HcsSyncConstant.HCS_STATUS_UNSYNCED, HcsSyncConstant.HCS_STATUS_SYNCED, HcsSyncConstant.HCS_STATUS_FAILED)
|
||||
.contains(syncStatus)) {
|
||||
throw new ServiceException("同步状态不合法");
|
||||
}
|
||||
for (ContractChange contractChange : listByIds(idList)) {
|
||||
if (!Objects.equals(contractChange.getApprovalStatus(), STATUS_APPROVED)) {
|
||||
throw new ServiceException("仅审批通过的合同变更允许更新同步状态");
|
||||
}
|
||||
contractChange.setSyncStatus(syncStatus);
|
||||
updateById(contractChange);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<ContractChange> buildQuery(ContractChangeVO contractChange) {
|
||||
TransportBusinessSupport.validateAllDept(contractChange.getAllDept(), "合同变更");
|
||||
LambdaQueryWrapper<ContractChange> queryWrapper = Wrappers.<ContractChange>lambdaQuery().eq(ContractChange::getIsDeleted, 0);
|
||||
if (TransportBusinessSupport.isAdministrator()) {
|
||||
if (Objects.equals(contractChange.getAllDept(), 1) && Func.isNotEmpty(contractChange.getOrganizationId())) {
|
||||
queryWrapper.eq(ContractChange::getOrganizationId, contractChange.getOrganizationId());
|
||||
}
|
||||
} else if (!Objects.equals(contractChange.getAllDept(), 1)) {
|
||||
Long currentDeptId = TransportBusinessSupport.currentDeptId("合同变更");
|
||||
Long currentUserId = AuthUtil.getUserId();
|
||||
queryWrapper.and(wrapper -> wrapper.eq(ContractChange::getOrganizationId, currentDeptId)
|
||||
.or().eq(ContractChange::getCreateUser, currentUserId)
|
||||
.or().eq(ContractChange::getHandlerUserId, currentUserId));
|
||||
} else if (Func.isNotEmpty(contractChange.getOrganizationId())) {
|
||||
queryWrapper.eq(ContractChange::getOrganizationId, contractChange.getOrganizationId());
|
||||
}
|
||||
queryWrapper.eq(Func.isNotEmpty(contractChange.getProjectId()), ContractChange::getProjectId, contractChange.getProjectId())
|
||||
.like(Func.isNotEmpty(contractChange.getContractNo()), ContractChange::getContractNo, contractChange.getContractNo())
|
||||
.like(Func.isNotEmpty(contractChange.getContractName()), ContractChange::getContractName, contractChange.getContractName())
|
||||
.like(Func.isNotEmpty(contractChange.getProjectName()) && Func.isEmpty(contractChange.getProjectId()),
|
||||
ContractChange::getProjectName, contractChange.getProjectName())
|
||||
.like(Func.isNotEmpty(contractChange.getOrganizationName()), ContractChange::getOrganizationName, contractChange.getOrganizationName())
|
||||
.eq(Func.isNotEmpty(contractChange.getContractCategory()), ContractChange::getContractCategory, contractChange.getContractCategory())
|
||||
.eq(Func.isNotEmpty(contractChange.getSignType()), ContractChange::getSignType, contractChange.getSignType())
|
||||
.eq(Func.isNotEmpty(contractChange.getApprovalStatus()), ContractChange::getApprovalStatus, contractChange.getApprovalStatus())
|
||||
.eq(Func.isNotEmpty(contractChange.getChangeType()), ContractChange::getChangeType, contractChange.getChangeType())
|
||||
.eq(Func.isNotEmpty(contractChange.getContractId()), ContractChange::getContractId, contractChange.getContractId())
|
||||
.like(Func.isNotEmpty(contractChange.getChangeNo()), ContractChange::getChangeNo, contractChange.getChangeNo());
|
||||
return queryWrapper;
|
||||
}
|
||||
|
||||
private ContractChange copyFromContract(ContractManage contractManage) {
|
||||
ContractChange contractChange = Objects.requireNonNull(BeanUtil.copyProperties(contractManage, ContractChange.class));
|
||||
contractChange.setId(null);
|
||||
contractChange.setCreateUser(null);
|
||||
contractChange.setCreateDept(null);
|
||||
contractChange.setCreateTime(null);
|
||||
contractChange.setUpdateUser(null);
|
||||
contractChange.setUpdateTime(null);
|
||||
contractChange.setStatus(1);
|
||||
contractChange.setIsDeleted(0);
|
||||
return contractChange;
|
||||
}
|
||||
|
||||
private void prepareEditableFields(ContractChange target, ContractChange source) {
|
||||
target.setChangeType(TransportBusinessSupport.trimToNull(source.getChangeType()));
|
||||
target.setChangeReason(TransportBusinessSupport.trimToNull(source.getChangeReason()));
|
||||
target.setChangeContent(TransportBusinessSupport.trimToNull(source.getChangeContent()));
|
||||
target.setChangeAttachmentsJson(TransportBusinessSupport.trimToNull(source.getChangeAttachmentsJson()));
|
||||
target.setSignType(source.getSignType());
|
||||
target.setContractNo(source.getContractNo());
|
||||
target.setContractName(source.getContractName());
|
||||
target.setPartyB(source.getPartyB());
|
||||
target.setStartDate(source.getStartDate());
|
||||
target.setEndDate(source.getEndDate());
|
||||
target.setContractFormat(source.getContractFormat());
|
||||
target.setSettlementMode(source.getSettlementMode());
|
||||
target.setLegalSealFlag(source.getLegalSealFlag());
|
||||
target.setCopyCount(source.getCopyCount());
|
||||
target.setSettlementCurrency(source.getSettlementCurrency());
|
||||
target.setInvoiceCycle(source.getInvoiceCycle());
|
||||
target.setPaymentDays(source.getPaymentDays());
|
||||
target.setContractAmount(source.getContractAmount());
|
||||
target.setTemplateFlag(source.getTemplateFlag());
|
||||
target.setOriginalContractNo(source.getOriginalContractNo());
|
||||
target.setElectronicSealFlag(source.getElectronicSealFlag());
|
||||
target.setBillingEnabled(source.getBillingEnabled());
|
||||
target.setFeeGenerationMode(source.getFeeGenerationMode());
|
||||
target.setContractFileJson(source.getContractFileJson());
|
||||
target.setAttachmentsJson(source.getAttachmentsJson());
|
||||
target.setBillingPlanJson(source.getBillingPlanJson());
|
||||
target.setSettlementRuleJson(source.getSettlementRuleJson());
|
||||
target.setPreSettlementConfigJson(source.getPreSettlementConfigJson());
|
||||
target.setFormalSettlementConfigJson(source.getFormalSettlementConfigJson());
|
||||
target.setPaymentRatioJson(source.getPaymentRatioJson());
|
||||
target.setReconciliationJson(source.getReconciliationJson());
|
||||
target.setMainContent(source.getMainContent());
|
||||
target.setRemark(source.getRemark());
|
||||
}
|
||||
|
||||
private Map<String, Object> buildSnapshot(ContractManage contractManage) {
|
||||
Map<String, Object> data = new LinkedHashMap<>();
|
||||
data.put("contractNo", contractManage.getContractNo());
|
||||
data.put("contractName", contractManage.getContractName());
|
||||
data.put("signType", contractManage.getSignType());
|
||||
data.put("partyB", contractManage.getPartyB());
|
||||
data.put("startDate", contractManage.getStartDate());
|
||||
data.put("endDate", contractManage.getEndDate());
|
||||
data.put("contractFormat", contractManage.getContractFormat());
|
||||
data.put("settlementMode", contractManage.getSettlementMode());
|
||||
data.put("legalSealFlag", contractManage.getLegalSealFlag());
|
||||
data.put("copyCount", contractManage.getCopyCount());
|
||||
data.put("settlementCurrency", contractManage.getSettlementCurrency());
|
||||
data.put("invoiceCycle", contractManage.getInvoiceCycle());
|
||||
data.put("paymentDays", contractManage.getPaymentDays());
|
||||
data.put("contractAmount", contractManage.getContractAmount());
|
||||
data.put("templateFlag", contractManage.getTemplateFlag());
|
||||
data.put("originalContractNo", contractManage.getOriginalContractNo());
|
||||
data.put("electronicSealFlag", contractManage.getElectronicSealFlag());
|
||||
data.put("mainContent", contractManage.getMainContent());
|
||||
data.put("remark", contractManage.getRemark());
|
||||
data.put("feeGenerationMode", contractManage.getFeeGenerationMode());
|
||||
data.put("billingPlanJson", contractManage.getBillingPlanJson());
|
||||
data.put("settlementRuleJson", contractManage.getSettlementRuleJson());
|
||||
data.put("preSettlementConfigJson", contractManage.getPreSettlementConfigJson());
|
||||
data.put("formalSettlementConfigJson", contractManage.getFormalSettlementConfigJson());
|
||||
data.put("paymentRatioJson", contractManage.getPaymentRatioJson());
|
||||
data.put("contractFileJson", contractManage.getContractFileJson());
|
||||
data.put("attachmentsJson", contractManage.getAttachmentsJson());
|
||||
return data;
|
||||
}
|
||||
|
||||
private void validateContractChangeable(ContractManage contractManage) {
|
||||
boolean approved = List.of("approved", "change_approved").contains(contractManage.getApprovalStatus());
|
||||
if (!approved || !Objects.equals(contractManage.getContractStage(), STAGE_FORMAL)) {
|
||||
throw new ServiceException("仅正式合同且审批通过允许发起变更");
|
||||
}
|
||||
}
|
||||
|
||||
private ContractChange findLatestByStatuses(Long contractId, List<String> statuses) {
|
||||
return getOne(Wrappers.<ContractChange>lambdaQuery()
|
||||
.eq(ContractChange::getIsDeleted, 0)
|
||||
.eq(ContractChange::getContractId, contractId)
|
||||
.in(ContractChange::getApprovalStatus, statuses)
|
||||
.orderByDesc(ContractChange::getCreateTime)
|
||||
.last("limit 1"), false);
|
||||
}
|
||||
|
||||
private void validateDraft(ContractChange contractChange) {
|
||||
TransportBusinessSupport.validateRequired(contractChange.getChangeType(), "请选择变更类型");
|
||||
if (!List.of(CHANGE_TYPE_INFO, CHANGE_TYPE_SETTLEMENT).contains(contractChange.getChangeType())) {
|
||||
throw new ServiceException("请选择变更类型");
|
||||
}
|
||||
TransportBusinessSupport.validateLength(contractChange.getChangeReason(), 500, "变更原因不能超过500个字");
|
||||
TransportBusinessSupport.validateLength(contractChange.getChangeContent(), 2000, "变更内容不能超过2000个字");
|
||||
}
|
||||
|
||||
private void validateSubmit(ContractChange contractChange) {
|
||||
validateDraft(contractChange);
|
||||
TransportBusinessSupport.validateRequired(contractChange.getChangeReason(), "请输入变更原因");
|
||||
if (Objects.equals(contractChange.getChangeType(), CHANGE_TYPE_SETTLEMENT)) {
|
||||
return;
|
||||
}
|
||||
TransportBusinessSupport.validateRequired(contractChange.getContractName(), "请输入合同名称");
|
||||
TransportBusinessSupport.validateRequired(contractChange.getSettlementCurrency(), "请选择结算币种");
|
||||
if (contractChange.getContractAmount() != null && contractChange.getContractAmount().compareTo(BigDecimal.ZERO) < 0) {
|
||||
throw new ServiceException("合同金额不能小于0");
|
||||
}
|
||||
}
|
||||
|
||||
private String resolveApprovalNode(ContractChange contractChange) {
|
||||
return Func.isBlank(contractChange.getChangeType()) ? "合同变更审批" : contractChange.getChangeType() + "审批";
|
||||
}
|
||||
|
||||
private synchronized String nextChangeNo() {
|
||||
return "HTBG" + LocalDate.now().format(CODE_DATE) + String.format("%06d", count() + 1);
|
||||
}
|
||||
|
||||
private ContractChange loadExists(Long id) {
|
||||
if (Func.isEmpty(id)) {
|
||||
throw new ServiceException("主键不能为空");
|
||||
}
|
||||
ContractChange contractChange = getById(id);
|
||||
if (Func.isEmpty(contractChange) || Objects.equals(contractChange.getIsDeleted(), 1)) {
|
||||
throw new ServiceException("合同变更不存在");
|
||||
}
|
||||
return contractChange;
|
||||
}
|
||||
|
||||
private ContractChange loadEditable(Long id) {
|
||||
ContractChange contractChange = loadExists(id);
|
||||
if (!canCurrentUserOperate(contractChange)) {
|
||||
throw new ServiceException("无权操作其他组织合同变更");
|
||||
}
|
||||
if (!List.of(STATUS_DRAFT, STATUS_WITHDRAWN, STATUS_REJECTED).contains(contractChange.getApprovalStatus())) {
|
||||
throw new ServiceException("当前状态不允许编辑");
|
||||
}
|
||||
return contractChange;
|
||||
}
|
||||
|
||||
private ContractChange loadReviewing(Long id) {
|
||||
ContractChange contractChange = loadExists(id);
|
||||
if (!Objects.equals(contractChange.getApprovalStatus(), STATUS_REVIEWING)) {
|
||||
throw new ServiceException("仅审批中的合同变更允许该操作");
|
||||
}
|
||||
return contractChange;
|
||||
}
|
||||
|
||||
private boolean canCurrentUserOperate(ContractChange contractChange) {
|
||||
if (TransportBusinessSupport.isAdministrator()) {
|
||||
return true;
|
||||
}
|
||||
Long currentUserId = AuthUtil.getUserId();
|
||||
if (Objects.equals(contractChange.getCreateUser(), currentUserId)
|
||||
|| Objects.equals(contractChange.getHandlerUserId(), currentUserId)) {
|
||||
return true;
|
||||
}
|
||||
Long currentDeptId = TransportBusinessSupport.currentDeptId("合同变更");
|
||||
return currentDeptId != null && Objects.equals(contractChange.getOrganizationId(), currentDeptId);
|
||||
}
|
||||
|
||||
private void fillReadonly(ContractChangeVO contractChangeVO) {
|
||||
contractChangeVO.setReadonly(!canCurrentUserOperate(contractChangeVO));
|
||||
}
|
||||
|
||||
}
|
||||
+96
-7
@@ -41,6 +41,7 @@ import org.springblade.transport.constant.HcsSyncConstant;
|
||||
import org.springblade.transport.excel.ContractManageExcel;
|
||||
import org.springblade.transport.mapper.ContractManageMapper;
|
||||
import org.springblade.transport.mapper.HcsContractExeStageMapper;
|
||||
import org.springblade.transport.pojo.entity.ContractChange;
|
||||
import org.springblade.transport.pojo.entity.ContractManage;
|
||||
import org.springblade.transport.pojo.entity.HcsContractExeStage;
|
||||
import org.springblade.transport.pojo.vo.ContractManageVO;
|
||||
@@ -341,6 +342,95 @@ public class ContractManageServiceImpl extends BaseServiceImpl<ContractManageMap
|
||||
return updateById(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean applyChangeFromRecord(ContractChange change) {
|
||||
if (change == null || Func.isEmpty(change.getContractId())) {
|
||||
throw new ServiceException("合同变更单无效");
|
||||
}
|
||||
ContractManage source = loadExists(change.getContractId());
|
||||
if (!Objects.equals(source.getContractStage(), STAGE_FORMAL)
|
||||
|| !List.of(STATUS_APPROVED, STATUS_CHANGE_APPROVED).contains(source.getApprovalStatus())) {
|
||||
throw new ServiceException("当前合同状态不允许回写变更");
|
||||
}
|
||||
String changeType = resolveChangeType(change.getChangeType());
|
||||
boolean settlementRuleOnly = Objects.equals(changeType, CHANGE_TYPE_SETTLEMENT);
|
||||
String changeReason = TransportBusinessSupport.trimToNull(change.getChangeReason());
|
||||
TransportBusinessSupport.validateLength(changeReason, 500, "变更原因不能超过500字");
|
||||
ContractManage request = toContractManageRequest(change);
|
||||
validateBillingPlans(request.getBillingPlanJson());
|
||||
Map<String, Object> beforeData = buildContractChangeSnapshot(source);
|
||||
if (settlementRuleOnly) {
|
||||
applySettlementRuleChange(source, request);
|
||||
} else {
|
||||
applyContractInfoChange(source, request);
|
||||
}
|
||||
Map<String, Object> afterData = buildContractChangeSnapshot(source);
|
||||
retainChangedSnapshotFields(beforeData, afterData);
|
||||
source.setChangeContent(TransportBusinessSupport.trimToNull(change.getChangeContent()));
|
||||
source.setChangeReason(changeReason);
|
||||
source.setChangeAttachmentsJson(TransportBusinessSupport.trimToNull(change.getChangeAttachmentsJson()));
|
||||
appendChangeRecord(source, changeType, changeReason, STATUS_CHANGE_APPROVED, "变更审批通过", beforeData, afterData);
|
||||
source.setAttachmentsJson(mergeAttachmentJson(source.getAttachmentsJson(), source.getChangeAttachmentsJson()));
|
||||
source.setChangeAttachmentsJson(null);
|
||||
source.setChangeContent(null);
|
||||
source.setChangeReason(null);
|
||||
source.setContractFileJson(markContractFilesApproved(source.getContractFileJson()));
|
||||
refreshArchiveStatusOnApprove(source);
|
||||
source.setApprovalStatus(STATUS_CHANGE_APPROVED);
|
||||
source.setCurrentNode("变更审批通过");
|
||||
String processor = TransportBusinessSupport.trimToNull(AuthUtil.getUserName());
|
||||
source.setCurrentProcessor(processor == null ? "系统" : processor);
|
||||
source.setApprovedTime(LocalDateTime.now());
|
||||
source.setHcsSyncStatus(HcsSyncConstant.HCS_STATUS_UNSYNCED);
|
||||
contractExeStageService.createDefaultRowOnApprove(source);
|
||||
hcsContractExeStageMapper.update(null, Wrappers.<HcsContractExeStage>lambdaUpdate()
|
||||
.eq(HcsContractExeStage::getContractId, source.getId())
|
||||
.isNull(HcsContractExeStage::getHcsStageFdId)
|
||||
.set(HcsContractExeStage::getRowOp, "add"));
|
||||
return updateById(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将变更单可回写字段映射为临时 ContractManage,供 apply*Change 复用。
|
||||
*/
|
||||
private ContractManage toContractManageRequest(ContractChange change) {
|
||||
ContractManage request = new ContractManage();
|
||||
request.setChangeType(change.getChangeType());
|
||||
request.setChangeContent(change.getChangeContent());
|
||||
request.setChangeReason(change.getChangeReason());
|
||||
request.setChangeAttachmentsJson(change.getChangeAttachmentsJson());
|
||||
request.setSignType(change.getSignType());
|
||||
request.setContractNo(change.getContractNo());
|
||||
request.setContractName(change.getContractName());
|
||||
request.setPartyB(change.getPartyB());
|
||||
request.setStartDate(change.getStartDate());
|
||||
request.setEndDate(change.getEndDate());
|
||||
request.setContractFormat(change.getContractFormat());
|
||||
request.setSettlementMode(change.getSettlementMode());
|
||||
request.setLegalSealFlag(change.getLegalSealFlag());
|
||||
request.setCopyCount(change.getCopyCount());
|
||||
request.setSettlementCurrency(change.getSettlementCurrency());
|
||||
request.setInvoiceCycle(change.getInvoiceCycle());
|
||||
request.setPaymentDays(change.getPaymentDays());
|
||||
request.setContractAmount(change.getContractAmount());
|
||||
request.setTemplateFlag(change.getTemplateFlag());
|
||||
request.setOriginalContractNo(change.getOriginalContractNo());
|
||||
request.setElectronicSealFlag(change.getElectronicSealFlag());
|
||||
request.setRemark(change.getRemark());
|
||||
request.setMainContent(change.getMainContent());
|
||||
request.setBillingEnabled(change.getBillingEnabled());
|
||||
request.setFeeGenerationMode(change.getFeeGenerationMode());
|
||||
request.setBillingPlanJson(change.getBillingPlanJson());
|
||||
request.setSettlementRuleJson(change.getSettlementRuleJson());
|
||||
request.setPreSettlementConfigJson(change.getPreSettlementConfigJson());
|
||||
request.setFormalSettlementConfigJson(change.getFormalSettlementConfigJson());
|
||||
request.setPaymentRatioJson(change.getPaymentRatioJson());
|
||||
request.setContractFileJson(change.getContractFileJson());
|
||||
request.setAttachmentsJson(change.getAttachmentsJson());
|
||||
return request;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析并校验合同变更类型,兼容历史未传类型的请求。
|
||||
*/
|
||||
@@ -358,7 +448,7 @@ public class ContractManageServiceImpl extends BaseServiceImpl<ContractManageMap
|
||||
/**
|
||||
* 结算规则变更:仅允许更新计费信息与结算单规则。
|
||||
*/
|
||||
private void applySettlementRuleChange(ContractManage source, ContractManage request) {
|
||||
void applySettlementRuleChange(ContractManage source, ContractManage request) {
|
||||
source.setBillingEnabled(request.getBillingEnabled());
|
||||
source.setFeeGenerationMode(request.getFeeGenerationMode());
|
||||
source.setBillingPlanJson(request.getBillingPlanJson());
|
||||
@@ -370,7 +460,7 @@ public class ContractManageServiceImpl extends BaseServiceImpl<ContractManageMap
|
||||
/**
|
||||
* 合同信息变更:更新合同基本信息、计费/结算规则、付款比例及附件。
|
||||
*/
|
||||
private void applyContractInfoChange(ContractManage source, ContractManage request) {
|
||||
void applyContractInfoChange(ContractManage source, ContractManage request) {
|
||||
TransportBusinessSupport.validateRequired(request.getSettlementCurrency(), "请选择结算币种");
|
||||
ContractManage candidate = new ContractManage();
|
||||
BeanUtil.copyProperties(source, candidate);
|
||||
@@ -379,6 +469,7 @@ public class ContractManageServiceImpl extends BaseServiceImpl<ContractManageMap
|
||||
validatePaymentRatios(request.getPaymentRatioJson());
|
||||
applyContractNo(source, request.getContractNo(), false);
|
||||
source.setContractName(request.getContractName());
|
||||
source.setSignType(request.getSignType());
|
||||
source.setPartyB(request.getPartyB());
|
||||
source.setStartDate(request.getStartDate());
|
||||
source.setEndDate(request.getEndDate());
|
||||
@@ -399,11 +490,6 @@ public class ContractManageServiceImpl extends BaseServiceImpl<ContractManageMap
|
||||
normalizeOptionalIntegerFields(source);
|
||||
validateContractAmountRequired(source);
|
||||
validateAdditionalFields(source);
|
||||
source.setBillingPlanJson(request.getBillingPlanJson()); source.setSettlementRuleJson(request.getSettlementRuleJson()); source.setPreSettlementConfigJson(request.getPreSettlementConfigJson()); source.setFormalSettlementConfigJson(request.getFormalSettlementConfigJson()); source.setPaymentRatioJson(request.getPaymentRatioJson());
|
||||
source.setContractFileJson(request.getContractFileJson()); source.setAttachmentsJson(request.getAttachmentsJson());
|
||||
source.setChangeAttachmentsJson(TransportBusinessSupport.trimToNull(request.getChangeAttachmentsJson()));
|
||||
// 高风险/黑名单客商管控:变更提交同样必须携带特批附件(与新增/暂存/转正式一致,外部客商,内部组织默认无风险)
|
||||
validateSpecExplanationOnSubmit(source);
|
||||
source.setBillingPlanJson(request.getBillingPlanJson());
|
||||
source.setSettlementRuleJson(request.getSettlementRuleJson());
|
||||
source.setPreSettlementConfigJson(request.getPreSettlementConfigJson());
|
||||
@@ -411,6 +497,9 @@ public class ContractManageServiceImpl extends BaseServiceImpl<ContractManageMap
|
||||
source.setPaymentRatioJson(request.getPaymentRatioJson());
|
||||
source.setContractFileJson(request.getContractFileJson());
|
||||
source.setAttachmentsJson(request.getAttachmentsJson());
|
||||
source.setChangeAttachmentsJson(TransportBusinessSupport.trimToNull(request.getChangeAttachmentsJson()));
|
||||
// 高风险/黑名单客商管控:变更提交同样必须携带特批附件(与新增/暂存/转正式一致,外部客商,内部组织默认无风险)
|
||||
validateSpecExplanationOnSubmit(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.transport.wrapper;
|
||||
|
||||
import org.springblade.core.mp.support.BaseEntityWrapper;
|
||||
import org.springblade.core.tool.utils.BeanUtil;
|
||||
import org.springblade.system.cache.UserCache;
|
||||
import org.springblade.transport.pojo.entity.ContractChange;
|
||||
import org.springblade.transport.pojo.vo.ContractChangeVO;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 合同变更包装类
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public class ContractChangeWrapper extends BaseEntityWrapper<ContractChange, ContractChangeVO> {
|
||||
|
||||
public static ContractChangeWrapper build() {
|
||||
return new ContractChangeWrapper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContractChangeVO entityVO(ContractChange contractChange) {
|
||||
ContractChangeVO contractChangeVO = Objects.requireNonNull(BeanUtil.copyProperties(contractChange, ContractChangeVO.class));
|
||||
contractChangeVO.setCreateUserName(UserCache.getUserRealName(contractChange.getCreateUser()));
|
||||
contractChangeVO.setUpdateUserName(UserCache.getUserRealName(contractChange.getUpdateUser()));
|
||||
contractChangeVO.setApprovalStatusName(statusName(contractChange.getApprovalStatus()));
|
||||
contractChangeVO.setSyncStatusName(syncStatusName(contractChange.getSyncStatus()));
|
||||
return contractChangeVO;
|
||||
}
|
||||
|
||||
private String statusName(String status) {
|
||||
if (status == null) {
|
||||
return "未知";
|
||||
}
|
||||
return switch (status) {
|
||||
case "draft" -> "草稿";
|
||||
case "reviewing" -> "审批中";
|
||||
case "withdrawn" -> "已撤回";
|
||||
case "approved" -> "审批通过";
|
||||
case "rejected" -> "已驳回";
|
||||
default -> "未知";
|
||||
};
|
||||
}
|
||||
|
||||
private String syncStatusName(String syncStatus) {
|
||||
if (syncStatus == null || syncStatus.isBlank()) {
|
||||
return "";
|
||||
}
|
||||
return switch (syncStatus) {
|
||||
case "unsynced" -> "待推送";
|
||||
case "synced" -> "已推送";
|
||||
case "failed" -> "推送失败";
|
||||
default -> syncStatus;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
-- 合同变更独立单据 + 菜单
|
||||
-- 审批通过后再回写 blade_contract_manage
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `blade_contract_change` (
|
||||
`id` bigint(20) NOT NULL COMMENT '主键',
|
||||
`tenant_id` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '000000' COMMENT '租户ID',
|
||||
`create_user` bigint(20) DEFAULT NULL COMMENT '创建人',
|
||||
`create_dept` bigint(20) DEFAULT NULL COMMENT '创建部门',
|
||||
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||
`update_user` bigint(20) DEFAULT NULL COMMENT '修改人',
|
||||
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
|
||||
`status` int(11) DEFAULT '1' COMMENT '状态',
|
||||
`is_deleted` int(11) DEFAULT '0' COMMENT '是否已删除',
|
||||
`contract_id` bigint(20) NOT NULL COMMENT '原合同ID',
|
||||
`change_no` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '变更编号',
|
||||
`change_type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '变更类型',
|
||||
`change_date` date DEFAULT NULL COMMENT '变更日期',
|
||||
`change_content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '变更内容',
|
||||
`change_reason` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '变更原因',
|
||||
`change_attachments_json` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '变更附件JSON',
|
||||
`before_data_json` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '变更前快照JSON',
|
||||
`contract_no` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '合同编号',
|
||||
`contract_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '合同名称',
|
||||
`project_id` bigint(20) DEFAULT NULL COMMENT '所属项目ID',
|
||||
`project_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '所属项目',
|
||||
`organization_id` bigint(20) DEFAULT NULL COMMENT '合同负责部门ID',
|
||||
`organization_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '合同负责部门',
|
||||
`contract_category` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '合同类别',
|
||||
`sign_type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '签约类型',
|
||||
`party_a` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '甲方',
|
||||
`party_b` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '乙方',
|
||||
`start_date` date DEFAULT NULL COMMENT '开始日期',
|
||||
`end_date` date DEFAULT NULL COMMENT '结束日期',
|
||||
`temporary_start_date` date DEFAULT NULL COMMENT '临时效力起',
|
||||
`temporary_end_date` date DEFAULT NULL COMMENT '临时效力止',
|
||||
`handler_user_id` bigint(20) DEFAULT NULL COMMENT '经办人ID',
|
||||
`handler_user_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '经办人',
|
||||
`sign_date` date DEFAULT NULL COMMENT '签订日期',
|
||||
`apply_date` date DEFAULT NULL COMMENT '申请日期',
|
||||
`settlement_mode` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '结算方式',
|
||||
`contract_format` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '合同格式',
|
||||
`legal_seal_flag` int(11) DEFAULT NULL COMMENT '是否需要加盖法人章',
|
||||
`copy_count` int(11) DEFAULT NULL COMMENT '一式份数',
|
||||
`settlement_currency` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '结算币种',
|
||||
`invoice_cycle` int(11) DEFAULT NULL COMMENT '开票周期(天)',
|
||||
`payment_days` int(11) DEFAULT NULL COMMENT '回款账期(天)',
|
||||
`contract_amount` decimal(18,2) DEFAULT NULL COMMENT '合同金额',
|
||||
`template_flag` int(11) DEFAULT NULL COMMENT '是否范本',
|
||||
`original_contract_no` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '原件合同编号',
|
||||
`electronic_seal_flag` int(11) DEFAULT NULL COMMENT '是否电子章',
|
||||
`billing_enabled` int(11) DEFAULT NULL COMMENT '计费信息开关',
|
||||
`fee_generation_mode` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '费用生成模式',
|
||||
`contract_file_json` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '合同主文件JSON',
|
||||
`attachments_json` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '其它附件JSON',
|
||||
`billing_plan_json` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '计费方案JSON',
|
||||
`settlement_rule_json` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '结算生成规则JSON',
|
||||
`pre_settlement_config_json` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '预结算配置JSON',
|
||||
`formal_settlement_config_json` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '正式结算配置JSON',
|
||||
`payment_ratio_json` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '付款比例设置JSON',
|
||||
`reconciliation_json` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '对账配置JSON',
|
||||
`main_content` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '合同主要内容',
|
||||
`remark` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '其他事项说明',
|
||||
`hcs_risk_level` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '合规客商风险等级(展示用)',
|
||||
`hcs_black_status` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '合规客商黑名单状态(展示用)',
|
||||
`approval_status` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '审批状态',
|
||||
`current_node` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '当前节点',
|
||||
`current_processor` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '当前处理人',
|
||||
`approved_time` datetime DEFAULT NULL COMMENT '审核通过时间',
|
||||
`sync_status` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '同步状态 unsynced/synced/failed',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
KEY `idx_contract_change_contract` (`contract_id`) USING BTREE,
|
||||
KEY `idx_contract_change_status` (`approval_status`) USING BTREE,
|
||||
KEY `idx_contract_change_type` (`change_type`) USING BTREE,
|
||||
KEY `idx_contract_change_create_time` (`create_time`) USING BTREE,
|
||||
KEY `idx_contract_change_no` (`change_no`) USING BTREE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='合同变更';
|
||||
|
||||
-- 菜单:合同管理下增加「合同变更」
|
||||
INSERT IGNORE INTO `blade_menu` (`id`, `parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `component`, `remark`, `is_deleted`) VALUES
|
||||
(2110000000000000200, 2110000000000000000, 'contract_change', '合同变更', 'contract_change', '/business/contract-change', 'iconfont icon-caidanguanli', 20, 1, 0, 1, NULL, '', 0),
|
||||
(2110000000000000201, 2110000000000000200, 'contract_change_view', '查看', 'contract_change_view', '', '', 1, 2, 0, 1, NULL, '', 0),
|
||||
(2110000000000000202, 2110000000000000200, 'contract_change_add', '新增', 'contract_change_add', '', '', 2, 2, 0, 1, NULL, '', 0),
|
||||
(2110000000000000203, 2110000000000000200, 'contract_change_edit', '编辑', 'contract_change_edit', '', '', 3, 2, 0, 1, NULL, '', 0),
|
||||
(2110000000000000204, 2110000000000000200, 'contract_change_delete', '删除', 'contract_change_delete', '', '', 4, 2, 0, 1, NULL, '', 0),
|
||||
(2110000000000000205, 2110000000000000200, 'contract_change_submit', '提交', 'contract_change_submit', '', '', 5, 2, 0, 1, NULL, '', 0),
|
||||
(2110000000000000206, 2110000000000000200, 'contract_change_withdraw', '撤回', 'contract_change_withdraw', '', '', 6, 2, 0, 1, NULL, '', 0),
|
||||
(2110000000000000207, 2110000000000000200, 'contract_change_approve', '审批通过', 'contract_change_approve', '', '', 7, 2, 0, 1, NULL, '', 0),
|
||||
(2110000000000000208, 2110000000000000200, 'contract_change_reject', '审批驳回', 'contract_change_reject', '', '', 8, 2, 0, 1, NULL, '', 0);
|
||||
|
||||
-- 业务字典 mk_template:提交合同变更审核流(dict_key 需按实际 MK 模板编码配置)
|
||||
INSERT IGNORE INTO `blade_dict_biz` (`id`, `tenant_id`, `parent_id`, `code`, `dict_key`, `dict_value`, `sort`, `remark`, `is_sealed`, `status`, `is_deleted`)
|
||||
SELECT 2110000000000000299, '000000', id, 'mk_template', 'CONTRACT_CHANGE_TEMPLATE', '提交合同变更审核流', 99, '合同变更MK模板编码,请替换为真实 templateCode', 0, 1, 0
|
||||
FROM `blade_dict_biz`
|
||||
WHERE `code` = 'mk_template' AND `parent_id` = 0 AND `is_deleted` = 0
|
||||
LIMIT 1;
|
||||
Reference in New Issue
Block a user