功能完善

This commit is contained in:
2026-05-29 15:25:25 +08:00
parent 4721490132
commit a4c9c4c919
28 changed files with 3318 additions and 4 deletions
@@ -7,7 +7,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan({
"com.nbport.zgwl.mapper",
"com.nbport.zgwl.partner.mapper",
"com.nbport.zgwl.manifest.mapper"
"com.nbport.zgwl.manifest.mapper",
"com.nbport.zgwl.contractlaunch.mapper"
})
@SpringBootApplication
public class ZgwlEndApplication {
@@ -0,0 +1,268 @@
package com.nbport.zgwl.contractlaunch.controller;
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.ContractLaunchDto;
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchQueryDto;
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchSealDto;
import com.nbport.zgwl.contractlaunch.service.ContractLaunchService;
import com.nbport.zgwl.contractlaunch.utils.ContractLaunchConstants;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
/**
* 合同发起 Controller
*
* 这里除了正常 CRUD,还额外提供了几类“测试按钮”接口:
* 1. 模拟法务审批通过 / 驳回
* 2. 模拟合同采集
* 3. 合同归档
* 4. 回写签章结果
*
* 这些测试接口在法务系统不可用期间便于你完整演示流程,
* 后续接入真实系统后,保留或删除都很方便。
*/
@RestController
@RequiredArgsConstructor
@RequestMapping(ContractLaunchConstants.REQUEST_PREFIX)
public class ContractLaunchController {
private final ContractLaunchService contractLaunchService;
/**
* 分页查询合同列表。
*
* 支持按合同名称、合同编号、合同类型、状态、创建时间范围过滤。
* 返回结果附带合同方摘要、文件列表、履行计划(不含日志,列表页日志量大)。
*
* 对应前端功能:合同列表页
*
* 请求体 ContractLaunchQueryDto 字段:
* contractName - 合同名称(模糊)
* contractCode - 合同编号
* contractType - 合同类型
* status - 状态(draft/reviewing/rejected/pending_sign/signing/...
* dateStart - 创建时间范围-开始(yyyy-MM-dd
* dateEnd - 创建时间范围-结束(yyyy-MM-dd
*/
@PostMapping("/list")
public R<PageResult<ContractLaunchDto>> queryList(@RequestBody ContractLaunchQueryDto queryDto) {
return R.success(contractLaunchService.queryPage(queryDto));
}
/**
* 查询合同详情(含所有子表数据)。
*
* 返回合同基本信息 + 合同方列表 + 文件列表 + 履行计划 + 操作日志。
*
* 对应前端功能:合同详情页 / 编辑页面回显
*/
@GetMapping("/{id}")
public R<ContractLaunchDto> getDetail(@PathVariable("id") Long id) {
return R.success(contractLaunchService.getDetail(id));
}
/**
* 创建合同草稿。
*
* 流程:生成 contractSysIdCLS-xxx)和 contractCode → 保存主表 → 保存子表(合同方/文件/履行计划)→ 记录操作日志
* 状态变为:draft(草稿)
*
* 必填校验项:合同名称、合同类型、合同类型编码、计价方式、币种、签订方式、合同期限类型、至少一个甲方+乙方
*
* 对应前端功能:新建合同 → 保存草稿
*/
@PostMapping
public R<ContractLaunchDto> createDraft(@RequestBody ContractLaunchDto contract) {
return R.success(contractLaunchService.createDraft(contract));
}
/**
* 编辑合同草稿。
*
* 仅 draft(草稿)或 rejected(已驳回)状态允许编辑。
* 逻辑:先删子表旧数据,再以当前数据重新插入(替换式更新)。
* 保留原有的 contractSysId、contractCode、创建人/创建时间 不变。
*
* 对应前端功能:编辑草稿 → 保存
*/
@PutMapping
public R<ContractLaunchDto> updateDraft(@RequestBody ContractLaunchDto contract) {
return R.success(contractLaunchService.updateDraft(contract));
}
/**
* 提交法务审批。
*
* 状态流转:draft/rejected → reviewing
* 调用结算平台 pushContract 接口将合同数据推送给法务系统开始审批流程。
* 目前法务接口不可用,仅做状态变更 + 记录日志(TODO:联调时打开 settlementPushService.pushContract 调用)。
*
* 推送法务的报文包含:合同基本字段 + contractOpposites(相对方) + contractKxPlans(履行计划) + 附件等
*
* 对应前端功能:提交审批按钮
*/
@PostMapping("/{id}/submit")
public R<ContractLaunchDto> submitToLaw(@PathVariable("id") Long id) {
return R.success(contractLaunchService.submitToLaw(id));
}
/**
* 【测试按钮】模拟法务审批通过。
*
* 状态流转:reviewing → pending_sign(待签署)
* 生成模拟的 lawContractCode 和 lawContractId 记录到合同上,以便后续流程使用。
* 可在请求体中传入 approveMessage(审批意见)、lawContractCode、lawContractId 覆盖自动生成的值。
*
* 真实场景下,此方法应由法务系统的回调接口替代(见 lawApproveCallback)。
*
* 对应前端功能:测试按钮 → 模拟审批通过
*/
@PostMapping("/{id}/mock-approve")
public R<ContractLaunchDto> mockApprove(@PathVariable("id") Long id,
@RequestBody(required = false) ContractLaunchApproveDto approveDto) {
return R.success(contractLaunchService.mockApprove(id, approveDto));
}
/**
* 【测试按钮】模拟法务审批驳回。
*
* 状态流转:reviewing → rejected(已驳回)
* 可在请求体中传入 approveMessage(驳回原因)。
* 驳回后合同可再次编辑和提交。
*
* 对应前端功能:测试按钮 → 模拟驳回
*/
@PostMapping("/{id}/mock-reject")
public R<ContractLaunchDto> mockReject(@PathVariable("id") Long id,
@RequestBody(required = false) ContractLaunchApproveDto approveDto) {
return R.success(contractLaunchService.mockReject(id, approveDto));
}
/**
* 法务审批结果回调入口(供法务系统调用)。
*
* submitToLaw 时推给法务的 pushUrl 默认指向此接口:POST /contract/launch/callback/law/approve
* 法务审批完成后,会往 pushUrl POST 审批结果。
*
* 当前法务接口不可用,但此回调接口已预先实现,可接受测试请求验证流程。
* 请求体使用 Map 接收以兼容不同版本的字段名,内部通过 getFirstText 按多个 key 依次尝试提取。
*
* 识别合同方式:从报文中取 contractSysId 定位到本系统的合同
* 判断通过/驳回:从 approveStatus/status/result 等多个字段名中取值判断
*
* 状态流转:reviewing → pending_sign(通过) / rejected(驳回)
*
* 对应前端功能:法务系统审批完成后自动回调(目前用法务系统暂未对接)
*/
@PostMapping("/callback/law/approve")
public R<ContractLaunchDto> lawApproveCallback(@RequestBody Map<String, Object> callbackPayload) {
return R.success(contractLaunchService.handleLawApproveCallback(callbackPayload));
}
/**
* 签署发起回调(浙江CA安全签调用)。
*
* 在浙江CA安全签平台创建签署合同后,回写 sealContractId 到本系统合同。
* 状态流转:pending_sign → signing(签署中)
*
* 请求体 ContractLaunchSealDto 字段:
* sealContractId - 签章平台生成的合同ID(必填)
* sealContractStatus - 签署状态(1:签署中)
*
* 对应前端功能:调起浙江CA签署后,回写签章合同ID
*/
@PostMapping("/{id}/seal/save")
public R<ContractLaunchDto> saveSealInfo(@PathVariable("id") Long id,
@RequestBody ContractLaunchSealDto sealDto) {
return R.success(contractLaunchService.saveSealInfo(id, sealDto));
}
/**
* 签署完成回调(浙江CA安全签/线下签署完成后调用)。
*
* 所有签署方完成签署后,将签署完成的合同文件信息回写。
* 状态流转:signing → pending_collect(待采集)
*
* 请求体 ContractLaunchSealDto 字段:
* sealContractStatus - 签署状态(2:签署完成)
* signedFileName - 签署完成后的文件名
* signedFilePath - 签署文件存储路径
* signedFileType - 文件类型
* signedFileSize - 文件大小
* signedOfflineReason - 线下签署原因(如果未在线签署)
*
* 签署文件会自动保存到 file 子表(fileCategory = "signed"),先删旧签署文件再插入新的。
*
* 对应前端功能:签署完成 → 回写签署结果
*/
@PostMapping("/{id}/seal/finish")
public R<ContractLaunchDto> finishSeal(@PathVariable("id") Long id,
@RequestBody ContractLaunchSealDto sealDto) {
return R.success(contractLaunchService.markSealCompleted(id, sealDto));
}
/**
* 【测试按钮】模拟合同采集。
*
* 合同签署完成后,调用数据采集 V3.0 的 collectContract 接口将合同信息推送到法务系统存档。
* 目前法务接口不可用,仅做状态变更 + 记录日志(TODO:联调时打开 dataCollectionPushService.collectContract 调用)。
*
* 状态流转:pending_collect → pending_archive(待归档)
*
* 推送数据采集的报文包含:合同基本字段 + 用印信息(c_seal)+ 签订信息(c_sign+ 附件等
*
* 对应前端功能:测试按钮 → 模拟采集
*/
@PostMapping("/{id}/mock-collect")
public R<ContractLaunchDto> mockCollect(@PathVariable("id") Long id) {
return R.success(contractLaunchService.mockCollect(id));
}
/**
* 合同归档。
*
* 合同全生命周期最后一步,状态变为 completed(已完成)。
* 同时将归档信息推送到法务系统存档(TODO:联调时打开 settlementPushService.pushArchive 调用)。
*
* 请求体 ContractLaunchArchiveDto 字段:
* archiveKeeper - 档案保管人手机号
* archiveKeeperUnit - 档案保管单位名称
* archiveKeeperUnitCode - 档案保管单位编码
* archiveFiles - 归档附件列表
*
* 归档附件自动保存到 file 子表(fileCategory = "archive")。
*
* 对应前端功能:归档按钮 → 合同完结
*/
@PostMapping("/{id}/archive")
public R<ContractLaunchDto> archive(@PathVariable("id") Long id,
@RequestBody(required = false) ContractLaunchArchiveDto archiveDto) {
return R.success(contractLaunchService.archive(id, archiveDto));
}
/**
* 删除合同草稿(逻辑删除)。
*
* 仅 draft(草稿)或 rejected(已驳回)状态允许删除。
* 逻辑:设置 isDeleted = 'Y',不物理删除数据。
*
* 对应前端功能:删除草稿按钮
*/
@DeleteMapping("/{id}")
public R<String> deleteDraft(@PathVariable("id") Long id) {
contractLaunchService.deleteDraft(id);
return R.success("删除成功");
}
}
@@ -0,0 +1,34 @@
package com.nbport.zgwl.contractlaunch.dto;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 模拟审批 / 驳回参数
*
* 当前法务接口不可用,通过「测试按钮」手动审批时携带此参数。
* 真实联调后,此 DTO 可由法务回调接口的报文替代。
*/
@Data
public class ContractLaunchApproveDto implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/** 审批意见 */
private String approveMessage;
/**
* 法务回调返回的合同编号。
* 模拟时自动生成,真实联调时由法务系统返回。
*/
private String lawContractCode;
/**
* 法务回调返回的合同ID。
* 模拟时自动生成,真实联调时由法务系统返回。
*/
private String lawContractId;
}
@@ -0,0 +1,30 @@
package com.nbport.zgwl.contractlaunch.dto;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* 合同归档参数
*/
@Data
public class ContractLaunchArchiveDto implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/** 档案保管人手机号 */
private String archiveKeeper;
/** 档案保管单位名称 */
private String archiveKeeperUnit;
/** 档案保管单位编码 */
private String archiveKeeperUnitCode;
/** 归档附件列表(纸质或电子档案材料) */
private List<ContractLaunchFileDto> archiveFiles = new ArrayList<>();
}
@@ -0,0 +1,359 @@
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;
import java.util.ArrayList;
import java.util.List;
/**
* 合同发起主对象
*
* 这里尽量把前后端会直接用到的字段都放在一个 DTO 里,
* 方便你后续排查和修改,不做过深的分层。
*/
@Data
public class ContractLaunchDto implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
// ==================== 主键与编号 ====================
/** 主键ID */
private Long id;
/** 合同系统唯一编码(本系统生成,格式 CLS-时间戳-随机数) */
private String contractSysId;
/** 业务合同编号(如 MM-20260522-1234,前端可手动输入,不传则自动生成) */
private String contractCode;
/** 法务系统生成的合同编号(审批通过后法务返回) */
private String lawContractCode;
/** 法务系统返回的合同ID(审批通过后法务返回) */
private String lawContractId;
// ==================== 合同基本信息 ====================
/** 合同名称 */
private String contractName;
/** 合同类型中文名(如 买卖合同、服务合同) */
private String contractType;
/** 合同类型编码(如 MM/GY/ZL,见文档附录字典) */
private String contractTypeCode;
/** 合同来源(ECP:结算平台, DSSP:大宗平台) */
private String contractSource;
/** 创建方式(template:从模板创建, manual:手动创建) */
private String creationMode;
/** 选择的模板ID */
private Long templateId;
/** 选择的模板编号 */
private String templateCode;
/** 选择的模板名称 */
private String templateName;
// ==================== 流程状态 ====================
/**
* 合同状态流转:
* draft → reviewing → (approved→pending_sign / rejected)
* pending_sign → signing → pending_collect → pending_archive → completed
*/
private String status;
/** 审批状态(pending:待审批, approved:已通过, rejected:已驳回) */
private String approveStatus;
/** 审批意见/消息 */
private String approveMessage;
// ==================== 签章状态 ====================
/** 签章平台合同ID(浙江CA安全签创建后返回) */
private String sealContractId;
/** 签章状态(1:签署中, 2:签署完成, 3:签署失败, null:未发起) */
private Integer sealContractStatus;
// ==================== 金额与币种 ====================
/** 合同标的额(元) */
private Double contractAmount;
/** 币种(RMB/USD/HKD/EUR/IDR */
private String currencyName;
/** 合同期限类型(0:固定期限, 1:无固定期限) */
private String contractPeriodType;
/** 期限说明(无固定期限时必填) */
private String periodExplain;
/** 合同开始日期 */
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private LocalDateTime effectiveStart;
/** 合同结束日期 */
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private LocalDateTime effectiveEnd;
/** 付款方式 */
private String paymentMethod;
/** 合同主要内容 */
private String primaryContent;
/** 金额说明(计价方式为无金额时填写) */
private String amountExplain;
/** 计价方式(0:无金额, 1:固定总价, 2:预估总价, 3:无法预估总价, 4:固定单价) */
private String valuationMode;
// ==================== 签署相关 ====================
/** 签订方式(GZ:公章, HTZYZ:合同专用章, 等) */
private String sealType;
/** 文本来源(standardText:推荐文本, exampleText:示范文本, draftBySelf:自行起草, otherText:对方文本) */
private String textSource;
/** 授权方式(当签订方式为"公章/合同专用章+被授权人签字"时必填) */
private String mandateType;
/** 货类 */
private String cargoType;
/** 协助部门名称 */
private String assistDepartmentName;
/** 执行人账号(手机号) */
private String executorAccount;
/** 创建人手机号 */
private String creatorPhone;
/** 二级单位合同编码 */
private String selfCode;
/** 补录主合同编码(用于关联主合同,多个用逗号分割) */
private String mainContractCode;
/**
* 签约主体编码,推送法务字段 signingSubjectCode。
* 与 orgId 分开保存,避免被当前登录人的组织ID覆盖。
*/
private String signingSubjectCode;
/**
* 固定期间日期类型,推送法务字段 dateType:0-年,1-月,2-日
*/
private String dateType;
// ==================== 业务标识 ====================
/** 是否补录合同(1:补录, 2:非补录) */
private Integer isAddit;
/** 签署方式(0:纸质合同, 1:电子合同,默认1) */
private String isElectron;
/** 收支方向(1:付款, 2:收款, 3:收支双向, 0:无) */
private String paymentDirection;
/**
* 回调推送地址,法务审批完成后回调本系统使用。
* 真实地址后续可以由配置文件统一生成。
*/
private String pushUrl;
/** 是否重大合同(1:是, 0:否) */
private Integer isMajorContract;
/** 是否公开招标(1:是, 0:否) */
private Integer isOpenBidding;
/** 是否列入当年预算(1:是, 0:否) */
private Integer isYearBudget;
/** 是否共享(1:是, 0:否) */
private String isShare;
/** 签约主体是否涉外(1:是, 0:否) */
private String contractNature;
/** 签约主体是否涉港澳台(1:是, 0:否) */
private String isSgat;
/** 是否正常 */
private String isNormal;
/** 是否终止 */
private String isTerminated;
/** 是否单方协议(Y/N */
private String isSingleAgreement;
/** 招标编号 */
private String biddingNo;
/** 公开招标说明 */
private String openBiddingRemark;
/** 签订依据说明 */
private String contractGistRemark;
/**
* 额外金额类型,多个用逗号拼接:DJ-定金,YJ-押金,YFK-预付款,BZJ-保证金
*/
private String ewAmountType;
/** 定金金额 */
private Double djAmount;
/** 押金金额 */
private Double yjAmount;
/** 预付款金额 */
private Double yfkAmount;
/** 保证金金额 */
private Double bzjAmount;
/** 正文/摘要 */
private String bodySummary;
// ==================== 文件信息 ====================
/** 合同正文文件名 */
private String contractTextFileName;
/** 合同正文文件路径 */
private String contractTextFilePath;
/** 合同正文文件类型 */
private String contractTextFileType;
/** 合同正文文件大小(字节) */
private Long contractTextFileSize;
// ==================== 签署完成信息 ====================
/** 签署完成后的合同文件名 */
private String signedFileName;
/** 签署完成后的合同文件路径 */
private String signedFilePath;
/** 签署完成后的合同文件类型 */
private String signedFileType;
/** 签署完成后的合同文件大小(字节) */
private Long signedFileSize;
/** 未在线签署的原因(线下签署时填写) */
private String signedOfflineReason;
// ==================== 签署与归档时间 ====================
/** 签署日期 */
@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;
/** 归档日期 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime archiveDate;
/** 档案保管人手机号 */
private String archiveKeeper;
/** 档案保管单位 */
private String archiveKeeperUnit;
/** 档案保管单位编码 */
private String archiveKeeperUnitCode;
// ==================== 业务扩展字段(财务提醒) ====================
/** 开票时间(用于账单开票提醒,提前3天提醒) */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime invoiceDate;
/** 收款时间(用于应收账款提醒,提前3天提醒) */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime receiveDate;
/** 提前提醒天数 */
private Integer remindDays;
// ==================== 创建信息 ====================
/** 发起人 */
private String initiator;
/** 发起人部门 */
private String initiatorDept;
/** 公司名称(当前登录人所在公司) */
private String companyName;
/** 公司/组织编码 */
private String orgId;
/** 查询范围(personal:个人, company:公司, admin:管理员) */
private String queryScope;
/** 创建人 */
private String createBy;
/** 创建时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime createTime;
/** 更新人 */
private String updateBy;
/** 更新时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime updateTime;
/** 删除标记(N:未删除, Y:已删除) */
private String isDeleted;
/** 备注 */
private String remark;
// ==================== 子表数据(非数据库字段) ====================
/**
* 前端表格直接展示用的相对方摘要
*/
private String counterpartySummary;
/** 合同方列表(甲方/乙方/丙方等) */
private List<ContractLaunchPartyDto> partyList = new ArrayList<>();
/** 附件文件列表(正文/签订依据/其他附件/签署文件/归档文件) */
private List<ContractLaunchFileDto> fileList = new ArrayList<>();
/** 履行计划列表 */
private List<ContractLaunchPlanDto> performancePlans = new ArrayList<>();
/** 操作日志列表 */
private List<ContractLaunchLogDto> logList = new ArrayList<>();
}
@@ -0,0 +1,43 @@
package com.nbport.zgwl.contractlaunch.dto;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 合同文件信息
*/
@Data
public class ContractLaunchFileDto implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 关联合同主表 ID */
private Long contractId;
/** 文件分类:body-正文, gist-签订依据, other-其他附件, signed-签署文件, archive-归档文件 */
private String fileCategory;
/** 文件名 */
private String fileName;
/** 文件路径(上传到法务系统后返回的 path,或本系统存储路径) */
private String filePath;
/** 文件类型(docx/pdf 等) */
private String fileType;
/** 文件大小(字节) */
private Long fileSize;
/** 排序号 */
private Integer sortOrder;
/** 备注 */
private String remark;
}
@@ -0,0 +1,52 @@
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;
/**
* 合同操作日志
*/
@Data
public class ContractLaunchLogDto implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 关联合同主表 ID */
private Long contractId;
/** 操作类型(save/submit/approve/reject/seal_start/seal_finish/collect/archive/delete */
private String actionType;
/** 操作名称(中文描述,如"保存草稿"、"提交法务" */
private String actionName;
/** 操作状态(success/failed/pending */
private String actionStatus;
/** 操作人姓名 */
private String operatorName;
/** 操作人手机号 */
private String operatorPhone;
/** 操作时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime actionTime;
/** 操作内容描述 */
private String actionContent;
/** 回调/操作的原始报文(JSON 文本存储,用于追溯) */
private String callbackPayload;
/** 备注 */
private String remark;
}
@@ -0,0 +1,88 @@
package com.nbport.zgwl.contractlaunch.dto;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 合同方信息
*/
@Data
public class ContractLaunchPartyDto implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 关联合同主表 ID */
private Long contractId;
/** 角色编码(A:甲方/我方, B:乙方/相对方, C:丙方 等) */
private String roleCode;
/** 角色名称(甲方/乙方/丙方) */
private String roleName;
/** 排序号 */
private Integer sortOrder;
/** 关联相对方主表 IDpartner 模块的 customerSysid */
private Long partnerId;
/** 法务系统的相对方ID(jtId,采集后返回) */
private String oppositeId;
/** 公司全称 */
private String companyName;
/** 公司类型(client/supplier/Partner/clientAndSup/other */
private String companyType;
/** 相对方性质(1:境内组织,2:境内个人,3:境外组织,4:境外个人) */
private String oppositeCharacter;
/** 联系人姓名 */
private String contactName;
/** 联系人电话 */
private String contactPhone;
/** 联系人邮箱 */
private String contactEmail;
/** 联系地址 */
private String contactAddress;
/** 注册地址 */
private String registeredAddress;
/** 法定代表人 */
private String legalRepresentative;
/** 统一社会信用代码 */
private String creditCode;
/** 开户银行 */
private String bankName;
/** 银行账户 */
private String bankAccount;
/** 自然人证件类型 */
private String naturalPersonIdType;
/** 自然人证件号码 */
private String naturalPersonIdNumber;
/** 是否集团内(Y/N */
private String isGroupInternal;
/** 是否涉港澳台(Y/N */
private String isHongKongMacaoTaiwan;
/** 备注 */
private String remark;
}
@@ -0,0 +1,62 @@
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;
/**
* 履行计划
*
* 对应结算平台推送合同接口的 contractKxPlans 字段。
* 与法务接口文档中的款项计划一一映射。
*/
@Data
public class ContractLaunchPlanDto implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** 关联合同主表 ID */
private Long contractId;
/** 履行事项(如:第一笔付款) */
private String planMatter;
/** 履约条件(如:达到xx条件) */
private String planWhere;
/** 节点日期 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime planTime;
/** 提前提醒天数 */
private Integer planDay;
/** 款项金额 */
private Double planMoney;
/**
* 所属主体编码,推送法务字段 planSubjectCode。
*/
private String planSubjectCode;
/**
* 所属主体名称,推送法务字段 planSubjectName。
*/
private String planSubjectName;
/** 备注 */
private String planDetail;
/** 履行状态(0:待履行, 1:已履行, 2:逾期) */
private String planStatus;
/** 备注 */
private String remark;
}
@@ -0,0 +1,37 @@
package com.nbport.zgwl.contractlaunch.dto;
import com.nbport.zgwl.dto.BasePageDto;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
import java.io.Serializable;
/**
* 合同发起列表查询参数
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class ContractLaunchQueryDto extends BasePageDto implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/** 合同名称(模糊搜索) */
private String contractName;
/** 合同编号 */
private String contractCode;
/** 合同类型 */
private String contractType;
/** 状态(draft/reviewing/rejected/pending_sign/signing/pending_collect/pending_archive/completed */
private String status;
/** 创建时间范围-开始 yyyy-MM-dd */
private String dateStart;
/** 创建时间范围-结束 yyyy-MM-dd */
private String dateEnd;
}
@@ -0,0 +1,40 @@
package com.nbport.zgwl.contractlaunch.dto;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 签章回写参数
*
* 签署完成后,浙江CA安全签平台通过回调通知我方,
* 我方把签署结果回写到合同的 seal_* 字段。
*/
@Data
public class ContractLaunchSealDto implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/** 签章平台生成的合同ID(用于后续查询签署进度) */
private String sealContractId;
/** 签章状态(1:签署中, 2:签署完成, 3:签署失败) */
private Integer sealContractStatus;
/** 签署完成后的合同文件名 */
private String signedFileName;
/** 签署完成后的合同文件路径(我方存储) */
private String signedFilePath;
/** 签署完成后的合同文件类型 */
private String signedFileType;
/** 签署完成后的合同文件大小 */
private Long signedFileSize;
/** 未在线签署的原因(线下签署时填写) */
private String signedOfflineReason;
}
@@ -0,0 +1,96 @@
package com.nbport.zgwl.contractlaunch.mapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchDto;
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchFileDto;
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchLogDto;
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchPartyDto;
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchPlanDto;
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchQueryDto;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface ContractLaunchMapper {
/** 获取主表序列(Oracle 主键生成) */
Long selectMainSeqNextVal();
/** 获取合同方表序列 */
Long selectPartySeqNextVal();
/** 获取文件表序列 */
Long selectFileSeqNextVal();
/** 获取履行计划表序列 */
Long selectPlanSeqNextVal();
/** 获取日志表序列 */
Long selectLogSeqNextVal();
/** 分页查询合同列表 */
IPage<ContractLaunchDto> selectContractPage(Page<ContractLaunchDto> page, @Param("query") ContractLaunchQueryDto queryDto);
/** 根据主键查询合同 */
ContractLaunchDto selectContractById(@Param("id") Long id);
/** 根据 contractSysId 查询合同(法务回调时用于定位) */
ContractLaunchDto selectContractByContractSysId(@Param("contractSysId") String contractSysId);
/** 新增合同 */
int insertContract(ContractLaunchDto contract);
/** 修改合同 */
int updateContract(ContractLaunchDto contract);
/** 逻辑删除合同 */
int deleteContract(@Param("id") Long id, @Param("updateBy") String updateBy);
/** 批量插入合同方 */
int batchInsertParty(@Param("list") List<ContractLaunchPartyDto> list,
@Param("createBy") String createBy,
@Param("updateBy") String updateBy);
/** 批量插入文件 */
int batchInsertFile(@Param("list") List<ContractLaunchFileDto> list,
@Param("createBy") String createBy,
@Param("updateBy") String updateBy);
/** 批量插入履行计划 */
int batchInsertPlan(@Param("list") List<ContractLaunchPlanDto> list,
@Param("createBy") String createBy,
@Param("updateBy") String updateBy);
/** 插入单条操作日志 */
int insertLog(ContractLaunchLogDto logDto);
/** 删除合同下的所有合同方(逻辑删除) */
int deletePartyByContractId(@Param("contractId") Long contractId,
@Param("updateBy") String updateBy);
/** 删除合同下的所有文件(逻辑删除) */
int deleteFileByContractId(@Param("contractId") Long contractId,
@Param("updateBy") String updateBy);
/** 按分类删除合同下的文件(如重新上传正文时只删正文,不删其他附件) */
int deleteFileByContractIdAndCategory(@Param("contractId") Long contractId,
@Param("fileCategory") String fileCategory,
@Param("updateBy") String updateBy);
/** 删除合同下的所有履行计划(逻辑删除) */
int deletePlanByContractId(@Param("contractId") Long contractId,
@Param("updateBy") String updateBy);
/** 批量查询合同方(按 contractIds */
List<ContractLaunchPartyDto> selectPartyByContractIds(@Param("contractIds") List<Long> contractIds);
/** 批量查询文件(按 contractIds */
List<ContractLaunchFileDto> selectFileByContractIds(@Param("contractIds") List<Long> contractIds);
/** 批量查询履行计划(按 contractIds */
List<ContractLaunchPlanDto> selectPlanByContractIds(@Param("contractIds") List<Long> contractIds);
/** 批量查询操作日志(按 contractIds */
List<ContractLaunchLogDto> selectLogByContractIds(@Param("contractIds") List<Long> contractIds);
}
@@ -0,0 +1,52 @@
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.ContractLaunchDto;
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchQueryDto;
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchSealDto;
import java.util.Map;
public interface ContractLaunchService {
/** 分页查询合同列表 */
PageResult<ContractLaunchDto> queryPage(ContractLaunchQueryDto queryDto);
/** 查询合同详情(含合同方/文件/履行计划/日志) */
ContractLaunchDto getDetail(Long id);
/** 创建合同草稿 */
ContractLaunchDto createDraft(ContractLaunchDto contract);
/** 编辑合同草稿 */
ContractLaunchDto updateDraft(ContractLaunchDto contract);
/** 提交法务审批(调用结算平台 pushContract 接口) */
ContractLaunchDto submitToLaw(Long id);
/** 模拟审批通过(测试按钮,TODO:替换为真实法务回调) */
ContractLaunchDto mockApprove(Long id, ContractLaunchApproveDto approveDto);
/** 模拟审批驳回(测试按钮,TODO:替换为真实法务回调) */
ContractLaunchDto mockReject(Long id, ContractLaunchApproveDto approveDto);
/** 接收法务审批回调(处理审批结果,更新合同状态) */
ContractLaunchDto handleLawApproveCallback(Map<String, Object> callbackPayload);
/** 回写签章信息(签署发起时调用,记录 sealContractId */
ContractLaunchDto saveSealInfo(Long id, ContractLaunchSealDto sealDto);
/** 签署完成回调(回写签署文件路径,状态变更为待采集) */
ContractLaunchDto markSealCompleted(Long id, ContractLaunchSealDto sealDto);
/** 模拟合同采集(调用数据采集 collectContract 接口,TODO:替换为真实调用) */
ContractLaunchDto mockCollect(Long id);
/** 合同归档(状态变更为已完成,TODO:同时推送归档到法务) */
ContractLaunchDto archive(Long id, ContractLaunchArchiveDto archiveDto);
/** 删除草稿(仅 draft/rejected 状态允许) */
void deleteDraft(Long id);
}
@@ -0,0 +1,937 @@
package com.nbport.zgwl.contractlaunch.service;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
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.ContractLaunchDto;
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchFileDto;
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchLogDto;
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchPartyDto;
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchPlanDto;
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchQueryDto;
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchSealDto;
import com.nbport.zgwl.contractlaunch.mapper.ContractLaunchMapper;
import com.nbport.zgwl.contractlaunch.utils.ContractLaunchCodeUtils;
import com.nbport.zgwl.contractlaunch.utils.ContractLaunchConstants;
import com.nbport.zgwl.contractpush.dto.PushPayloadDTO;
import com.nbport.zgwl.contractpush.service.DataCollectionPushService;
import com.nbport.zgwl.contractpush.service.SettlementPushService;
import com.nbport.zgwl.entity.SysUserEntity;
import com.nbport.zgwl.exception.ServiceException;
import com.nbport.zgwl.utils.AdminSecurityManage;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* 合同发起主服务
*
* 这里尽量把核心流程都写在一个 Service 里,
* 方便你后续自己看和改,不额外再拆很多 handler。
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class ContractLaunchServiceImpl implements ContractLaunchService {
private final ContractLaunchMapper contractLaunchMapper;
private final AdminSecurityManage adminSecurityManage;
private final SettlementPushService settlementPushService;
private final DataCollectionPushService dataCollectionPushService;
/** 分页查询,附带合同方/文件/履行计划(列表页不查日志) */
@Override
public PageResult<ContractLaunchDto> queryPage(ContractLaunchQueryDto queryDto) {
Page<ContractLaunchDto> page = new Page<>(queryDto.getPageNo(), queryDto.getPageSize());
Page<ContractLaunchDto> resultPage = (Page<ContractLaunchDto>) contractLaunchMapper.selectContractPage(page, queryDto);
PageResult<ContractLaunchDto> pageResult = new PageResult<>(resultPage);
fillChildren(pageResult.getData(), false);
return pageResult;
}
/** 查询详情,含日志 */
@Override
public ContractLaunchDto getDetail(Long id) {
ContractLaunchDto contract = contractLaunchMapper.selectContractById(id);
if (contract == null) {
throw new ServiceException("合同不存在");
}
fillChildren(Collections.singletonList(contract), true);
return contract;
}
/**
* 创建合同草稿。
*
* 完整流程:
* 1. 获取当前登录用户信息
* 2. 数据清洗(normalizeContract:去空格、补默认值)
* 3. 数据校验(validateDraft:必填项检查)
* 4. 生成主键ID 和 contractSysIdCLS-时间戳)、contractCode(类型编码-日期-随机数)
* 5. 填充创建人/创建时间/公司/部门/状态 draft
* 6. 保存主表 + 子表(合同方/文件/履行计划)
* 7. 记录操作日志
*
* 注意:此时仅在本系统保存,未推送到法务系统。
*/
@Override
@Transactional(rollbackFor = Exception.class)
public ContractLaunchDto createDraft(ContractLaunchDto contract) {
SysUserEntity currentUser = adminSecurityManage.getUser();
normalizeContract(contract);
validateDraft(contract);
LocalDateTime now = LocalDateTime.now();
contract.setId(contractLaunchMapper.selectMainSeqNextVal());
contract.setContractSysId(ContractLaunchCodeUtils.buildContractSysId());
if (contract.getContractCode() == null || contract.getContractCode().isBlank()) {
contract.setContractCode(ContractLaunchCodeUtils.buildContractCode(contract.getContractTypeCode()));
}
contract.setContractSource(contract.getContractSource() == null || contract.getContractSource().isBlank() ? "ECP" : contract.getContractSource());
contract.setStatus(ContractLaunchConstants.STATUS_DRAFT);
contract.setApproveStatus(ContractLaunchConstants.APPROVE_STATUS_PENDING);
contract.setInitiator(currentUser.getUsername());
contract.setInitiatorDept(currentUser.getSysOrgEntity() == null ? "" : currentUser.getSysOrgEntity().getOrgName());
contract.setCompanyName(currentUser.getSysOrgEntity() == null ? "" : currentUser.getSysOrgEntity().getOrgName());
contract.setOrgId(currentUser.getSysOrgEntity() == null ? "" : currentUser.getSysOrgEntity().getId());
contract.setCreatorPhone(currentUser.getMobilePhone());
contract.setCreateBy(currentUser.getUsername());
contract.setCreateTime(now);
contract.setUpdateBy(currentUser.getUsername());
contract.setUpdateTime(now);
contract.setIsDeleted(ContractLaunchConstants.IS_DELETED_NO);
contract.setQueryScope("personal");
contractLaunchMapper.insertContract(contract);
saveChildren(contract, currentUser.getUsername());
insertLog(contract.getId(), ContractLaunchConstants.ACTION_SAVE, "保存草稿", ContractLaunchConstants.ACTION_STATUS_SUCCESS, "合同草稿创建成功", null, currentUser);
return getDetail(contract.getId());
}
/**
* 编辑合同草稿。
*
* 仅 draft(草稿)或 rejected(已驳回)可编辑。
* 采用替换式更新:先删子表(合同方/文件/履行计划)旧数据,再以当前数据重新插入。
* 保留以下字段不变:contractSysId、contractCode、lawContractCode、lawContractId、
* 状态、审批状态、发起人、公司、orgId、创建人/创建时间。
*/
@Override
@Transactional(rollbackFor = Exception.class)
public ContractLaunchDto updateDraft(ContractLaunchDto contract) {
if (contract.getId() == null) {
throw new ServiceException("修改时 id 不能为空");
}
ContractLaunchDto dbContract = getDetail(contract.getId());
if (!canEdit(dbContract.getStatus())) {
throw new ServiceException("当前状态不允许编辑");
}
SysUserEntity currentUser = adminSecurityManage.getUser();
normalizeContract(contract);
validateDraft(contract);
contract.setContractSysId(dbContract.getContractSysId());
contract.setContractCode(dbContract.getContractCode());
contract.setLawContractCode(dbContract.getLawContractCode());
contract.setLawContractId(dbContract.getLawContractId());
contract.setStatus(dbContract.getStatus());
contract.setApproveStatus(dbContract.getApproveStatus());
contract.setInitiator(dbContract.getInitiator());
contract.setInitiatorDept(dbContract.getInitiatorDept());
contract.setCompanyName(dbContract.getCompanyName());
contract.setOrgId(dbContract.getOrgId());
contract.setCreatorPhone(dbContract.getCreatorPhone());
contract.setCreateBy(dbContract.getCreateBy());
contract.setCreateTime(dbContract.getCreateTime());
contract.setUpdateBy(currentUser.getUsername());
contract.setUpdateTime(LocalDateTime.now());
contract.setIsDeleted(ContractLaunchConstants.IS_DELETED_NO);
contractLaunchMapper.updateContract(contract);
replaceChildren(contract, currentUser.getUsername());
insertLog(contract.getId(), ContractLaunchConstants.ACTION_SAVE, "编辑草稿", ContractLaunchConstants.ACTION_STATUS_SUCCESS, "合同草稿修改成功", null, currentUser);
return getDetail(contract.getId());
}
/**
* 提交法务审批。
*
* 状态流转:draft/rejected → reviewing(待审批)
*
* 主要做两件事:
* 1. 更新合同状态为 reviewing
* 2. 构建结算平台 pushContract 接口的完整报文(含合同方、履行计划、附件等)
* 3. 记录提交日志(日志中保存了完整的推送报文,方便排查)
*
* TODO(真实联调时打开):
* PushPayloadDTO requestDTO = new PushPayloadDTO();
* requestDTO.setPayload(settlementPayload);
* settlementPushService.pushContract(requestDTO);
*
* 法务审批完成后会通过 pushUrl 回调本系统的 /callback/law/approve 接口。
*/
@Override
@Transactional(rollbackFor = Exception.class)
public ContractLaunchDto submitToLaw(Long id) {
ContractLaunchDto contract = getDetail(id);
if (!canSubmit(contract.getStatus())) {
throw new ServiceException("当前状态不允许提交法务");
}
SysUserEntity currentUser = adminSecurityManage.getUser();
contract.setStatus(ContractLaunchConstants.STATUS_REVIEWING);
contract.setApproveStatus(ContractLaunchConstants.APPROVE_STATUS_PENDING);
contract.setApproveMessage("已提交法务,等待审批");
contract.setUpdateBy(currentUser.getUsername());
contract.setUpdateTime(LocalDateTime.now());
contractLaunchMapper.updateContract(contract);
Map<String, Object> settlementPayload = buildSettlementPushPayload(contract);
insertLog(id, ContractLaunchConstants.ACTION_SUBMIT, "提交法务", ContractLaunchConstants.ACTION_STATUS_PENDING, "合同已提交法务接口,当前先保留 mock 流程", settlementPayload, currentUser);
// TODO: 法务接口当前不可用,真实联调时打开下面调用即可
// PushPayloadDTO requestDTO = new PushPayloadDTO();
// requestDTO.setPayload(settlementPayload);
// Map<String, Object> response = settlementPushService.pushContract(requestDTO);
return getDetail(id);
}
/**
* 【测试按钮】模拟法务审批通过。
*
* 状态流转:reviewing → pending_sign(待签署)
*
* 模拟法务系统返回 lawContractCode 和 lawContractId,供后续签署流程使用。
* 如果 approveDto 中传入了值则使用传入值,否则自动生成模拟值:
* - lawContractCode = "LAW-" + 合同类型编码-日期-随机数
* - lawContractId = "LAWID-" + 合同ID
*
* 真实场景下此逻辑由法务回调接口 handleLawApproveCallback 替代。
*/
@Override
@Transactional(rollbackFor = Exception.class)
public ContractLaunchDto mockApprove(Long id, ContractLaunchApproveDto approveDto) {
ContractLaunchDto contract = getDetail(id);
if (!ContractLaunchConstants.STATUS_REVIEWING.equals(contract.getStatus())) {
throw new ServiceException("仅审批中的合同可模拟通过");
}
SysUserEntity currentUser = adminSecurityManage.getUser();
contract.setStatus(ContractLaunchConstants.STATUS_PENDING_SIGN);
contract.setApproveStatus(ContractLaunchConstants.APPROVE_STATUS_APPROVED);
contract.setApproveMessage(approveDto == null || approveDto.getApproveMessage() == null || approveDto.getApproveMessage().isBlank()
? "法务审批通过(测试按钮模拟)"
: approveDto.getApproveMessage());
contract.setLawContractCode(approveDto == null || approveDto.getLawContractCode() == null || approveDto.getLawContractCode().isBlank()
? "LAW-" + ContractLaunchCodeUtils.buildContractCode(contract.getContractTypeCode())
: approveDto.getLawContractCode());
contract.setLawContractId(approveDto == null || approveDto.getLawContractId() == null || approveDto.getLawContractId().isBlank()
? "LAWID-" + id
: approveDto.getLawContractId());
contract.setUpdateBy(currentUser.getUsername());
contract.setUpdateTime(LocalDateTime.now());
contractLaunchMapper.updateContract(contract);
insertLog(id, ContractLaunchConstants.ACTION_APPROVE, "模拟审批通过", ContractLaunchConstants.ACTION_STATUS_SUCCESS, contract.getApproveMessage(), approveDto, currentUser);
return getDetail(id);
}
/**
* 【测试按钮】模拟法务审批驳回。
*
* 状态流转:reviewing → rejected(已驳回)
* 驳回后合同回到草稿状态,可以再次编辑后重新提交。
*/
@Override
@Transactional(rollbackFor = Exception.class)
public ContractLaunchDto mockReject(Long id, ContractLaunchApproveDto approveDto) {
ContractLaunchDto contract = getDetail(id);
if (!ContractLaunchConstants.STATUS_REVIEWING.equals(contract.getStatus())) {
throw new ServiceException("仅审批中的合同可模拟驳回");
}
SysUserEntity currentUser = adminSecurityManage.getUser();
contract.setStatus(ContractLaunchConstants.STATUS_REJECTED);
contract.setApproveStatus(ContractLaunchConstants.APPROVE_STATUS_REJECTED);
contract.setApproveMessage(approveDto == null || approveDto.getApproveMessage() == null || approveDto.getApproveMessage().isBlank()
? "法务审批驳回(测试按钮模拟)"
: approveDto.getApproveMessage());
contract.setUpdateBy(currentUser.getUsername());
contract.setUpdateTime(LocalDateTime.now());
contractLaunchMapper.updateContract(contract);
insertLog(id, ContractLaunchConstants.ACTION_REJECT, "模拟审批驳回", ContractLaunchConstants.ACTION_STATUS_SUCCESS, contract.getApproveMessage(), approveDto, currentUser);
return getDetail(id);
}
/**
* 接收法务审批回调。
*
* 法务系统审批完成后,通过 pushUrl POST 审批结果到本接口。
*
* 处理逻辑:
* 1. 从回调报文中提取 contractSysId 定位到本系统合同
* 2. 判断审批结果(通过/驳回)
* - 通过:status → pending_sign(待签署),记录法务返回的合同编号和合同ID
* - 驳回:status → rejected(已驳回),记录驳回原因
* 3. 记录操作日志
*
* 兼容设计:
* - 使用 getFirstText 按多个 key 依次尝试提取字段(如 approveStatus/status/result
* - 审批通过状态兼容:1/true/success/approved/pass/agree/审批通过
* - 合同编号兼容:lawContractCode/contractCode/htCode/code
* - 合同ID兼容:lawContractId/contractId/id/businessId
*/
@Override
@Transactional(rollbackFor = Exception.class)
public ContractLaunchDto handleLawApproveCallback(Map<String, Object> callbackPayload) {
ContractLaunchDto contract = getContractByLawCallback(callbackPayload);
SysUserEntity currentUser = adminSecurityManage.getUser();
boolean approved = isLawCallbackApproved(callbackPayload);
contract.setApproveStatus(approved
? ContractLaunchConstants.APPROVE_STATUS_APPROVED
: ContractLaunchConstants.APPROVE_STATUS_REJECTED);
contract.setStatus(approved
? ContractLaunchConstants.STATUS_PENDING_SIGN
: ContractLaunchConstants.STATUS_REJECTED);
contract.setApproveMessage(getFirstText(callbackPayload,
"approveMessage", "message", "msg", "opinion", "remark"));
String lawContractCode = getFirstText(callbackPayload,
"lawContractCode", "contractCode", "htCode", "code");
String lawContractId = getFirstText(callbackPayload,
"lawContractId", "contractId", "id", "businessId");
if (lawContractCode != null && !lawContractCode.isBlank()) {
contract.setLawContractCode(lawContractCode);
}
if (lawContractId != null && !lawContractId.isBlank()) {
contract.setLawContractId(lawContractId);
}
contract.setUpdateBy(currentUser.getUsername());
contract.setUpdateTime(LocalDateTime.now());
contractLaunchMapper.updateContract(contract);
insertLog(
contract.getId(),
approved ? ContractLaunchConstants.ACTION_APPROVE : ContractLaunchConstants.ACTION_REJECT,
approved ? "法务审批回调通过" : "法务审批回调驳回",
ContractLaunchConstants.ACTION_STATUS_SUCCESS,
contract.getApproveMessage(),
callbackPayload,
currentUser
);
return getDetail(contract.getId());
}
/**
* 回写签章信息(签署发起时调用)。
*
* 浙江CA安全签平台创建签署合同后,回调此方法回写 sealContractId。
* 状态流转:pending_sign → signing(签署中)
*
* sealContractId 由浙江CA安全签平台生成,后续通过此 ID 查询签署进度。
*/
@Override
@Transactional(rollbackFor = Exception.class)
public ContractLaunchDto saveSealInfo(Long id, ContractLaunchSealDto sealDto) {
ContractLaunchDto contract = getDetail(id);
SysUserEntity currentUser = adminSecurityManage.getUser();
contract.setSealContractId(sealDto.getSealContractId());
contract.setSealContractStatus(sealDto.getSealContractStatus());
contract.setStatus(ContractLaunchConstants.STATUS_SIGNING);
contract.setUpdateBy(currentUser.getUsername());
contract.setUpdateTime(LocalDateTime.now());
contractLaunchMapper.updateContract(contract);
insertLog(id, ContractLaunchConstants.ACTION_SEAL_START, "开始签署", ContractLaunchConstants.ACTION_STATUS_SUCCESS, "签章平台合同已创建", sealDto, currentUser);
return getDetail(id);
}
/**
* 签署完成回调。
*
* 所有签署方签署完成后(或在浙江CA签署完成、或线下签署后手动上传),
* 回写签署完成的合同文件信息。
*
* 状态流转:signing → pending_collect(待采集)
*
* 执行步骤:
* 1. 回写 signedFileName/signedFilePath/signedFileType/signedFileSize
* 2. 如果有线下签署原因(signedOfflineReason),一并保存
* 3. 将签署文件保存到 file 子表(fileCategory = "signed"
* 4. 记录操作日志
*/
@Override
@Transactional(rollbackFor = Exception.class)
public ContractLaunchDto markSealCompleted(Long id, ContractLaunchSealDto sealDto) {
ContractLaunchDto contract = getDetail(id);
SysUserEntity currentUser = adminSecurityManage.getUser();
contract.setSealContractId(sealDto.getSealContractId() == null || sealDto.getSealContractId().isBlank() ? contract.getSealContractId() : sealDto.getSealContractId());
contract.setSealContractStatus(sealDto.getSealContractStatus());
contract.setSignedFileName(sealDto.getSignedFileName());
contract.setSignedFilePath(sealDto.getSignedFilePath());
contract.setSignedFileType(sealDto.getSignedFileType());
contract.setSignedFileSize(sealDto.getSignedFileSize());
contract.setSignedOfflineReason(sealDto.getSignedOfflineReason());
contract.setStatus(ContractLaunchConstants.STATUS_PENDING_COLLECT);
contract.setUpdateBy(currentUser.getUsername());
contract.setUpdateTime(LocalDateTime.now());
contractLaunchMapper.updateContract(contract);
saveSignedFile(id, sealDto, currentUser.getUsername());
insertLog(id, ContractLaunchConstants.ACTION_SEAL_FINISH, "签署完成", ContractLaunchConstants.ACTION_STATUS_SUCCESS, "合同签署已完成,待采集", sealDto, currentUser);
return getDetail(id);
}
/**
* 【测试按钮】模拟合同采集。
*
* 合同签署完成后,将合同最新信息(含用印信息和签订信息)推送到法务系统。
*
* 状态流转:pending_collect → pending_archive(待归档)
*
* 构建数据采集 V3.0 collectContract 接口的报文,包含:
* - 合同基本字段(c_name, c_code, c_type 等)
* - 用印信息 c_seal(签章类型、签章日期等)
* - 签订信息 c_sign(签署日期、生效日期、签署附件等)
* - 履行计划 c_lxPlan
* - 附件(正文 c_zw / 其他 c_attachs / 签署文件 c_signAttachs
*
* TODO(真实联调时打开):
* PushPayloadDTO requestDTO = new PushPayloadDTO();
* requestDTO.setPayload(payload);
* dataCollectionPushService.collectContract(requestDTO);
*/
@Override
@Transactional(rollbackFor = Exception.class)
public ContractLaunchDto mockCollect(Long id) {
ContractLaunchDto contract = getDetail(id);
if (!ContractLaunchConstants.STATUS_PENDING_COLLECT.equals(contract.getStatus())) {
throw new ServiceException("当前状态不允许执行采集");
}
SysUserEntity currentUser = adminSecurityManage.getUser();
Map<String, Object> payload = buildDataCollectionContractPayload(contract);
insertLog(id, ContractLaunchConstants.ACTION_COLLECT, "模拟合同采集", ContractLaunchConstants.ACTION_STATUS_PENDING, "合同采集接口当前先注释,使用测试按钮流转", payload, currentUser);
// TODO: 法务接口当前不可用,真实联调时打开下面调用即可
// PushPayloadDTO requestDTO = new PushPayloadDTO();
// requestDTO.setPayload(payload);
// dataCollectionPushService.collectContract(requestDTO);
contract.setStatus(ContractLaunchConstants.STATUS_PENDING_ARCHIVE);
contract.setUpdateBy(currentUser.getUsername());
contract.setUpdateTime(LocalDateTime.now());
contractLaunchMapper.updateContract(contract);
return getDetail(id);
}
/**
* 合同归档。
*
* 合同全生命周期最后一步。将归档信息(保管人、保管单位、归档附件)保存到合同,
* 同时推送到法务系统存档。
*
* 状态流转:pending_archive → completed(已完成)
*
* 执行步骤:
* 1. 填写归档日期、保管人信息
* 2. 保存归档附件到 file 子表(fileCategory = "archive"
* 3. 构建归档报文 pushArchive 接口的 payload
* 4. 记录操作日志
*
* TODO(真实联调时打开):
* settlementPushService.pushArchive(requestDTO)
* dataCollectionPushService.collectContractArchive(requestDTO)
*/
@Override
@Transactional(rollbackFor = Exception.class)
public ContractLaunchDto archive(Long id, ContractLaunchArchiveDto archiveDto) {
ContractLaunchDto contract = getDetail(id);
if (!ContractLaunchConstants.STATUS_PENDING_ARCHIVE.equals(contract.getStatus())) {
throw new ServiceException("当前状态不允许归档");
}
SysUserEntity currentUser = adminSecurityManage.getUser();
contract.setArchiveDate(LocalDateTime.now());
contract.setArchiveKeeper(archiveDto == null ? null : archiveDto.getArchiveKeeper());
contract.setArchiveKeeperUnit(archiveDto == null ? null : archiveDto.getArchiveKeeperUnit());
contract.setArchiveKeeperUnitCode(archiveDto == null ? null : archiveDto.getArchiveKeeperUnitCode());
contract.setStatus(ContractLaunchConstants.STATUS_COMPLETED);
contract.setUpdateBy(currentUser.getUsername());
contract.setUpdateTime(LocalDateTime.now());
contractLaunchMapper.updateContract(contract);
if (archiveDto != null && archiveDto.getArchiveFiles() != null && !archiveDto.getArchiveFiles().isEmpty()) {
for (ContractLaunchFileDto fileDto : archiveDto.getArchiveFiles()) {
fileDto.setId(contractLaunchMapper.selectFileSeqNextVal());
fileDto.setContractId(id);
fileDto.setFileCategory(ContractLaunchConstants.FILE_CATEGORY_ARCHIVE);
}
contractLaunchMapper.batchInsertFile(archiveDto.getArchiveFiles(), currentUser.getUsername(), currentUser.getUsername());
}
Map<String, Object> payload = buildArchivePayload(contract, archiveDto);
insertLog(id, ContractLaunchConstants.ACTION_ARCHIVE, "合同归档", ContractLaunchConstants.ACTION_STATUS_PENDING, "合同归档接口当前先注释,使用测试按钮流转", payload, currentUser);
// TODO: 法务接口当前不可用,真实联调时打开下面调用即可
// PushPayloadDTO requestDTO = new PushPayloadDTO();
// requestDTO.setPayload(payload);
// settlementPushService.pushArchive(requestDTO);
// dataCollectionPushService.collectContractArchive(requestDTO);
return getDetail(id);
}
/**
* 删除合同草稿(逻辑删除)。
*
* 仅 draft(草稿)或 rejected(已驳回)状态允许删除。
* 设置 isDeleted = 'Y',不物理删除数据。
* 已提交法务审批或进行中的合同不允许删除。
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteDraft(Long id) {
ContractLaunchDto contract = getDetail(id);
if (!canDelete(contract.getStatus())) {
throw new ServiceException("仅草稿或驳回状态允许删除");
}
SysUserEntity currentUser = adminSecurityManage.getUser();
contractLaunchMapper.deleteContract(id, currentUser.getUsername());
insertLog(id, ContractLaunchConstants.ACTION_DELETE, "删除合同", ContractLaunchConstants.ACTION_STATUS_SUCCESS, "合同已逻辑删除", null, currentUser);
}
/**
* 批量填充子表数据(合同方/文件/履行计划/日志)。
*
* 一次性查完所有子表再按 contractId 分组赋值,避免 N+1 查询。
* includeLogs: 列表页不查日志(日志数据量大),详情页才查。
*/
private void fillChildren(List<ContractLaunchDto> list, boolean includeLogs) {
if (list == null || list.isEmpty()) {
return;
}
List<Long> ids = list.stream().map(ContractLaunchDto::getId).filter(Objects::nonNull).collect(Collectors.toList());
if (ids.isEmpty()) {
return;
}
Map<Long, List<ContractLaunchPartyDto>> partyMap = contractLaunchMapper.selectPartyByContractIds(ids).stream()
.collect(Collectors.groupingBy(ContractLaunchPartyDto::getContractId));
Map<Long, List<ContractLaunchFileDto>> fileMap = contractLaunchMapper.selectFileByContractIds(ids).stream()
.collect(Collectors.groupingBy(ContractLaunchFileDto::getContractId));
Map<Long, List<ContractLaunchPlanDto>> planMap = contractLaunchMapper.selectPlanByContractIds(ids).stream()
.collect(Collectors.groupingBy(ContractLaunchPlanDto::getContractId));
Map<Long, List<ContractLaunchLogDto>> logMap = includeLogs
? contractLaunchMapper.selectLogByContractIds(ids).stream().collect(Collectors.groupingBy(ContractLaunchLogDto::getContractId))
: Collections.emptyMap();
list.forEach(item -> {
item.setPartyList(new ArrayList<>(partyMap.getOrDefault(item.getId(), Collections.emptyList())));
item.setFileList(new ArrayList<>(fileMap.getOrDefault(item.getId(), Collections.emptyList())));
item.setPerformancePlans(new ArrayList<>(planMap.getOrDefault(item.getId(), Collections.emptyList())));
item.setLogList(new ArrayList<>(logMap.getOrDefault(item.getId(), Collections.emptyList())));
item.setCounterpartySummary(
item.getPartyList().stream()
.filter(party -> !"A".equalsIgnoreCase(party.getRoleCode()))
.map(ContractLaunchPartyDto::getCompanyName)
.filter(name -> name != null && !name.isBlank())
.collect(Collectors.joining(""))
);
});
}
/** 保存子表数据(合同方/文件/履行计划,插入前生成主键 ID) */
private void saveChildren(ContractLaunchDto contract, String operator) {
if (contract.getPartyList() != null) {
for (int i = 0; i < contract.getPartyList().size(); i++) {
ContractLaunchPartyDto party = contract.getPartyList().get(i);
party.setId(contractLaunchMapper.selectPartySeqNextVal());
party.setContractId(contract.getId());
party.setSortOrder(i + 1);
}
if (!contract.getPartyList().isEmpty()) {
contractLaunchMapper.batchInsertParty(contract.getPartyList(), operator, operator);
}
}
if (contract.getFileList() != null) {
for (int i = 0; i < contract.getFileList().size(); i++) {
ContractLaunchFileDto file = contract.getFileList().get(i);
file.setId(contractLaunchMapper.selectFileSeqNextVal());
file.setContractId(contract.getId());
file.setSortOrder(i + 1);
}
if (!contract.getFileList().isEmpty()) {
contractLaunchMapper.batchInsertFile(contract.getFileList(), operator, operator);
}
}
if (contract.getPerformancePlans() != null) {
for (ContractLaunchPlanDto plan : contract.getPerformancePlans()) {
plan.setId(contractLaunchMapper.selectPlanSeqNextVal());
plan.setContractId(contract.getId());
if (plan.getPlanStatus() == null || plan.getPlanStatus().isBlank()) {
plan.setPlanStatus("0");
}
}
if (!contract.getPerformancePlans().isEmpty()) {
contractLaunchMapper.batchInsertPlan(contract.getPerformancePlans(), operator, operator);
}
}
}
/** 替换子表数据(先删旧数据,再保存新数据) */
private void replaceChildren(ContractLaunchDto contract, String operator) {
contractLaunchMapper.deletePartyByContractId(contract.getId(), operator);
contractLaunchMapper.deleteFileByContractId(contract.getId(), operator);
contractLaunchMapper.deletePlanByContractId(contract.getId(), operator);
saveChildren(contract, operator);
}
/** 保存签署文件到 file 子表(先删旧签署文件,再插入新的) */
private void saveSignedFile(Long contractId, ContractLaunchSealDto sealDto, String operator) {
if (sealDto.getSignedFilePath() == null || sealDto.getSignedFilePath().isBlank()) {
return;
}
contractLaunchMapper.deleteFileByContractIdAndCategory(contractId, ContractLaunchConstants.FILE_CATEGORY_SIGNED, operator);
ContractLaunchFileDto fileDto = new ContractLaunchFileDto();
fileDto.setId(contractLaunchMapper.selectFileSeqNextVal());
fileDto.setContractId(contractId);
fileDto.setFileCategory(ContractLaunchConstants.FILE_CATEGORY_SIGNED);
fileDto.setFileName(sealDto.getSignedFileName() == null || sealDto.getSignedFileName().isBlank()
? "已签署合同文件"
: sealDto.getSignedFileName());
fileDto.setFilePath(sealDto.getSignedFilePath());
fileDto.setFileType(sealDto.getSignedFileType());
fileDto.setFileSize(sealDto.getSignedFileSize());
fileDto.setSortOrder(1);
contractLaunchMapper.batchInsertFile(Collections.singletonList(fileDto), operator, operator);
}
/** 写入操作日志 */
private void insertLog(Long contractId, String actionType, String actionName, String actionStatus, String actionContent, Object payload, SysUserEntity currentUser) {
ContractLaunchLogDto logDto = new ContractLaunchLogDto();
logDto.setId(contractLaunchMapper.selectLogSeqNextVal());
logDto.setContractId(contractId);
logDto.setActionType(actionType);
logDto.setActionName(actionName);
logDto.setActionStatus(actionStatus);
logDto.setOperatorName(currentUser.getUsername());
logDto.setOperatorPhone(currentUser.getMobilePhone());
logDto.setActionTime(LocalDateTime.now());
logDto.setActionContent(actionContent);
logDto.setCallbackPayload(payload == null ? null : JSON.toJSONString(payload));
contractLaunchMapper.insertLog(logDto);
}
/** 数据清洗:去空格、补默认值 */
private void normalizeContract(ContractLaunchDto contract) {
if (contract == null) {
throw new ServiceException("合同数据不能为空");
}
contract.setContractName(trim(contract.getContractName()));
contract.setContractCode(trim(contract.getContractCode()));
contract.setContractType(trim(contract.getContractType()));
contract.setContractTypeCode(trim(contract.getContractTypeCode()));
contract.setPaymentMethod(trim(contract.getPaymentMethod()));
contract.setPrimaryContent(trim(contract.getPrimaryContent()));
contract.setAmountExplain(trim(contract.getAmountExplain()));
contract.setAssistDepartmentName(trim(contract.getAssistDepartmentName()));
contract.setExecutorAccount(trim(contract.getExecutorAccount()));
contract.setPeriodExplain(trim(contract.getPeriodExplain()));
contract.setContractGistRemark(trim(contract.getContractGistRemark()));
contract.setBodySummary(trim(contract.getBodySummary()));
contract.setSigningSubjectCode(trim(contract.getSigningSubjectCode()));
contract.setDateType(trim(contract.getDateType()));
contract.setPushUrl(trim(contract.getPushUrl()));
contract.setEwAmountType(trim(contract.getEwAmountType()));
if (contract.getDateType() == null || contract.getDateType().isBlank()) {
contract.setDateType("0");
}
if (contract.getTextSource() == null || contract.getTextSource().isBlank()) {
contract.setTextSource("standardText");
}
if (contract.getIsElectron() == null || contract.getIsElectron().isBlank()) {
contract.setIsElectron("1");
}
if (contract.getPaymentDirection() == null || contract.getPaymentDirection().isBlank()) {
contract.setPaymentDirection("0");
}
if (contract.getPushUrl() == null || contract.getPushUrl().isBlank()) {
contract.setPushUrl("/contract/launch/callback/law/approve");
}
if (contract.getPartyList() == null) {
contract.setPartyList(new ArrayList<>());
}
if (contract.getFileList() == null) {
contract.setFileList(new ArrayList<>());
}
if (contract.getPerformancePlans() == null) {
contract.setPerformancePlans(new ArrayList<>());
}
}
/** 校验草稿必填项 */
private void validateDraft(ContractLaunchDto contract) {
if (contract.getContractName() == null || contract.getContractName().isBlank()) {
throw new ServiceException("合同名称不能为空");
}
if (contract.getContractTypeCode() == null || contract.getContractTypeCode().isBlank()) {
throw new ServiceException("合同类型编码不能为空");
}
if (contract.getContractType() == null || contract.getContractType().isBlank()) {
throw new ServiceException("合同类型不能为空");
}
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.getContractPeriodType() == null || contract.getContractPeriodType().isBlank()) {
throw new ServiceException("合同期限类型不能为空");
}
if ("0".equals(contract.getContractPeriodType())
&& (contract.getEffectiveStart() == null || contract.getEffectiveEnd() == null)) {
throw new ServiceException("固定期限合同必须填写开始和结束时间");
}
if ("1".equals(contract.getContractPeriodType())
&& (contract.getPeriodExplain() == null || contract.getPeriodExplain().isBlank())) {
throw new ServiceException("无固定期限合同必须填写期限说明");
}
if (contract.getPartyList() == null || contract.getPartyList().isEmpty()) {
throw new ServiceException("至少需要维护一个合同方");
}
boolean hasPartyA = contract.getPartyList().stream().anyMatch(item -> "A".equalsIgnoreCase(item.getRoleCode()));
boolean hasCounterparty = contract.getPartyList().stream().anyMatch(item -> !"A".equalsIgnoreCase(item.getRoleCode()));
if (!hasPartyA) {
throw new ServiceException("必须维护我方信息");
}
if (!hasCounterparty) {
throw new ServiceException("至少维护一个相对方");
}
}
private boolean canEdit(String status) {
return ContractLaunchConstants.STATUS_DRAFT.equals(status) || ContractLaunchConstants.STATUS_REJECTED.equals(status);
}
private boolean canSubmit(String status) {
return ContractLaunchConstants.STATUS_DRAFT.equals(status) || ContractLaunchConstants.STATUS_REJECTED.equals(status);
}
private boolean canDelete(String status) {
return ContractLaunchConstants.STATUS_DRAFT.equals(status) || ContractLaunchConstants.STATUS_REJECTED.equals(status);
}
/** 通过法务回调报文查找对应合同(先取 contractSysId 再查库) */
private ContractLaunchDto getContractByLawCallback(Map<String, Object> payload) {
if (payload == null || payload.isEmpty()) {
throw new ServiceException("法务回调报文不能为空");
}
String contractSysId = getFirstText(payload, "contractSysId", "businessNo", "thirdContractId");
if (contractSysId == null || contractSysId.isBlank()) {
throw new ServiceException("法务回调缺少 contractSysId,无法定位合同");
}
ContractLaunchDto contract = contractLaunchMapper.selectContractByContractSysId(contractSysId);
if (contract == null) {
throw new ServiceException("未找到法务回调对应的合同:" + contractSysId);
}
fillChildren(Collections.singletonList(contract), true);
return contract;
}
/** 判断法务回调是否审批通过(兼容多种字段名和值) */
private boolean isLawCallbackApproved(Map<String, Object> payload) {
String status = getFirstText(payload, "approveStatus", "status", "result", "auditStatus");
if (status == null || status.isBlank()) {
return true;
}
String normalized = status.trim().toLowerCase();
return normalized.equals("1")
|| normalized.equals("true")
|| normalized.equals("success")
|| normalized.equals("approved")
|| normalized.equals("pass")
|| normalized.equals("agree")
|| normalized.equals("通过")
|| normalized.equals("审批通过");
}
/** 从回调报文中提取指定 key 的文本值(多个 key 依次尝试,取第一个非空) */
private String getFirstText(Map<String, Object> payload, String... keys) {
if (payload == null) {
return null;
}
for (String key : keys) {
Object value = payload.get(key);
if (value == null) {
continue;
}
String text = String.valueOf(value).trim();
if (!text.isBlank()) {
return text;
}
}
return null;
}
/** 构建结算平台推送合同报文(pushContract 接口的 payload */
private Map<String, Object> buildSettlementPushPayload(ContractLaunchDto contract) {
Map<String, Object> payload = new LinkedHashMap<>();
payload.put("contractSource", contract.getContractSource());
payload.put("isAddit", contract.getIsAddit() == null ? 2 : contract.getIsAddit());
payload.put("operate", "create");
payload.put("mainContractCode", contract.getMainContractCode());
payload.put("periodExplain", contract.getPeriodExplain());
payload.put("valuationMode", contract.getValuationMode());
payload.put("isMajorContract", contract.getIsMajorContract() == null ? 0 : contract.getIsMajorContract());
payload.put("sealType", contract.getSealType());
payload.put("creatorPhone", contract.getCreatorPhone());
payload.put("dateType", contract.getDateType());
payload.put("currencyName", contract.getCurrencyName());
payload.put("contractGistRemark", contract.getContractGistRemark());
payload.put("contractSysId", contract.getContractSysId());
payload.put("selfCode", contract.getSelfCode());
payload.put("contractName", contract.getContractName());
payload.put("startTime", contract.getEffectiveStart());
payload.put("endTime", contract.getEffectiveEnd());
payload.put("amountExplain", contract.getAmountExplain());
payload.put("isText", contract.getTextSource());
payload.put("primaryContent", contract.getPrimaryContent());
payload.put("isElectron", contract.getIsElectron());
payload.put("paymentDirection", contract.getPaymentDirection());
payload.put("contractTypeCode", contract.getContractTypeCode());
payload.put("bodySummary", contract.getBodySummary());
payload.put("signingSubjectCode",
contract.getSigningSubjectCode() == null || contract.getSigningSubjectCode().isBlank()
? contract.getOrgId()
: contract.getSigningSubjectCode());
payload.put("executorAccount", contract.getExecutorAccount());
payload.put("contractPeriod", contract.getContractPeriodType());
payload.put("contractAmount", contract.getContractAmount());
payload.put("isSgat", contract.getIsSgat());
payload.put("isOpenBidding", contract.getIsOpenBidding() == null ? 0 : contract.getIsOpenBidding());
payload.put("pushUrl", contract.getPushUrl());
payload.put("isYearBudget", contract.getIsYearBudget() == null ? 0 : contract.getIsYearBudget());
payload.put("isShare", contract.getIsShare());
payload.put("assistDepartmentName", contract.getAssistDepartmentName());
payload.put("contractNature", contract.getContractNature());
payload.put("contractCode", contract.getContractCode());
payload.put("ewAmountType", contract.getEwAmountType());
payload.put("djAmount", contract.getDjAmount());
payload.put("yjAmount", contract.getYjAmount());
payload.put("yfkAmount", contract.getYfkAmount());
payload.put("bzjAmount", contract.getBzjAmount());
payload.put("contractOpposites", contract.getPartyList().stream()
.filter(item -> !"A".equalsIgnoreCase(item.getRoleCode()))
.map(item -> {
Map<String, Object> map = new LinkedHashMap<>();
map.put("oppCharacter", "2".equals(item.getOppositeCharacter()) ? "ZZR" : "QY");
map.put("credirCode", item.getCreditCode());
map.put("idCard", item.getNaturalPersonIdNumber());
map.put("oppositeName", item.getCompanyName());
return map;
}).collect(Collectors.toList()));
payload.put("contractKxPlans", contract.getPerformancePlans().stream().map(plan -> {
Map<String, Object> map = new LinkedHashMap<>();
map.put("planWhere", plan.getPlanWhere());
map.put("planMoney", plan.getPlanMoney());
map.put("planDetail", plan.getPlanDetail());
map.put("planTime", plan.getPlanTime());
map.put("planMatter", plan.getPlanMatter());
map.put("planDay", plan.getPlanDay());
map.put("planSubjectCode", plan.getPlanSubjectCode());
map.put("planSubjectName", plan.getPlanSubjectName());
return map;
}).collect(Collectors.toList()));
payload.put("contractText", buildFilePayloadList(contract, ContractLaunchConstants.FILE_CATEGORY_BODY));
payload.put("otherAttach", buildFilePayloadList(contract, ContractLaunchConstants.FILE_CATEGORY_OTHER));
payload.put("contractGistFile", buildFilePayloadList(contract, ContractLaunchConstants.FILE_CATEGORY_GIST));
return payload;
}
/** 构建数据采集合同报文(collectContract 接口的 payload */
private Map<String, Object> buildDataCollectionContractPayload(ContractLaunchDto contract) {
Map<String, Object> payload = new LinkedHashMap<>();
payload.put("c_name", contract.getContractName());
payload.put("c_code", contract.getLawContractCode() == null || contract.getLawContractCode().isBlank() ? contract.getContractCode() : contract.getLawContractCode());
payload.put("c_weNames", contract.getCompanyName());
payload.put("c_oppositeNames", contract.getCounterpartySummary());
payload.put("c_textSource", contract.getTextSource());
payload.put("c_mainContent", contract.getPrimaryContent());
payload.put("c_direction", contract.getPaymentDirection());
payload.put("c_method", contract.getValuationMode());
payload.put("c_subjectAMT", contract.getContractAmount());
payload.put("c_currency", contract.getCurrencyName());
payload.put("c_amountExplain", contract.getAmountExplain());
payload.put("c_type", contract.getContractTypeCode());
payload.put("c_termType", contract.getContractPeriodType());
payload.put("c_termExplain", contract.getPeriodExplain());
payload.put("c_termStart", contract.getEffectiveStart());
payload.put("c_termEnd", contract.getEffectiveEnd());
payload.put("c_qyztGAT", contract.getIsSgat());
payload.put("c_executor", contract.getExecutorAccount());
payload.put("c_openBidding", contract.getIsOpenBidding());
payload.put("c_currentBudget", contract.getIsYearBudget());
payload.put("c_major", contract.getIsMajorContract());
payload.put("c_signMethod", contract.getSealType());
payload.put("c_creator", contract.getInitiator());
payload.put("c_creatorPhone", contract.getCreatorPhone());
payload.put("c_createDept", contract.getInitiatorDept());
payload.put("c_zw", buildFilePayloadList(contract, ContractLaunchConstants.FILE_CATEGORY_BODY));
payload.put("c_attachs", buildFilePayloadList(contract, ContractLaunchConstants.FILE_CATEGORY_OTHER));
payload.put("c_signAttachs", buildFilePayloadList(contract, ContractLaunchConstants.FILE_CATEGORY_SIGNED));
payload.put("c_lxPlan", contract.getPerformancePlans());
Map<String, Object> seal = new LinkedHashMap<>();
seal.put("seal_isSeal", "1");
seal.put("seal_approveSame", "1");
seal.put("seal_type", contract.getSealType());
seal.put("seal_date", contract.getSignDate());
payload.put("c_seal", seal);
Map<String, Object> sign = new LinkedHashMap<>();
sign.put("sign_isSign", "1");
sign.put("sign_date", contract.getSignDate());
sign.put("sign_activeDate", contract.getActiveDate());
sign.put("sign_attachs", buildFilePayloadList(contract, ContractLaunchConstants.FILE_CATEGORY_SIGNED));
sign.put("sign_executor", contract.getExecutorAccount());
payload.put("c_sign", sign);
return payload;
}
/** 构建归档报文(pushArchive 接口的 payload */
private Map<String, Object> buildArchivePayload(ContractLaunchDto contract, ContractLaunchArchiveDto archiveDto) {
Map<String, Object> payload = new LinkedHashMap<>();
payload.put("contractCode", contract.getLawContractCode());
payload.put("contractSysId", contract.getContractSysId());
payload.put("Keeper", archiveDto == null ? null : archiveDto.getArchiveKeeper());
payload.put("KeeperUnit", archiveDto == null ? null : archiveDto.getArchiveKeeperUnit());
payload.put("KeeperUnitCode", archiveDto == null ? null : archiveDto.getArchiveKeeperUnitCode());
payload.put("archivePapers", List.of());
payload.put("archiveEles", (archiveDto == null || archiveDto.getArchiveFiles() == null) ? List.of() : archiveDto.getArchiveFiles());
return payload;
}
/** 按 fileCategory 提取文件列表,转为法务接口要求的附件格式 */
private List<Map<String, Object>> buildFilePayloadList(ContractLaunchDto contract, String fileCategory) {
return contract.getFileList().stream()
.filter(item -> fileCategory.equals(item.getFileCategory()))
.map(item -> {
Map<String, Object> map = new LinkedHashMap<>();
map.put("fileName", item.getFileName());
map.put("filePath", item.getFilePath());
map.put("fileSize", item.getFileSize());
map.put("fileType", item.getFileType());
return map;
}).collect(Collectors.toList());
}
private String trim(String value) {
return value == null ? null : value.trim();
}
}
@@ -0,0 +1,42 @@
package com.nbport.zgwl.contractlaunch.utils;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ThreadLocalRandom;
/**
* 合同编号工具
*
* contractSysId:本系统合同唯一标识,格式 CLS-yyyyMMddHHmmss-随机4位
* contractCode:业务合同编号,格式 合同类型编码-yyyyMMdd-随机4位(如 MM-20260522-1234
*/
public final class ContractLaunchCodeUtils {
private ContractLaunchCodeUtils() {
}
/** 生成合同系统唯一编码(CLS-时间戳-随机4位) */
public static String buildContractSysId() {
return "CLS-" + formatNow("yyyyMMddHHmmss") + "-" + randomDigits(4);
}
/** 生成业务合同编号(合同类型编码-日期-随机4位,如 MM-20260522-1234 */
public static String buildContractCode(String contractTypeCode) {
String typeCode = contractTypeCode == null || contractTypeCode.isBlank()
? "QT"
: contractTypeCode;
return typeCode + "-" + formatNow("yyyyMMdd") + "-" + randomDigits(4);
}
private static String formatNow(String pattern) {
return new SimpleDateFormat(pattern).format(new Date());
}
private static String randomDigits(int length) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < length; i++) {
builder.append(ThreadLocalRandom.current().nextInt(10));
}
return builder.toString();
}
}
@@ -0,0 +1,51 @@
package com.nbport.zgwl.contractlaunch.utils;
/**
* 合同发起模块常量
*
* 这里把状态值集中放一起,方便你后续改状态文案或补真实流程。
*/
public final class ContractLaunchConstants {
private ContractLaunchConstants() {
}
public static final String REQUEST_PREFIX = "/contract/launch";
public static final String STATUS_DRAFT = "draft";
public static final String STATUS_REVIEWING = "reviewing";
public static final String STATUS_REJECTED = "rejected";
public static final String STATUS_PENDING_SIGN = "pending_sign";
public static final String STATUS_SIGNING = "signing";
public static final String STATUS_PENDING_COLLECT = "pending_collect";
public static final String STATUS_PENDING_ARCHIVE = "pending_archive";
public static final String STATUS_COMPLETED = "completed";
public static final String STATUS_TERMINATED = "terminated";
public static final String APPROVE_STATUS_PENDING = "pending";
public static final String APPROVE_STATUS_APPROVED = "approved";
public static final String APPROVE_STATUS_REJECTED = "rejected";
public static final String FILE_CATEGORY_BODY = "body";
public static final String FILE_CATEGORY_OTHER = "other";
public static final String FILE_CATEGORY_GIST = "gist";
public static final String FILE_CATEGORY_SIGNED = "signed";
public static final String FILE_CATEGORY_ARCHIVE = "archive";
public static final String ACTION_SAVE = "save";
public static final String ACTION_SUBMIT = "submit";
public static final String ACTION_APPROVE = "approve";
public static final String ACTION_REJECT = "reject";
public static final String ACTION_SEAL_START = "seal_start";
public static final String ACTION_SEAL_FINISH = "seal_finish";
public static final String ACTION_COLLECT = "collect";
public static final String ACTION_ARCHIVE = "archive";
public static final String ACTION_DELETE = "delete";
public static final String ACTION_STATUS_SUCCESS = "success";
public static final String ACTION_STATUS_FAILED = "failed";
public static final String ACTION_STATUS_PENDING = "pending";
public static final String IS_DELETED_NO = "N";
public static final String IS_DELETED_YES = "Y";
}
@@ -0,0 +1,25 @@
package com.nbport.zgwl.entity;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 组织信息
*
* 当前项目里先作为一个简单对象使用,
* 后续接入真实权限系统时,可以直接替换成真实组织实体。
*/
@Data
public class SysOrgEntity implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/** 组织ID */
private String id;
/** 组织名称 */
private String orgName;
}
@@ -28,4 +28,12 @@ public class SysUserEntity extends BaseEntity<SysUserEntity> {
@TableField("email")
private String email;
/**
* 当前登录人的所属组织
*
* 这里不映射数据库字段,只用于业务代码里取组织信息。
*/
@TableField(exist = false)
private SysOrgEntity sysOrgEntity;
}
@@ -16,6 +16,38 @@ import java.util.concurrent.ThreadLocalRandom;
public final class ManifestCodeUtils {
private static final Map<String, String> CONTRACT_TYPE_CODE_MAP = Map.ofEntries(
Map.entry("MM", "MM"),
Map.entry("GY", "GY"),
Map.entry("ZY", "ZY"),
Map.entry("JK", "JK"),
Map.entry("BZ", "BZ"),
Map.entry("ZL", "ZL"),
Map.entry("RZ", "RZ"),
Map.entry("BL", "BL"),
Map.entry("CL", "CL"),
Map.entry("GC", "GC"),
Map.entry("YS", "YS"),
Map.entry("JS", "JS"),
Map.entry("BG", "BG"),
Map.entry("CC", "CC"),
Map.entry("WT", "WT"),
Map.entry("WY", "WY"),
Map.entry("HJ", "HJ"),
Map.entry("ZJ", "ZJ"),
Map.entry("HH", "HH"),
Map.entry("YG", "YG"),
Map.entry("YW", "YW"),
Map.entry("QT", "QT"),
Map.entry("YWBFP", "YWBFP"),
Map.entry("YWBFS", "YWBFS"),
Map.entry("YWIOP", "YWIOP"),
Map.entry("YWIOS", "YWIOS"),
Map.entry("YWDOP", "YWDOP"),
Map.entry("YWDOS", "YWDOS"),
Map.entry("YWBCP", "YWBCP"),
Map.entry("YWBCS", "YWBCS"),
Map.entry("YWOTP", "YWOTP"),
Map.entry("YWOTS", "YWOTS"),
Map.entry("买卖合同", "MM"),
Map.entry("采购合同", "CG"),
Map.entry("销售合同", "XS"),
@@ -0,0 +1,30 @@
package com.nbport.zgwl.utils;
import com.nbport.zgwl.entity.SysOrgEntity;
import com.nbport.zgwl.entity.SysUserEntity;
import org.springframework.stereotype.Component;
/**
* 登录用户获取组件
*
* 当前系统还没有真正接入统一认证,
* 所以这里先返回一个 mock 用户,便于业务代码先跑通。
* 后续接入真实系统时,直接把这里替换成真正的登录态获取逻辑即可。
*/
@Component
public class AdminSecurityManage {
public SysUserEntity getUser() {
SysOrgEntity orgEntity = new SysOrgEntity();
orgEntity.setId("ORG001");
orgEntity.setOrgName("浙港物流平台有限公司");
SysUserEntity user = new SysUserEntity();
user.setId(1L);
user.setUsername("admin");
user.setMobilePhone("13800000000");
user.setEmail("admin@test.com");
user.setSysOrgEntity(orgEntity);
return user;
}
}
@@ -0,0 +1,532 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.nbport.zgwl.contractlaunch.mapper.ContractLaunchMapper">
<resultMap id="ContractLaunchResult" type="com.nbport.zgwl.contractlaunch.dto.ContractLaunchDto">
<id property="id" column="ID"/>
<result property="contractSysId" column="CONTRACT_SYS_ID"/>
<result property="contractCode" column="CONTRACT_CODE"/>
<result property="lawContractCode" column="LAW_CONTRACT_CODE"/>
<result property="lawContractId" column="LAW_CONTRACT_ID"/>
<result property="contractName" column="CONTRACT_NAME"/>
<result property="contractType" column="CONTRACT_TYPE"/>
<result property="contractTypeCode" column="CONTRACT_TYPE_CODE"/>
<result property="contractSource" column="CONTRACT_SOURCE"/>
<result property="creationMode" column="CREATION_MODE"/>
<result property="templateId" column="TEMPLATE_ID"/>
<result property="templateCode" column="TEMPLATE_CODE"/>
<result property="templateName" column="TEMPLATE_NAME"/>
<result property="status" column="STATUS"/>
<result property="approveStatus" column="APPROVE_STATUS"/>
<result property="approveMessage" column="APPROVE_MESSAGE"/>
<result property="sealContractId" column="SEAL_CONTRACT_ID"/>
<result property="sealContractStatus" column="SEAL_CONTRACT_STATUS"/>
<result property="contractAmount" column="CONTRACT_AMOUNT"/>
<result property="currencyName" column="CURRENCY_NAME"/>
<result property="contractPeriodType" column="CONTRACT_PERIOD_TYPE"/>
<result property="periodExplain" column="PERIOD_EXPLAIN"/>
<result property="effectiveStart" column="EFFECTIVE_START"/>
<result property="effectiveEnd" column="EFFECTIVE_END"/>
<result property="paymentMethod" column="PAYMENT_METHOD"/>
<result property="primaryContent" column="PRIMARY_CONTENT"/>
<result property="amountExplain" column="AMOUNT_EXPLAIN"/>
<result property="valuationMode" column="VALUATION_MODE"/>
<result property="sealType" column="SEAL_TYPE"/>
<result property="textSource" column="TEXT_SOURCE"/>
<result property="mandateType" column="MANDATE_TYPE"/>
<result property="cargoType" column="CARGO_TYPE"/>
<result property="assistDepartmentName" column="ASSIST_DEPARTMENT_NAME"/>
<result property="executorAccount" column="EXECUTOR_ACCOUNT"/>
<result property="creatorPhone" column="CREATOR_PHONE"/>
<result property="selfCode" column="SELF_CODE"/>
<result property="mainContractCode" column="MAIN_CONTRACT_CODE"/>
<result property="signingSubjectCode" column="SIGNING_SUBJECT_CODE"/>
<result property="dateType" column="DATE_TYPE"/>
<result property="isAddit" column="IS_ADDIT"/>
<result property="isElectron" column="IS_ELECTRON"/>
<result property="paymentDirection" column="PAYMENT_DIRECTION"/>
<result property="pushUrl" column="PUSH_URL"/>
<result property="isMajorContract" column="IS_MAJOR_CONTRACT"/>
<result property="isOpenBidding" column="IS_OPEN_BIDDING"/>
<result property="isYearBudget" column="IS_YEAR_BUDGET"/>
<result property="isShare" column="IS_SHARE"/>
<result property="contractNature" column="CONTRACT_NATURE"/>
<result property="isSgat" column="IS_SGAT"/>
<result property="isNormal" column="IS_NORMAL"/>
<result property="isTerminated" column="IS_TERMINATED"/>
<result property="isSingleAgreement" column="IS_SINGLE_AGREEMENT"/>
<result property="biddingNo" column="BIDDING_NO"/>
<result property="openBiddingRemark" column="OPEN_BIDDING_REMARK"/>
<result property="contractGistRemark" column="CONTRACT_GIST_REMARK"/>
<result property="ewAmountType" column="EW_AMOUNT_TYPE"/>
<result property="djAmount" column="DJ_AMOUNT"/>
<result property="yjAmount" column="YJ_AMOUNT"/>
<result property="yfkAmount" column="YFK_AMOUNT"/>
<result property="bzjAmount" column="BZJ_AMOUNT"/>
<result property="bodySummary" column="BODY_SUMMARY"/>
<result property="contractTextFileName" column="CONTRACT_TEXT_FILE_NAME"/>
<result property="contractTextFilePath" column="CONTRACT_TEXT_FILE_PATH"/>
<result property="contractTextFileType" column="CONTRACT_TEXT_FILE_TYPE"/>
<result property="contractTextFileSize" column="CONTRACT_TEXT_FILE_SIZE"/>
<result property="signedFileName" column="SIGNED_FILE_NAME"/>
<result property="signedFilePath" column="SIGNED_FILE_PATH"/>
<result property="signedFileType" column="SIGNED_FILE_TYPE"/>
<result property="signedFileSize" column="SIGNED_FILE_SIZE"/>
<result property="signedOfflineReason" column="SIGNED_OFFLINE_REASON"/>
<result property="signDate" column="SIGN_DATE"/>
<result property="activeDate" column="ACTIVE_DATE"/>
<result property="archiveDate" column="ARCHIVE_DATE"/>
<result property="archiveKeeper" column="ARCHIVE_KEEPER"/>
<result property="archiveKeeperUnit" column="ARCHIVE_KEEPER_UNIT"/>
<result property="archiveKeeperUnitCode" column="ARCHIVE_KEEPER_UNIT_CODE"/>
<result property="invoiceDate" column="INVOICE_DATE"/>
<result property="receiveDate" column="RECEIVE_DATE"/>
<result property="remindDays" column="REMIND_DAYS"/>
<result property="initiator" column="INITIATOR"/>
<result property="initiatorDept" column="INITIATOR_DEPT"/>
<result property="companyName" column="COMPANY_NAME"/>
<result property="orgId" column="ORG_ID"/>
<result property="queryScope" column="QUERY_SCOPE"/>
<result property="createBy" column="CREATE_BY"/>
<result property="createTime" column="CREATE_TIME"/>
<result property="updateBy" column="UPDATE_BY"/>
<result property="updateTime" column="UPDATE_TIME"/>
<result property="isDeleted" column="IS_DELETED"/>
<result property="remark" column="REMARK"/>
</resultMap>
<resultMap id="PartyResult" type="com.nbport.zgwl.contractlaunch.dto.ContractLaunchPartyDto">
<id property="id" column="ID"/>
<result property="contractId" column="CONTRACT_ID"/>
<result property="roleCode" column="ROLE_CODE"/>
<result property="roleName" column="ROLE_NAME"/>
<result property="sortOrder" column="SORT_ORDER"/>
<result property="partnerId" column="PARTNER_ID"/>
<result property="oppositeId" column="OPPOSITE_ID"/>
<result property="companyName" column="COMPANY_NAME"/>
<result property="companyType" column="COMPANY_TYPE"/>
<result property="oppositeCharacter" column="OPPOSITE_CHARACTER"/>
<result property="contactName" column="CONTACT_NAME"/>
<result property="contactPhone" column="CONTACT_PHONE"/>
<result property="contactEmail" column="CONTACT_EMAIL"/>
<result property="contactAddress" column="CONTACT_ADDRESS"/>
<result property="registeredAddress" column="REGISTERED_ADDRESS"/>
<result property="legalRepresentative" column="LEGAL_REPRESENTATIVE"/>
<result property="creditCode" column="CREDIT_CODE"/>
<result property="bankName" column="BANK_NAME"/>
<result property="bankAccount" column="BANK_ACCOUNT"/>
<result property="naturalPersonIdType" column="NATURAL_PERSON_ID_TYPE"/>
<result property="naturalPersonIdNumber" column="NATURAL_PERSON_ID_NUMBER"/>
<result property="isGroupInternal" column="IS_GROUP_INTERNAL"/>
<result property="isHongKongMacaoTaiwan" column="IS_HONG_KONG_MACAO_TAIWAN"/>
<result property="remark" column="REMARK"/>
</resultMap>
<resultMap id="FileResult" type="com.nbport.zgwl.contractlaunch.dto.ContractLaunchFileDto">
<id property="id" column="ID"/>
<result property="contractId" column="CONTRACT_ID"/>
<result property="fileCategory" column="FILE_CATEGORY"/>
<result property="fileName" column="FILE_NAME"/>
<result property="filePath" column="FILE_PATH"/>
<result property="fileType" column="FILE_TYPE"/>
<result property="fileSize" column="FILE_SIZE"/>
<result property="sortOrder" column="SORT_ORDER"/>
<result property="remark" column="REMARK"/>
</resultMap>
<resultMap id="PlanResult" type="com.nbport.zgwl.contractlaunch.dto.ContractLaunchPlanDto">
<id property="id" column="ID"/>
<result property="contractId" column="CONTRACT_ID"/>
<result property="planMatter" column="PLAN_MATTER"/>
<result property="planWhere" column="PLAN_WHERE"/>
<result property="planTime" column="PLAN_TIME"/>
<result property="planDay" column="PLAN_DAY"/>
<result property="planMoney" column="PLAN_MONEY"/>
<result property="planSubjectCode" column="PLAN_SUBJECT_CODE"/>
<result property="planSubjectName" column="PLAN_SUBJECT_NAME"/>
<result property="planDetail" column="PLAN_DETAIL"/>
<result property="planStatus" column="PLAN_STATUS"/>
<result property="remark" column="REMARK"/>
</resultMap>
<resultMap id="LogResult" type="com.nbport.zgwl.contractlaunch.dto.ContractLaunchLogDto">
<id property="id" column="ID"/>
<result property="contractId" column="CONTRACT_ID"/>
<result property="actionType" column="ACTION_TYPE"/>
<result property="actionName" column="ACTION_NAME"/>
<result property="actionStatus" column="ACTION_STATUS"/>
<result property="operatorName" column="OPERATOR_NAME"/>
<result property="operatorPhone" column="OPERATOR_PHONE"/>
<result property="actionTime" column="ACTION_TIME"/>
<result property="actionContent" column="ACTION_CONTENT"/>
<result property="callbackPayload" column="CALLBACK_PAYLOAD"/>
<result property="remark" column="REMARK"/>
</resultMap>
<sql id="mainColumns">
select ID, CONTRACT_SYS_ID, CONTRACT_CODE, LAW_CONTRACT_CODE, LAW_CONTRACT_ID,
CONTRACT_NAME, CONTRACT_TYPE, CONTRACT_TYPE_CODE, CONTRACT_SOURCE, CREATION_MODE,
TEMPLATE_ID, TEMPLATE_CODE, TEMPLATE_NAME, STATUS, APPROVE_STATUS, APPROVE_MESSAGE,
SEAL_CONTRACT_ID, SEAL_CONTRACT_STATUS, CONTRACT_AMOUNT, CURRENCY_NAME,
CONTRACT_PERIOD_TYPE, PERIOD_EXPLAIN, EFFECTIVE_START, EFFECTIVE_END,
PAYMENT_METHOD, PRIMARY_CONTENT, AMOUNT_EXPLAIN, VALUATION_MODE, SEAL_TYPE,
TEXT_SOURCE, MANDATE_TYPE, CARGO_TYPE, ASSIST_DEPARTMENT_NAME, EXECUTOR_ACCOUNT,
CREATOR_PHONE, SELF_CODE, MAIN_CONTRACT_CODE, SIGNING_SUBJECT_CODE, DATE_TYPE, IS_ADDIT, IS_ELECTRON,
PAYMENT_DIRECTION, PUSH_URL, IS_MAJOR_CONTRACT, IS_OPEN_BIDDING, IS_YEAR_BUDGET, IS_SHARE,
CONTRACT_NATURE, IS_SGAT, IS_NORMAL, IS_TERMINATED, IS_SINGLE_AGREEMENT,
BIDDING_NO, OPEN_BIDDING_REMARK, CONTRACT_GIST_REMARK,
EW_AMOUNT_TYPE, DJ_AMOUNT, YJ_AMOUNT, YFK_AMOUNT, BZJ_AMOUNT, BODY_SUMMARY,
CONTRACT_TEXT_FILE_NAME, CONTRACT_TEXT_FILE_PATH, CONTRACT_TEXT_FILE_TYPE, CONTRACT_TEXT_FILE_SIZE,
SIGNED_FILE_NAME, SIGNED_FILE_PATH, SIGNED_FILE_TYPE, SIGNED_FILE_SIZE, SIGNED_OFFLINE_REASON,
SIGN_DATE, ACTIVE_DATE, ARCHIVE_DATE, ARCHIVE_KEEPER, ARCHIVE_KEEPER_UNIT,
ARCHIVE_KEEPER_UNIT_CODE, INVOICE_DATE, RECEIVE_DATE, REMIND_DAYS,
INITIATOR, INITIATOR_DEPT, COMPANY_NAME, ORG_ID, QUERY_SCOPE,
CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, IS_DELETED, REMARK
from SEAL_CONTRACT_LAUNCH_MAIN
</sql>
<select id="selectMainSeqNextVal" resultType="java.lang.Long">
select SEQ_SEAL_CONTRACT_LAUNCH_MAIN.NEXTVAL from dual
</select>
<select id="selectPartySeqNextVal" resultType="java.lang.Long">
select SEQ_SEAL_CONTRACT_LAUNCH_PARTY.NEXTVAL from dual
</select>
<select id="selectFileSeqNextVal" resultType="java.lang.Long">
select SEQ_SEAL_CONTRACT_LAUNCH_FILE.NEXTVAL from dual
</select>
<select id="selectPlanSeqNextVal" resultType="java.lang.Long">
select SEQ_SEAL_CONTRACT_LAUNCH_PLAN.NEXTVAL from dual
</select>
<select id="selectLogSeqNextVal" resultType="java.lang.Long">
select SEQ_SEAL_CONTRACT_LAUNCH_LOG.NEXTVAL from dual
</select>
<select id="selectContractPage" resultMap="ContractLaunchResult">
<include refid="mainColumns"/>
<where>
IS_DELETED = 'N'
<if test="query.contractName != null and query.contractName != ''">
and CONTRACT_NAME like CONCAT(CONCAT('%', #{query.contractName}), '%')
</if>
<if test="query.contractCode != null and query.contractCode != ''">
and CONTRACT_CODE like CONCAT(CONCAT('%', #{query.contractCode}), '%')
</if>
<if test="query.contractType != null and query.contractType != ''">
and CONTRACT_TYPE = #{query.contractType}
</if>
<if test="query.status != null and query.status != ''">
and STATUS = #{query.status}
</if>
<if test="query.dateStart != null and query.dateStart != ''">
and CREATE_TIME >= TO_DATE(#{query.dateStart} || ' 00:00:00', 'YYYY-MM-DD HH24:MI:SS')
</if>
<if test="query.dateEnd != null and query.dateEnd != ''">
and CREATE_TIME &lt;= TO_DATE(#{query.dateEnd} || ' 23:59:59', 'YYYY-MM-DD HH24:MI:SS')
</if>
</where>
order by CREATE_TIME desc, ID desc
</select>
<select id="selectContractById" resultMap="ContractLaunchResult">
<include refid="mainColumns"/>
where ID = #{id}
and IS_DELETED = 'N'
</select>
<select id="selectContractByContractSysId" resultMap="ContractLaunchResult">
<include refid="mainColumns"/>
where CONTRACT_SYS_ID = #{contractSysId}
and IS_DELETED = 'N'
</select>
<insert id="insertContract" parameterType="com.nbport.zgwl.contractlaunch.dto.ContractLaunchDto">
insert into SEAL_CONTRACT_LAUNCH_MAIN (
ID, CONTRACT_SYS_ID, CONTRACT_CODE, LAW_CONTRACT_CODE, LAW_CONTRACT_ID,
CONTRACT_NAME, CONTRACT_TYPE, CONTRACT_TYPE_CODE, CONTRACT_SOURCE, CREATION_MODE,
TEMPLATE_ID, TEMPLATE_CODE, TEMPLATE_NAME, STATUS, APPROVE_STATUS, APPROVE_MESSAGE,
SEAL_CONTRACT_ID, SEAL_CONTRACT_STATUS, CONTRACT_AMOUNT, CURRENCY_NAME,
CONTRACT_PERIOD_TYPE, PERIOD_EXPLAIN, EFFECTIVE_START, EFFECTIVE_END,
PAYMENT_METHOD, PRIMARY_CONTENT, AMOUNT_EXPLAIN, VALUATION_MODE, SEAL_TYPE,
TEXT_SOURCE, MANDATE_TYPE, CARGO_TYPE, ASSIST_DEPARTMENT_NAME, EXECUTOR_ACCOUNT,
CREATOR_PHONE, SELF_CODE, MAIN_CONTRACT_CODE, SIGNING_SUBJECT_CODE, DATE_TYPE, IS_ADDIT, IS_ELECTRON,
PAYMENT_DIRECTION, PUSH_URL, IS_MAJOR_CONTRACT, IS_OPEN_BIDDING, IS_YEAR_BUDGET, IS_SHARE,
CONTRACT_NATURE, IS_SGAT, IS_NORMAL, IS_TERMINATED, IS_SINGLE_AGREEMENT,
BIDDING_NO, OPEN_BIDDING_REMARK, CONTRACT_GIST_REMARK,
EW_AMOUNT_TYPE, DJ_AMOUNT, YJ_AMOUNT, YFK_AMOUNT, BZJ_AMOUNT, BODY_SUMMARY,
CONTRACT_TEXT_FILE_NAME, CONTRACT_TEXT_FILE_PATH, CONTRACT_TEXT_FILE_TYPE, CONTRACT_TEXT_FILE_SIZE,
SIGNED_FILE_NAME, SIGNED_FILE_PATH, SIGNED_FILE_TYPE, SIGNED_FILE_SIZE, SIGNED_OFFLINE_REASON,
SIGN_DATE, ACTIVE_DATE, ARCHIVE_DATE, ARCHIVE_KEEPER, ARCHIVE_KEEPER_UNIT,
ARCHIVE_KEEPER_UNIT_CODE, INVOICE_DATE, RECEIVE_DATE, REMIND_DAYS,
INITIATOR, INITIATOR_DEPT, COMPANY_NAME, ORG_ID, QUERY_SCOPE,
CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, IS_DELETED, REMARK
) values (
#{id}, #{contractSysId}, #{contractCode}, #{lawContractCode}, #{lawContractId},
#{contractName}, #{contractType}, #{contractTypeCode}, #{contractSource}, #{creationMode},
#{templateId}, #{templateCode}, #{templateName}, #{status}, #{approveStatus}, #{approveMessage},
#{sealContractId}, #{sealContractStatus}, #{contractAmount}, #{currencyName},
#{contractPeriodType}, #{periodExplain}, #{effectiveStart}, #{effectiveEnd},
#{paymentMethod}, #{primaryContent}, #{amountExplain}, #{valuationMode}, #{sealType},
#{textSource}, #{mandateType}, #{cargoType}, #{assistDepartmentName}, #{executorAccount},
#{creatorPhone}, #{selfCode}, #{mainContractCode}, #{signingSubjectCode}, #{dateType}, #{isAddit}, #{isElectron},
#{paymentDirection}, #{pushUrl}, #{isMajorContract}, #{isOpenBidding}, #{isYearBudget}, #{isShare},
#{contractNature}, #{isSgat}, #{isNormal}, #{isTerminated}, #{isSingleAgreement},
#{biddingNo}, #{openBiddingRemark}, #{contractGistRemark},
#{ewAmountType}, #{djAmount}, #{yjAmount}, #{yfkAmount}, #{bzjAmount}, #{bodySummary},
#{contractTextFileName}, #{contractTextFilePath}, #{contractTextFileType}, #{contractTextFileSize},
#{signedFileName}, #{signedFilePath}, #{signedFileType}, #{signedFileSize}, #{signedOfflineReason},
#{signDate}, #{activeDate}, #{archiveDate}, #{archiveKeeper}, #{archiveKeeperUnit},
#{archiveKeeperUnitCode}, #{invoiceDate}, #{receiveDate}, #{remindDays},
#{initiator}, #{initiatorDept}, #{companyName}, #{orgId}, #{queryScope},
#{createBy}, #{createTime}, #{updateBy}, #{updateTime}, #{isDeleted}, #{remark}
)
</insert>
<update id="updateContract" parameterType="com.nbport.zgwl.contractlaunch.dto.ContractLaunchDto">
update SEAL_CONTRACT_LAUNCH_MAIN
<trim prefix="set" suffixOverrides=",">
LAW_CONTRACT_CODE = #{lawContractCode},
LAW_CONTRACT_ID = #{lawContractId},
CONTRACT_NAME = #{contractName},
CONTRACT_TYPE = #{contractType},
CONTRACT_TYPE_CODE = #{contractTypeCode},
CONTRACT_SOURCE = #{contractSource},
CREATION_MODE = #{creationMode},
TEMPLATE_ID = #{templateId},
TEMPLATE_CODE = #{templateCode},
TEMPLATE_NAME = #{templateName},
STATUS = #{status},
APPROVE_STATUS = #{approveStatus},
APPROVE_MESSAGE = #{approveMessage},
SEAL_CONTRACT_ID = #{sealContractId},
SEAL_CONTRACT_STATUS = #{sealContractStatus},
CONTRACT_AMOUNT = #{contractAmount},
CURRENCY_NAME = #{currencyName},
CONTRACT_PERIOD_TYPE = #{contractPeriodType},
PERIOD_EXPLAIN = #{periodExplain},
EFFECTIVE_START = #{effectiveStart},
EFFECTIVE_END = #{effectiveEnd},
PAYMENT_METHOD = #{paymentMethod},
PRIMARY_CONTENT = #{primaryContent},
AMOUNT_EXPLAIN = #{amountExplain},
VALUATION_MODE = #{valuationMode},
SEAL_TYPE = #{sealType},
TEXT_SOURCE = #{textSource},
MANDATE_TYPE = #{mandateType},
CARGO_TYPE = #{cargoType},
ASSIST_DEPARTMENT_NAME = #{assistDepartmentName},
EXECUTOR_ACCOUNT = #{executorAccount},
CREATOR_PHONE = #{creatorPhone},
SELF_CODE = #{selfCode},
MAIN_CONTRACT_CODE = #{mainContractCode},
SIGNING_SUBJECT_CODE = #{signingSubjectCode},
DATE_TYPE = #{dateType},
IS_ADDIT = #{isAddit},
IS_ELECTRON = #{isElectron},
PAYMENT_DIRECTION = #{paymentDirection},
PUSH_URL = #{pushUrl},
IS_MAJOR_CONTRACT = #{isMajorContract},
IS_OPEN_BIDDING = #{isOpenBidding},
IS_YEAR_BUDGET = #{isYearBudget},
IS_SHARE = #{isShare},
CONTRACT_NATURE = #{contractNature},
IS_SGAT = #{isSgat},
IS_NORMAL = #{isNormal},
IS_TERMINATED = #{isTerminated},
IS_SINGLE_AGREEMENT = #{isSingleAgreement},
BIDDING_NO = #{biddingNo},
OPEN_BIDDING_REMARK = #{openBiddingRemark},
CONTRACT_GIST_REMARK = #{contractGistRemark},
EW_AMOUNT_TYPE = #{ewAmountType},
DJ_AMOUNT = #{djAmount},
YJ_AMOUNT = #{yjAmount},
YFK_AMOUNT = #{yfkAmount},
BZJ_AMOUNT = #{bzjAmount},
BODY_SUMMARY = #{bodySummary},
CONTRACT_TEXT_FILE_NAME = #{contractTextFileName},
CONTRACT_TEXT_FILE_PATH = #{contractTextFilePath},
CONTRACT_TEXT_FILE_TYPE = #{contractTextFileType},
CONTRACT_TEXT_FILE_SIZE = #{contractTextFileSize},
SIGNED_FILE_NAME = #{signedFileName},
SIGNED_FILE_PATH = #{signedFilePath},
SIGNED_FILE_TYPE = #{signedFileType},
SIGNED_FILE_SIZE = #{signedFileSize},
SIGNED_OFFLINE_REASON = #{signedOfflineReason},
SIGN_DATE = #{signDate},
ACTIVE_DATE = #{activeDate},
ARCHIVE_DATE = #{archiveDate},
ARCHIVE_KEEPER = #{archiveKeeper},
ARCHIVE_KEEPER_UNIT = #{archiveKeeperUnit},
ARCHIVE_KEEPER_UNIT_CODE = #{archiveKeeperUnitCode},
INVOICE_DATE = #{invoiceDate},
RECEIVE_DATE = #{receiveDate},
REMIND_DAYS = #{remindDays},
INITIATOR = #{initiator},
INITIATOR_DEPT = #{initiatorDept},
COMPANY_NAME = #{companyName},
ORG_ID = #{orgId},
QUERY_SCOPE = #{queryScope},
UPDATE_BY = #{updateBy},
UPDATE_TIME = #{updateTime},
IS_DELETED = #{isDeleted},
REMARK = #{remark},
</trim>
where ID = #{id}
and IS_DELETED = 'N'
</update>
<update id="deleteContract">
update SEAL_CONTRACT_LAUNCH_MAIN
set IS_DELETED = 'Y',
UPDATE_BY = #{updateBy},
UPDATE_TIME = SYSDATE
where ID = #{id}
and IS_DELETED = 'N'
</update>
<insert id="batchInsertParty">
INSERT ALL
<foreach collection="list" item="item">
INTO SEAL_CONTRACT_LAUNCH_PARTY (
ID, CONTRACT_ID, ROLE_CODE, ROLE_NAME, SORT_ORDER, PARTNER_ID, OPPOSITE_ID,
COMPANY_NAME, COMPANY_TYPE, OPPOSITE_CHARACTER, CONTACT_NAME, CONTACT_PHONE,
CONTACT_EMAIL, CONTACT_ADDRESS, REGISTERED_ADDRESS, LEGAL_REPRESENTATIVE,
CREDIT_CODE, BANK_NAME, BANK_ACCOUNT, NATURAL_PERSON_ID_TYPE, NATURAL_PERSON_ID_NUMBER,
IS_GROUP_INTERNAL, IS_HONG_KONG_MACAO_TAIWAN, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, IS_DELETED, REMARK
) VALUES (
#{item.id}, #{item.contractId}, #{item.roleCode}, #{item.roleName}, #{item.sortOrder}, #{item.partnerId}, #{item.oppositeId},
#{item.companyName}, #{item.companyType}, #{item.oppositeCharacter}, #{item.contactName}, #{item.contactPhone},
#{item.contactEmail}, #{item.contactAddress}, #{item.registeredAddress}, #{item.legalRepresentative},
#{item.creditCode}, #{item.bankName}, #{item.bankAccount}, #{item.naturalPersonIdType}, #{item.naturalPersonIdNumber},
#{item.isGroupInternal}, #{item.isHongKongMacaoTaiwan}, #{createBy}, SYSDATE, #{updateBy}, SYSDATE, 'N', #{item.remark}
)
</foreach>
SELECT 1 FROM DUAL
</insert>
<insert id="batchInsertFile">
INSERT ALL
<foreach collection="list" item="item">
INTO SEAL_CONTRACT_LAUNCH_FILE (
ID, CONTRACT_ID, FILE_CATEGORY, FILE_NAME, FILE_PATH, FILE_TYPE, FILE_SIZE,
SORT_ORDER, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, IS_DELETED, REMARK
) VALUES (
#{item.id}, #{item.contractId}, #{item.fileCategory}, #{item.fileName}, #{item.filePath}, #{item.fileType}, #{item.fileSize},
#{item.sortOrder}, #{createBy}, SYSDATE, #{updateBy}, SYSDATE, 'N', #{item.remark}
)
</foreach>
SELECT 1 FROM DUAL
</insert>
<insert id="batchInsertPlan">
INSERT ALL
<foreach collection="list" item="item">
INTO SEAL_CONTRACT_LAUNCH_PLAN (
ID, CONTRACT_ID, PLAN_MATTER, PLAN_WHERE, PLAN_TIME, PLAN_DAY, PLAN_MONEY,
PLAN_SUBJECT_CODE, PLAN_SUBJECT_NAME, PLAN_DETAIL, PLAN_STATUS,
CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, IS_DELETED, REMARK
) VALUES (
#{item.id}, #{item.contractId}, #{item.planMatter}, #{item.planWhere}, #{item.planTime}, #{item.planDay}, #{item.planMoney},
#{item.planSubjectCode}, #{item.planSubjectName}, #{item.planDetail}, #{item.planStatus},
#{createBy}, SYSDATE, #{updateBy}, SYSDATE, 'N', #{item.remark}
)
</foreach>
SELECT 1 FROM DUAL
</insert>
<insert id="insertLog" parameterType="com.nbport.zgwl.contractlaunch.dto.ContractLaunchLogDto">
insert into SEAL_CONTRACT_LAUNCH_LOG (
ID, CONTRACT_ID, ACTION_TYPE, ACTION_NAME, ACTION_STATUS, OPERATOR_NAME, OPERATOR_PHONE,
ACTION_TIME, ACTION_CONTENT, CALLBACK_PAYLOAD, REMARK
) values (
#{id}, #{contractId}, #{actionType}, #{actionName}, #{actionStatus}, #{operatorName}, #{operatorPhone},
#{actionTime}, #{actionContent}, #{callbackPayload}, #{remark}
)
</insert>
<update id="deletePartyByContractId">
update SEAL_CONTRACT_LAUNCH_PARTY
set IS_DELETED = 'Y',
UPDATE_BY = #{updateBy},
UPDATE_TIME = SYSDATE
where CONTRACT_ID = #{contractId}
and IS_DELETED = 'N'
</update>
<update id="deleteFileByContractId">
update SEAL_CONTRACT_LAUNCH_FILE
set IS_DELETED = 'Y',
UPDATE_BY = #{updateBy},
UPDATE_TIME = SYSDATE
where CONTRACT_ID = #{contractId}
and IS_DELETED = 'N'
</update>
<update id="deleteFileByContractIdAndCategory">
update SEAL_CONTRACT_LAUNCH_FILE
set IS_DELETED = 'Y',
UPDATE_BY = #{updateBy},
UPDATE_TIME = SYSDATE
where CONTRACT_ID = #{contractId}
and FILE_CATEGORY = #{fileCategory}
and IS_DELETED = 'N'
</update>
<update id="deletePlanByContractId">
update SEAL_CONTRACT_LAUNCH_PLAN
set IS_DELETED = 'Y',
UPDATE_BY = #{updateBy},
UPDATE_TIME = SYSDATE
where CONTRACT_ID = #{contractId}
and IS_DELETED = 'N'
</update>
<select id="selectPartyByContractIds" resultMap="PartyResult">
select ID, CONTRACT_ID, ROLE_CODE, ROLE_NAME, SORT_ORDER, PARTNER_ID, OPPOSITE_ID,
COMPANY_NAME, COMPANY_TYPE, OPPOSITE_CHARACTER, CONTACT_NAME, CONTACT_PHONE,
CONTACT_EMAIL, CONTACT_ADDRESS, REGISTERED_ADDRESS, LEGAL_REPRESENTATIVE,
CREDIT_CODE, BANK_NAME, BANK_ACCOUNT, NATURAL_PERSON_ID_TYPE, NATURAL_PERSON_ID_NUMBER,
IS_GROUP_INTERNAL, IS_HONG_KONG_MACAO_TAIWAN, REMARK
from SEAL_CONTRACT_LAUNCH_PARTY
where IS_DELETED = 'N'
and CONTRACT_ID in
<foreach collection="contractIds" item="contractId" open="(" separator="," close=")">
#{contractId}
</foreach>
order by CONTRACT_ID asc, SORT_ORDER asc, ID asc
</select>
<select id="selectFileByContractIds" resultMap="FileResult">
select ID, CONTRACT_ID, FILE_CATEGORY, FILE_NAME, FILE_PATH, FILE_TYPE, FILE_SIZE, SORT_ORDER, REMARK
from SEAL_CONTRACT_LAUNCH_FILE
where IS_DELETED = 'N'
and CONTRACT_ID in
<foreach collection="contractIds" item="contractId" open="(" separator="," close=")">
#{contractId}
</foreach>
order by CONTRACT_ID asc, SORT_ORDER asc, ID asc
</select>
<select id="selectPlanByContractIds" resultMap="PlanResult">
select ID, CONTRACT_ID, PLAN_MATTER, PLAN_WHERE, PLAN_TIME, PLAN_DAY, PLAN_MONEY,
PLAN_SUBJECT_CODE, PLAN_SUBJECT_NAME, PLAN_DETAIL, PLAN_STATUS, REMARK
from SEAL_CONTRACT_LAUNCH_PLAN
where IS_DELETED = 'N'
and CONTRACT_ID in
<foreach collection="contractIds" item="contractId" open="(" separator="," close=")">
#{contractId}
</foreach>
order by CONTRACT_ID asc, PLAN_TIME asc, ID asc
</select>
<select id="selectLogByContractIds" resultMap="LogResult">
select ID, CONTRACT_ID, ACTION_TYPE, ACTION_NAME, ACTION_STATUS, OPERATOR_NAME, OPERATOR_PHONE,
ACTION_TIME, ACTION_CONTENT, CALLBACK_PAYLOAD, REMARK
from SEAL_CONTRACT_LAUNCH_LOG
where CONTRACT_ID in
<foreach collection="contractIds" item="contractId" open="(" separator="," close=")">
#{contractId}
</foreach>
order by CONTRACT_ID asc, ACTION_TIME desc, ID desc
</select>
</mapper>
@@ -30,7 +30,7 @@
</resultMap>
<sql id="selectTemplateColumns">
select id, template_code, template_name, source, contract_type, self_party_role,
select id, template_code, template_name, source, contract_type,
version, status, variable_count, description, usage_tip,
template_file_name, template_file_path,
publish_org_ids_json, publish_org_names_json, variable_mappings_json,
@@ -73,7 +73,7 @@
<insert id="insertTemplate" parameterType="com.nbport.zgwl.manifest.dto.ContractTemplateDto">
insert into contract_template_manage
(
id, template_code, template_name, source, contract_type, self_party_role,
id, template_code, template_name, source, contract_type,
version, status, variable_count, description, usage_tip,
template_file_name, template_file_path,
publish_org_ids_json, publish_org_names_json, variable_mappings_json,
@@ -12,8 +12,14 @@
<resultMap id="PartnerManageResult" type="com.nbport.zgwl.partner.dto.PartnerManageDto">
<id property="customerSysid" column="CUSTOMER_SYSID"/>
<result property="customerRegno" column="CUSTOMER_REGNO"/>
<result property="customerNo" column="CUSTOMER_NO"/>
<result property="customerNameC" column="CUSTOMER_NAME_C"/>
<result property="customerTaxno" column="CUSTOMER_TAXNO"/>
<result property="customerAddress" column="CUSTOMER_ADDRESS"/>
<result property="officephone" column="OFFICEPHONE"/>
<result property="customerBank" column="CUSTOMER_BANK"/>
<result property="customerBankaccount" column="CUSTOMER_BANKACCOUNT"/>
<result property="customerRegaddr" column="CUSTOMER_REGADDR"/>
<result property="emailAddress" column="EMAIL_ADDRESS"/>
<result property="oppositeId" column="OPPOSITE_ID"/>
@@ -60,7 +66,8 @@
</resultMap>
<sql id="selectPartnerColumns">
select CUSTOMER_SYSID, CUSTOMER_NAME_C, CUSTOMER_TAXNO, CUSTOMER_REGADDR,
select CUSTOMER_SYSID, CUSTOMER_REGNO, CUSTOMER_NO, CUSTOMER_NAME_C, CUSTOMER_TAXNO,
CUSTOMER_ADDRESS, OFFICEPHONE, CUSTOMER_BANK, CUSTOMER_BANKACCOUNT, CUSTOMER_REGADDR,
EMAIL_ADDRESS, OPPOSITE_ID, OPPOSITE_CHARACTER, GAT_FLAG, GROUP_FLAG,
COUNTRY, COUNTRY_NAME, LEGAL_PERSON_NAME, CERTIFICATE_TYPE,
CERTIFICATE_NUM, TIN_CODE, REGISTERED_CAPITAL, REG_CAPITAL,
@@ -0,0 +1,33 @@
-- 合同发起模块字段补丁
-- 适用场景:如果你已经执行过旧版 zgwl_contract_launch_oracle.sql,再执行本文件补齐本次新增字段。
-- 如果是新库,直接执行 zgwl_contract_launch_oracle.sql 即可,不需要执行本补丁。
ALTER TABLE SEAL_CONTRACT_LAUNCH_MAIN ADD SIGNING_SUBJECT_CODE VARCHAR2(500 CHAR);
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.SIGNING_SUBJECT_CODE IS '签约主体编码,多个用逗号分隔';
ALTER TABLE SEAL_CONTRACT_LAUNCH_MAIN ADD DATE_TYPE VARCHAR2(10 CHAR);
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.DATE_TYPE IS '固定期间日期类型:0年 1月 2日';
ALTER TABLE SEAL_CONTRACT_LAUNCH_MAIN ADD PUSH_URL VARCHAR2(500 CHAR);
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.PUSH_URL IS '法务审批回调地址';
ALTER TABLE SEAL_CONTRACT_LAUNCH_MAIN ADD EW_AMOUNT_TYPE VARCHAR2(100 CHAR);
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.EW_AMOUNT_TYPE IS '额外金额类型:DJ定金 YJ押金 YFK预付款 BZJ保证金';
ALTER TABLE SEAL_CONTRACT_LAUNCH_MAIN ADD DJ_AMOUNT NUMBER(20, 2);
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.DJ_AMOUNT IS '定金金额';
ALTER TABLE SEAL_CONTRACT_LAUNCH_MAIN ADD YJ_AMOUNT NUMBER(20, 2);
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.YJ_AMOUNT IS '押金金额';
ALTER TABLE SEAL_CONTRACT_LAUNCH_MAIN ADD YFK_AMOUNT NUMBER(20, 2);
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.YFK_AMOUNT IS '预付款金额';
ALTER TABLE SEAL_CONTRACT_LAUNCH_MAIN ADD BZJ_AMOUNT NUMBER(20, 2);
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.BZJ_AMOUNT IS '保证金金额';
ALTER TABLE SEAL_CONTRACT_LAUNCH_PLAN ADD PLAN_SUBJECT_CODE VARCHAR2(100 CHAR);
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PLAN.PLAN_SUBJECT_CODE IS '所属主体编码';
ALTER TABLE SEAL_CONTRACT_LAUNCH_PLAN ADD PLAN_SUBJECT_NAME VARCHAR2(200 CHAR);
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PLAN.PLAN_SUBJECT_NAME IS '所属主体名称';
+455
View File
@@ -0,0 +1,455 @@
-- =============================================
-- Oracle version for contract launch module
-- Execute with:
-- sqlplus developer/dev123@localhost/XEPDB1 @zgwl_contract_launch_oracle.sql
-- =============================================
WHENEVER SQLERROR EXIT SQL.SQLCODE;
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE SEAL_CONTRACT_LAUNCH_LOG';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -942 THEN RAISE; END IF;
END;
/
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE SEAL_CONTRACT_LAUNCH_PLAN';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -942 THEN RAISE; END IF;
END;
/
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE SEAL_CONTRACT_LAUNCH_FILE';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -942 THEN RAISE; END IF;
END;
/
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE SEAL_CONTRACT_LAUNCH_PARTY';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -942 THEN RAISE; END IF;
END;
/
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE SEAL_CONTRACT_LAUNCH_MAIN';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -942 THEN RAISE; END IF;
END;
/
BEGIN
EXECUTE IMMEDIATE 'DROP SEQUENCE SEQ_SEAL_CONTRACT_LAUNCH_LOG';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -2289 THEN RAISE; END IF;
END;
/
BEGIN
EXECUTE IMMEDIATE 'DROP SEQUENCE SEQ_SEAL_CONTRACT_LAUNCH_PLAN';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -2289 THEN RAISE; END IF;
END;
/
BEGIN
EXECUTE IMMEDIATE 'DROP SEQUENCE SEQ_SEAL_CONTRACT_LAUNCH_FILE';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -2289 THEN RAISE; END IF;
END;
/
BEGIN
EXECUTE IMMEDIATE 'DROP SEQUENCE SEQ_SEAL_CONTRACT_LAUNCH_PARTY';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -2289 THEN RAISE; END IF;
END;
/
BEGIN
EXECUTE IMMEDIATE 'DROP SEQUENCE SEQ_SEAL_CONTRACT_LAUNCH_MAIN';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE != -2289 THEN RAISE; END IF;
END;
/
CREATE TABLE SEAL_CONTRACT_LAUNCH_MAIN (
ID NUMBER(19) NOT NULL,
CONTRACT_SYS_ID VARCHAR2(64 CHAR) NOT NULL,
CONTRACT_CODE VARCHAR2(64 CHAR),
LAW_CONTRACT_CODE VARCHAR2(64 CHAR),
LAW_CONTRACT_ID VARCHAR2(64 CHAR),
CONTRACT_NAME VARCHAR2(200 CHAR) NOT NULL,
CONTRACT_TYPE VARCHAR2(64 CHAR) NOT NULL,
CONTRACT_TYPE_CODE VARCHAR2(64 CHAR) NOT NULL,
CONTRACT_SOURCE VARCHAR2(32 CHAR) DEFAULT 'ECP' NOT NULL,
CREATION_MODE VARCHAR2(20 CHAR) NOT NULL,
TEMPLATE_ID NUMBER(19),
TEMPLATE_CODE VARCHAR2(64 CHAR),
TEMPLATE_NAME VARCHAR2(200 CHAR),
STATUS VARCHAR2(30 CHAR) NOT NULL,
APPROVE_STATUS VARCHAR2(30 CHAR),
APPROVE_MESSAGE VARCHAR2(500 CHAR),
SEAL_CONTRACT_ID VARCHAR2(64 CHAR),
SEAL_CONTRACT_STATUS NUMBER(10),
CONTRACT_AMOUNT NUMBER(20, 2),
CURRENCY_NAME VARCHAR2(20 CHAR),
CONTRACT_PERIOD_TYPE VARCHAR2(10 CHAR),
PERIOD_EXPLAIN VARCHAR2(500 CHAR),
EFFECTIVE_START DATE,
EFFECTIVE_END DATE,
PAYMENT_METHOD VARCHAR2(500 CHAR),
PRIMARY_CONTENT VARCHAR2(2000 CHAR),
AMOUNT_EXPLAIN VARCHAR2(2000 CHAR),
VALUATION_MODE VARCHAR2(10 CHAR),
SEAL_TYPE VARCHAR2(50 CHAR),
TEXT_SOURCE VARCHAR2(50 CHAR),
MANDATE_TYPE VARCHAR2(50 CHAR),
CARGO_TYPE VARCHAR2(50 CHAR),
ASSIST_DEPARTMENT_NAME VARCHAR2(200 CHAR),
EXECUTOR_ACCOUNT VARCHAR2(64 CHAR),
CREATOR_PHONE VARCHAR2(32 CHAR),
SELF_CODE VARCHAR2(64 CHAR),
MAIN_CONTRACT_CODE VARCHAR2(200 CHAR),
SIGNING_SUBJECT_CODE VARCHAR2(500 CHAR),
DATE_TYPE VARCHAR2(10 CHAR),
IS_ADDIT INTEGER DEFAULT 2,
IS_ELECTRON VARCHAR2(4 CHAR) DEFAULT '1',
PAYMENT_DIRECTION VARCHAR2(10 CHAR),
PUSH_URL VARCHAR2(500 CHAR),
IS_MAJOR_CONTRACT INTEGER DEFAULT 0,
IS_OPEN_BIDDING INTEGER DEFAULT 0,
IS_YEAR_BUDGET INTEGER DEFAULT 0,
IS_SHARE VARCHAR2(4 CHAR) DEFAULT '0',
CONTRACT_NATURE VARCHAR2(4 CHAR) DEFAULT '0',
IS_SGAT VARCHAR2(4 CHAR) DEFAULT '0',
IS_NORMAL VARCHAR2(4 CHAR) DEFAULT '1',
IS_TERMINATED VARCHAR2(4 CHAR) DEFAULT '0',
IS_SINGLE_AGREEMENT VARCHAR2(4 CHAR) DEFAULT '0',
BIDDING_NO VARCHAR2(100 CHAR),
OPEN_BIDDING_REMARK VARCHAR2(500 CHAR),
CONTRACT_GIST_REMARK VARCHAR2(1000 CHAR),
EW_AMOUNT_TYPE VARCHAR2(100 CHAR),
DJ_AMOUNT NUMBER(20, 2),
YJ_AMOUNT NUMBER(20, 2),
YFK_AMOUNT NUMBER(20, 2),
BZJ_AMOUNT NUMBER(20, 2),
BODY_SUMMARY VARCHAR2(2000 CHAR),
CONTRACT_TEXT_FILE_NAME VARCHAR2(255 CHAR),
CONTRACT_TEXT_FILE_PATH VARCHAR2(500 CHAR),
CONTRACT_TEXT_FILE_TYPE VARCHAR2(50 CHAR),
CONTRACT_TEXT_FILE_SIZE NUMBER(19),
SIGNED_FILE_NAME VARCHAR2(255 CHAR),
SIGNED_FILE_PATH VARCHAR2(500 CHAR),
SIGNED_FILE_TYPE VARCHAR2(50 CHAR),
SIGNED_FILE_SIZE NUMBER(19),
SIGNED_OFFLINE_REASON VARCHAR2(1000 CHAR),
SIGN_DATE DATE,
ACTIVE_DATE DATE,
ARCHIVE_DATE DATE,
ARCHIVE_KEEPER VARCHAR2(64 CHAR),
ARCHIVE_KEEPER_UNIT VARCHAR2(200 CHAR),
ARCHIVE_KEEPER_UNIT_CODE VARCHAR2(100 CHAR),
INVOICE_DATE DATE,
RECEIVE_DATE DATE,
REMIND_DAYS NUMBER(10) DEFAULT 3,
INITIATOR VARCHAR2(64 CHAR),
INITIATOR_DEPT VARCHAR2(200 CHAR),
COMPANY_NAME VARCHAR2(200 CHAR),
ORG_ID VARCHAR2(64 CHAR),
QUERY_SCOPE VARCHAR2(20 CHAR),
CREATE_BY VARCHAR2(64 CHAR),
CREATE_TIME DATE DEFAULT SYSDATE,
UPDATE_BY VARCHAR2(64 CHAR),
UPDATE_TIME DATE DEFAULT SYSDATE,
IS_DELETED VARCHAR2(2 CHAR) DEFAULT 'N',
REMARK VARCHAR2(1000 CHAR),
CONSTRAINT PK_SEAL_CONTRACT_LAUNCH_MAIN PRIMARY KEY (ID),
CONSTRAINT UK_SEAL_CONTRACT_SYS_ID UNIQUE (CONTRACT_SYS_ID)
);
CREATE TABLE SEAL_CONTRACT_LAUNCH_PARTY (
ID NUMBER(19) NOT NULL,
CONTRACT_ID NUMBER(19) NOT NULL,
ROLE_CODE VARCHAR2(10 CHAR) NOT NULL,
ROLE_NAME VARCHAR2(20 CHAR) NOT NULL,
SORT_ORDER NUMBER(10) DEFAULT 1,
PARTNER_ID NUMBER(19),
OPPOSITE_ID VARCHAR2(64 CHAR),
COMPANY_NAME VARCHAR2(200 CHAR) NOT NULL,
COMPANY_TYPE VARCHAR2(50 CHAR),
OPPOSITE_CHARACTER VARCHAR2(20 CHAR),
CONTACT_NAME VARCHAR2(100 CHAR),
CONTACT_PHONE VARCHAR2(50 CHAR),
CONTACT_EMAIL VARCHAR2(100 CHAR),
CONTACT_ADDRESS VARCHAR2(500 CHAR),
REGISTERED_ADDRESS VARCHAR2(500 CHAR),
LEGAL_REPRESENTATIVE VARCHAR2(100 CHAR),
CREDIT_CODE VARCHAR2(100 CHAR),
BANK_NAME VARCHAR2(200 CHAR),
BANK_ACCOUNT VARCHAR2(100 CHAR),
NATURAL_PERSON_ID_TYPE VARCHAR2(20 CHAR),
NATURAL_PERSON_ID_NUMBER VARCHAR2(100 CHAR),
IS_GROUP_INTERNAL VARCHAR2(4 CHAR),
IS_HONG_KONG_MACAO_TAIWAN VARCHAR2(4 CHAR),
CREATE_BY VARCHAR2(64 CHAR),
CREATE_TIME DATE DEFAULT SYSDATE,
UPDATE_BY VARCHAR2(64 CHAR),
UPDATE_TIME DATE DEFAULT SYSDATE,
IS_DELETED VARCHAR2(2 CHAR) DEFAULT 'N',
REMARK VARCHAR2(1000 CHAR),
CONSTRAINT PK_SEAL_CONTRACT_LAUNCH_PARTY PRIMARY KEY (ID)
);
CREATE TABLE SEAL_CONTRACT_LAUNCH_FILE (
ID NUMBER(19) NOT NULL,
CONTRACT_ID NUMBER(19) NOT NULL,
FILE_CATEGORY VARCHAR2(30 CHAR) NOT NULL,
FILE_NAME VARCHAR2(255 CHAR) NOT NULL,
FILE_PATH VARCHAR2(500 CHAR) NOT NULL,
FILE_TYPE VARCHAR2(50 CHAR),
FILE_SIZE NUMBER(19),
SORT_ORDER NUMBER(10) DEFAULT 1,
CREATE_BY VARCHAR2(64 CHAR),
CREATE_TIME DATE DEFAULT SYSDATE,
UPDATE_BY VARCHAR2(64 CHAR),
UPDATE_TIME DATE DEFAULT SYSDATE,
IS_DELETED VARCHAR2(2 CHAR) DEFAULT 'N',
REMARK VARCHAR2(1000 CHAR),
CONSTRAINT PK_SEAL_CONTRACT_LAUNCH_FILE PRIMARY KEY (ID)
);
CREATE TABLE SEAL_CONTRACT_LAUNCH_PLAN (
ID NUMBER(19) NOT NULL,
CONTRACT_ID NUMBER(19) NOT NULL,
PLAN_MATTER VARCHAR2(500 CHAR) NOT NULL,
PLAN_WHERE VARCHAR2(500 CHAR) NOT NULL,
PLAN_TIME DATE NOT NULL,
PLAN_DAY NUMBER(10) DEFAULT 3,
PLAN_MONEY NUMBER(20, 2),
PLAN_SUBJECT_CODE VARCHAR2(100 CHAR),
PLAN_SUBJECT_NAME VARCHAR2(200 CHAR),
PLAN_DETAIL VARCHAR2(1000 CHAR),
PLAN_STATUS VARCHAR2(20 CHAR) DEFAULT '0',
CREATE_BY VARCHAR2(64 CHAR),
CREATE_TIME DATE DEFAULT SYSDATE,
UPDATE_BY VARCHAR2(64 CHAR),
UPDATE_TIME DATE DEFAULT SYSDATE,
IS_DELETED VARCHAR2(2 CHAR) DEFAULT 'N',
REMARK VARCHAR2(1000 CHAR),
CONSTRAINT PK_SEAL_CONTRACT_LAUNCH_PLAN PRIMARY KEY (ID)
);
CREATE TABLE SEAL_CONTRACT_LAUNCH_LOG (
ID NUMBER(19) NOT NULL,
CONTRACT_ID NUMBER(19) NOT NULL,
ACTION_TYPE VARCHAR2(50 CHAR) NOT NULL,
ACTION_NAME VARCHAR2(100 CHAR) NOT NULL,
ACTION_STATUS VARCHAR2(20 CHAR) NOT NULL,
OPERATOR_NAME VARCHAR2(64 CHAR),
OPERATOR_PHONE VARCHAR2(32 CHAR),
ACTION_TIME DATE DEFAULT SYSDATE,
ACTION_CONTENT VARCHAR2(2000 CHAR),
CALLBACK_PAYLOAD CLOB,
REMARK VARCHAR2(1000 CHAR),
CONSTRAINT PK_SEAL_CONTRACT_LAUNCH_LOG PRIMARY KEY (ID)
);
COMMENT ON TABLE SEAL_CONTRACT_LAUNCH_MAIN IS '合同发起主表';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.ID IS '主键ID';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.CONTRACT_SYS_ID IS '平台合同唯一编码';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.CONTRACT_CODE IS '业务合同编码';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.LAW_CONTRACT_CODE IS '法务系统合同编号';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.LAW_CONTRACT_ID IS '法务系统合同ID';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.CONTRACT_NAME IS '合同名称';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.CONTRACT_TYPE IS '合同类型中文名称';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.CONTRACT_TYPE_CODE IS '合同类型编码';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.CONTRACT_SOURCE IS '合同来源';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.CREATION_MODE IS '创建方式:template/manual';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.TEMPLATE_ID IS '模板ID';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.TEMPLATE_CODE IS '模板编号';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.TEMPLATE_NAME IS '模板名称';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.STATUS IS '合同当前状态';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.APPROVE_STATUS IS '审批状态';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.APPROVE_MESSAGE IS '审批说明';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.SEAL_CONTRACT_ID IS '签章平台合同ID';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.SEAL_CONTRACT_STATUS IS '签章平台合同状态';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.CONTRACT_AMOUNT IS '合同金额';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.CURRENCY_NAME IS '币种';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.CONTRACT_PERIOD_TYPE IS '合同期限类型:0固定期限 1无固定期限';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.PERIOD_EXPLAIN IS '期限说明';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.EFFECTIVE_START IS '生效开始日期';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.EFFECTIVE_END IS '生效结束日期';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.PAYMENT_METHOD IS '付款方式';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.PRIMARY_CONTENT IS '合同主要内容';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.AMOUNT_EXPLAIN IS '金额说明';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.VALUATION_MODE IS '计价方式';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.SEAL_TYPE IS '签订方式';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.TEXT_SOURCE IS '文本来源';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.MANDATE_TYPE IS '委托类型';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.CARGO_TYPE IS '货种';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.ASSIST_DEPARTMENT_NAME IS '协助部门';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.EXECUTOR_ACCOUNT IS '合同执行人账号';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.CREATOR_PHONE IS '创建人手机号';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.SELF_CODE IS '二级单位合同编码';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.MAIN_CONTRACT_CODE IS '主合同编码';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.SIGNING_SUBJECT_CODE IS '签约主体编码,多个用逗号分隔';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.DATE_TYPE IS '固定期间日期类型:0年 1月 2日';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.IS_ADDIT IS '是否补录:1是 2否';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.IS_ELECTRON IS '签署方式:0纸质 1电子';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.PAYMENT_DIRECTION IS '收支方向';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.PUSH_URL IS '法务审批回调地址';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.IS_MAJOR_CONTRACT IS '是否重大合同';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.IS_OPEN_BIDDING IS '是否公开招标';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.IS_YEAR_BUDGET IS '是否列入当年预算';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.IS_SHARE IS '是否共享';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.CONTRACT_NATURE IS '签约主体是否涉外';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.IS_SGAT IS '是否涉港澳台';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.IS_NORMAL IS '是否正常';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.IS_TERMINATED IS '是否终止';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.IS_SINGLE_AGREEMENT IS '是否单方协议';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.BIDDING_NO IS '招标编号';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.OPEN_BIDDING_REMARK IS '公开招标备注';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.CONTRACT_GIST_REMARK IS '签订依据说明';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.EW_AMOUNT_TYPE IS '额外金额类型:DJ定金 YJ押金 YFK预付款 BZJ保证金';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.DJ_AMOUNT IS '定金金额';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.YJ_AMOUNT IS '押金金额';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.YFK_AMOUNT IS '预付款金额';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.BZJ_AMOUNT IS '保证金金额';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.BODY_SUMMARY IS '正文摘要';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.CONTRACT_TEXT_FILE_NAME IS '合同正文文件名';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.CONTRACT_TEXT_FILE_PATH IS '合同正文文件路径';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.CONTRACT_TEXT_FILE_TYPE IS '合同正文文件类型';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.CONTRACT_TEXT_FILE_SIZE IS '合同正文文件大小';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.SIGNED_FILE_NAME IS '已签署文件名';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.SIGNED_FILE_PATH IS '已签署文件路径';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.SIGNED_FILE_TYPE IS '已签署文件类型';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.SIGNED_FILE_SIZE IS '已签署文件大小';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.SIGNED_OFFLINE_REASON IS '线下签署原因';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.SIGN_DATE IS '签署日期';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.ACTIVE_DATE IS '合同生效日期';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.ARCHIVE_DATE IS '归档时间';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.ARCHIVE_KEEPER IS '档案保管人';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.ARCHIVE_KEEPER_UNIT IS '档案保管单位';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.ARCHIVE_KEEPER_UNIT_CODE IS '档案保管单位编码';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.INVOICE_DATE IS '开票时间';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.RECEIVE_DATE IS '收款时间';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.REMIND_DAYS IS '提醒提前天数';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.INITIATOR IS '发起人';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.INITIATOR_DEPT IS '发起部门';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.COMPANY_NAME IS '发起公司';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.ORG_ID IS '组织ID';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.QUERY_SCOPE IS '查询范围';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.CREATE_BY IS '创建人';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.CREATE_TIME IS '创建时间';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.UPDATE_BY IS '更新人';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.UPDATE_TIME IS '更新时间';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.IS_DELETED IS '逻辑删除标记';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_MAIN.REMARK IS '备注';
COMMENT ON TABLE SEAL_CONTRACT_LAUNCH_PARTY IS '合同方信息表';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PARTY.ID IS '主键ID';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PARTY.CONTRACT_ID IS '合同主表ID';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PARTY.ROLE_CODE IS '角色编码:A/B/C';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PARTY.ROLE_NAME IS '角色名称:甲方/乙方/丙方';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PARTY.SORT_ORDER IS '排序号';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PARTY.PARTNER_ID IS '相对方管理表主键';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PARTY.OPPOSITE_ID IS '法务相对方ID';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PARTY.COMPANY_NAME IS '公司名称';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PARTY.COMPANY_TYPE IS '公司类型';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PARTY.OPPOSITE_CHARACTER IS '公司性质';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PARTY.CONTACT_NAME IS '联系人';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PARTY.CONTACT_PHONE IS '联系电话';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PARTY.CONTACT_EMAIL IS '联系邮箱';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PARTY.CONTACT_ADDRESS IS '通讯地址';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PARTY.REGISTERED_ADDRESS IS '注册地址';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PARTY.LEGAL_REPRESENTATIVE IS '法定代表人';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PARTY.CREDIT_CODE IS '统一社会信用代码';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PARTY.BANK_NAME IS '开户行';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PARTY.BANK_ACCOUNT IS '银行账号';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PARTY.NATURAL_PERSON_ID_TYPE IS '自然人证件类型';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PARTY.NATURAL_PERSON_ID_NUMBER IS '自然人证件号码';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PARTY.IS_GROUP_INTERNAL IS '是否集团内';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PARTY.IS_HONG_KONG_MACAO_TAIWAN IS '是否涉港澳台';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PARTY.CREATE_BY IS '创建人';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PARTY.CREATE_TIME IS '创建时间';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PARTY.UPDATE_BY IS '更新人';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PARTY.UPDATE_TIME IS '更新时间';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PARTY.IS_DELETED IS '逻辑删除标记';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PARTY.REMARK IS '备注';
COMMENT ON TABLE SEAL_CONTRACT_LAUNCH_FILE IS '合同附件表';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_FILE.ID IS '主键ID';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_FILE.CONTRACT_ID IS '合同主表ID';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_FILE.FILE_CATEGORY IS '文件分类:body/other/gist/signed/archive';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_FILE.FILE_NAME IS '文件名称';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_FILE.FILE_PATH IS '文件路径';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_FILE.FILE_TYPE IS '文件类型';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_FILE.FILE_SIZE IS '文件大小';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_FILE.SORT_ORDER IS '排序号';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_FILE.CREATE_BY IS '创建人';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_FILE.CREATE_TIME IS '创建时间';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_FILE.UPDATE_BY IS '更新人';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_FILE.UPDATE_TIME IS '更新时间';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_FILE.IS_DELETED IS '逻辑删除标记';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_FILE.REMARK IS '备注';
COMMENT ON TABLE SEAL_CONTRACT_LAUNCH_PLAN IS '合同履行计划表';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PLAN.ID IS '主键ID';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PLAN.CONTRACT_ID IS '合同主表ID';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PLAN.PLAN_MATTER IS '履行事项';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PLAN.PLAN_WHERE IS '履约条件';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PLAN.PLAN_TIME IS '节点日期';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PLAN.PLAN_DAY IS '提前提醒天数';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PLAN.PLAN_MONEY IS '款项金额';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PLAN.PLAN_SUBJECT_CODE IS '所属主体编码';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PLAN.PLAN_SUBJECT_NAME IS '所属主体名称';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PLAN.PLAN_DETAIL IS '备注';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PLAN.PLAN_STATUS IS '反馈状态';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PLAN.CREATE_BY IS '创建人';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PLAN.CREATE_TIME IS '创建时间';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PLAN.UPDATE_BY IS '更新人';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PLAN.UPDATE_TIME IS '更新时间';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PLAN.IS_DELETED IS '逻辑删除标记';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_PLAN.REMARK IS '备注';
COMMENT ON TABLE SEAL_CONTRACT_LAUNCH_LOG IS '合同操作日志表';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_LOG.ID IS '主键ID';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_LOG.CONTRACT_ID IS '合同主表ID';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_LOG.ACTION_TYPE IS '动作类型';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_LOG.ACTION_NAME IS '动作名称';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_LOG.ACTION_STATUS IS '动作状态';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_LOG.OPERATOR_NAME IS '操作人';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_LOG.OPERATOR_PHONE IS '操作人手机号';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_LOG.ACTION_TIME IS '操作时间';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_LOG.ACTION_CONTENT IS '操作说明';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_LOG.CALLBACK_PAYLOAD IS '回调或接口报文';
COMMENT ON COLUMN SEAL_CONTRACT_LAUNCH_LOG.REMARK IS '备注';
CREATE INDEX IDX_CONTRACT_LAUNCH_STATUS ON SEAL_CONTRACT_LAUNCH_MAIN (STATUS);
CREATE INDEX IDX_CONTRACT_LAUNCH_CODE ON SEAL_CONTRACT_LAUNCH_MAIN (CONTRACT_CODE);
CREATE INDEX IDX_CONTRACT_LAUNCH_NAME ON SEAL_CONTRACT_LAUNCH_MAIN (CONTRACT_NAME);
CREATE INDEX IDX_CONTRACT_LAUNCH_CREATE_TIME ON SEAL_CONTRACT_LAUNCH_MAIN (CREATE_TIME);
CREATE INDEX IDX_CONTRACT_LAUNCH_PARTY_CONTRACT ON SEAL_CONTRACT_LAUNCH_PARTY (CONTRACT_ID);
CREATE INDEX IDX_CONTRACT_LAUNCH_FILE_CONTRACT ON SEAL_CONTRACT_LAUNCH_FILE (CONTRACT_ID);
CREATE INDEX IDX_CONTRACT_LAUNCH_PLAN_CONTRACT ON SEAL_CONTRACT_LAUNCH_PLAN (CONTRACT_ID);
CREATE INDEX IDX_CONTRACT_LAUNCH_LOG_CONTRACT ON SEAL_CONTRACT_LAUNCH_LOG (CONTRACT_ID);
CREATE SEQUENCE SEQ_SEAL_CONTRACT_LAUNCH_MAIN START WITH 1 INCREMENT BY 1 NOCACHE NOCYCLE;
CREATE SEQUENCE SEQ_SEAL_CONTRACT_LAUNCH_PARTY START WITH 1 INCREMENT BY 1 NOCACHE NOCYCLE;
CREATE SEQUENCE SEQ_SEAL_CONTRACT_LAUNCH_FILE START WITH 1 INCREMENT BY 1 NOCACHE NOCYCLE;
CREATE SEQUENCE SEQ_SEAL_CONTRACT_LAUNCH_PLAN START WITH 1 INCREMENT BY 1 NOCACHE NOCYCLE;
CREATE SEQUENCE SEQ_SEAL_CONTRACT_LAUNCH_LOG START WITH 1 INCREMENT BY 1 NOCACHE NOCYCLE;