commit 8a9a67b80502811e552675e38c6cd26fc5834962 Author: Jinyuanyuan <1197651512@qq.com> Date: Fri Apr 19 15:46:27 2024 +0800 first commit diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..35410ca --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml +# 基于编辑器的 HTTP 客户端请求 +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..639900d --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..b0ba5b4 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/pgcm.iml b/pgcm.iml new file mode 100644 index 0000000..f76df2b --- /dev/null +++ b/pgcm.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/gy/pgcm/nb/enums/NbErrorCode.java b/src/main/java/com/gy/pgcm/nb/enums/NbErrorCode.java new file mode 100644 index 0000000..2ff685c --- /dev/null +++ b/src/main/java/com/gy/pgcm/nb/enums/NbErrorCode.java @@ -0,0 +1,41 @@ +package com.gy.pgcm.nb.enums; + +import cn.bespinglobal.amg.common.exception.ErrorCode; +import org.apache.http.HttpStatus; + +/** + *

TODO

+ * + * @author zg + * @since 2023/12/27 + */ +public enum NbErrorCode implements ErrorCode { + NO_LOGIN(HttpStatus.SC_BAD_REQUEST, "用户登陆数据错误"), + NOT_EXIST(HttpStatus.SC_BAD_REQUEST, "数据不存在"), + ERROR_DO(HttpStatus.SC_BAD_REQUEST, "执行错误"), + INVALID_PARAM(HttpStatus.SC_BAD_REQUEST, "参数错误"), + INVALID_ACTION(HttpStatus.SC_BAD_REQUEST, "错误操作") + ; + + private int httpStatusCode; + private String message; + NbErrorCode(int httpStatusCode, String message) { + this.httpStatusCode = httpStatusCode; + this.message = message; + } + + @Override + public String getModule() { + return "FIN"; + } + + @Override + public int getHttpStatusCode() { + return this.httpStatusCode; + } + + @Override + public String getMessage() { + return this.message; + } +} diff --git a/src/main/java/com/gy/pgcm/nb/enums/NbRecordTypeEnum.java b/src/main/java/com/gy/pgcm/nb/enums/NbRecordTypeEnum.java new file mode 100644 index 0000000..d481b86 --- /dev/null +++ b/src/main/java/com/gy/pgcm/nb/enums/NbRecordTypeEnum.java @@ -0,0 +1,44 @@ +package com.gy.pgcm.nb.enums; + +import cn.bespinglobal.amg.common.base.IBaseEnum; + +/** + *

NB记录类型Enum

+ * + * @author zg + * @since 2023/12/27 + */ +public enum NbRecordTypeEnum implements IBaseEnum { + Type_Project("project", "项目"), + Type_Contract("contract", "合同"), + Type_Invoice("Invoice", "发票"), + Type_Invoice_Income("InvoiceIncome", "发票-确认收入"), + Type_Invoice_Account("InvoiceAccount", "发票-确认到账"), + ; + + private String value; + private String description; + + NbRecordTypeEnum(String value, String description) { + this.value = value; + this.description = description; + } + + @Override + public String getValue() { + return this.value; + } + + public void setValue(String value) { + this.value = value; + } + + @Override + public Object getDescription() { + return this.description; + } + + public void setDescription(String description) { + this.description = description; + } +} diff --git a/src/main/java/com/gy/pgcm/nb/mapper/NbLogMapper.java b/src/main/java/com/gy/pgcm/nb/mapper/NbLogMapper.java new file mode 100644 index 0000000..2b3c304 --- /dev/null +++ b/src/main/java/com/gy/pgcm/nb/mapper/NbLogMapper.java @@ -0,0 +1,16 @@ +package com.gy.pgcm.nb.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gy.pgcm.nb.model.entity.NbLogDO; +import com.gy.pgcm.nb.model.entity.NbRecordDO; +import org.apache.ibatis.annotations.Mapper; + +/** + *

TODO

+ * + * @author zg + * @since 2023/12/27 + */ +@Mapper +public interface NbLogMapper extends BaseMapper { +} diff --git a/src/main/java/com/gy/pgcm/nb/mapper/NbRecordMapper.java b/src/main/java/com/gy/pgcm/nb/mapper/NbRecordMapper.java new file mode 100644 index 0000000..e6ca65c --- /dev/null +++ b/src/main/java/com/gy/pgcm/nb/mapper/NbRecordMapper.java @@ -0,0 +1,18 @@ +package com.gy.pgcm.nb.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.gy.pgcm.nb.model.entity.NbRecordDO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + *

TODO

+ * + * @author zg + * @since 2023/12/27 + */ +@Mapper +public interface NbRecordMapper extends BaseMapper { + + NbRecordDO findByKey(@Param("type") String type, @Param("key") String key); +} diff --git a/src/main/java/com/gy/pgcm/nb/model/entity/NbLogDO.java b/src/main/java/com/gy/pgcm/nb/model/entity/NbLogDO.java new file mode 100644 index 0000000..a9b7c91 --- /dev/null +++ b/src/main/java/com/gy/pgcm/nb/model/entity/NbLogDO.java @@ -0,0 +1,48 @@ +package com.gy.pgcm.nb.model.entity; + +import cn.bespinglobal.amg.common.base.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + *

宁波数据接口调用日志

+ * + * @author zg + * @since 2023/12/27 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@TableName("nb_log") +public class NbLogDO extends BaseEntity implements Serializable { + private static final long serialVersionUID = 5654901998048634425L; + + /** + * 日志类型 + */ + private String logType; + + /** + * 传入参数 + */ + private String logParam; + + /** + * 返回结果 + */ + private String logRes; + + /** + * 执行结果 + */ + private Integer isSuc; + + /** + * 错误信息 + */ + private String errMsg; +} diff --git a/src/main/java/com/gy/pgcm/nb/model/entity/NbRecordDO.java b/src/main/java/com/gy/pgcm/nb/model/entity/NbRecordDO.java new file mode 100644 index 0000000..f52fb43 --- /dev/null +++ b/src/main/java/com/gy/pgcm/nb/model/entity/NbRecordDO.java @@ -0,0 +1,49 @@ +package com.gy.pgcm.nb.model.entity; + +import cn.bespinglobal.amg.common.base.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + *

宁波数据同步记录

+ * + * @author zg + * @since 2023/12/27 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Accessors(chain = true) +@TableName("nb_record") +public class NbRecordDO extends BaseEntity implements Serializable { + private static final long serialVersionUID = 4764199154617593360L; + + /** + * 记录类型 + */ + private String recordType; + + /** + * 记录key + */ + private String recordKey; + + /** + * 标记 0 + */ + private Integer recordFlag; + + /** + * 备注信息 + */ + private String remarks; + + /** + * 是否删除 0 正常; 1 已删除 + */ + private Integer isDelete; + +} diff --git a/src/main/java/com/gy/pgcm/nb/model/param/NbApproveCandidateItem.java b/src/main/java/com/gy/pgcm/nb/model/param/NbApproveCandidateItem.java new file mode 100644 index 0000000..5ff9dfe --- /dev/null +++ b/src/main/java/com/gy/pgcm/nb/model/param/NbApproveCandidateItem.java @@ -0,0 +1,22 @@ +package com.gy.pgcm.nb.model.param; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

TODO

+ * + * @author zg + * @since 2023/12/27 + */ +@ApiModel("宁波系统数据接口-开票状态返回审批记录候选项结果") +@Data +public class NbApproveCandidateItem { + + @ApiModelProperty(value = "录候人员部门名称") + private String deptName; + + @ApiModelProperty(value = "录候人员名称") + private String staffName; +} diff --git a/src/main/java/com/gy/pgcm/nb/model/param/NbApproveItem.java b/src/main/java/com/gy/pgcm/nb/model/param/NbApproveItem.java new file mode 100644 index 0000000..ea6a404 --- /dev/null +++ b/src/main/java/com/gy/pgcm/nb/model/param/NbApproveItem.java @@ -0,0 +1,39 @@ +package com.gy.pgcm.nb.model.param; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +/** + *

TODO

+ * + * @author zg + * @since 2023/12/27 + */ +@ApiModel("宁波系统数据接口-开票状态返回审批记录结果") +@Data +public class NbApproveItem { + + @ApiModelProperty(value = "审批步骤名称") + private String stepName; + + @ApiModelProperty(value = "审批候选人员列表") + private List candidateItems; + + @ApiModelProperty(value = "审批部门") + private String approveDept; + + @ApiModelProperty(value = "审批人员名称") + private String approveStaff; + + @ApiModelProperty(value = "审批操作时间") + private String approveTime; + + @ApiModelProperty(value = "审批状态 0 待审批; 1 通过; 2 驳回") + private int approveStatus; + + @ApiModelProperty(value = "审批拒绝原因") + private String approveRejectReason; +} diff --git a/src/main/java/com/gy/pgcm/nb/model/param/NbContractParam.java b/src/main/java/com/gy/pgcm/nb/model/param/NbContractParam.java new file mode 100644 index 0000000..18a2369 --- /dev/null +++ b/src/main/java/com/gy/pgcm/nb/model/param/NbContractParam.java @@ -0,0 +1,89 @@ +package com.gy.pgcm.nb.model.param; + +import com.gy.pgcm.sys.consts.dict.Dict; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; + +/** + *

TODO

+ * + * @author zg + * @since 2023/12/26 + */ +@ApiModel("宁波系统数据接口-合同参数") +@Data +public class NbContractParam { + + /** + * 合同编号 + */ + @ApiModelProperty(value = "合同编号 新增时传空;修改时必传") + private String contractCode; + + /** + * 合同名称 + */ + @ApiModelProperty(value = "合同名称") + private String contractName; + +// /** +// * 合同类型 +// */ +// @NotNull +// @ApiModelProperty(value = "字典:合同类型(BizContractTypeEnum)", required = true) +// private Integer contractType; + + /** + * 项目编号 + */ + @ApiModelProperty(value = "项目编号", required = true) + private String projectNo; + + /** + * 合同金额 + */ + @ApiModelProperty(value = "合同金额 默认同项目金额") + private BigDecimal contractAmount; + + /** + * 是否高新 + */ + @ApiModelProperty(value = "销售合同-是否高新") + private Integer highTech = 0; + + /** + * 中标方式 + */ + @ApiModelProperty(value = "销售合同-中标方式 字典:中标方式("+ Dict.WINNING_BID_WAY +")", required = true) + private String winningBidWay; + + /** + * 签出 + */ + @ApiModelProperty(value = "签出", required = true) + private Integer signOut = 0; + + /** + * 签入 + */ + @ApiModelProperty(value = "签入", required = true) + private Integer signIn = 0; + + /** + * 确认日期 + */ + @ApiModelProperty(value = "确认日期 yyyy-MM-dd") + private String confirmDate; + +// /** +// * 销售合同-关联实施人员Code列表 +// */ +// @ApiModelProperty(value = "销售合同-关联实施人员Code列表 多个用,连接") +// private String implUserCodes; + +} diff --git a/src/main/java/com/gy/pgcm/nb/model/param/NbContractQueryParam.java b/src/main/java/com/gy/pgcm/nb/model/param/NbContractQueryParam.java new file mode 100644 index 0000000..aef4923 --- /dev/null +++ b/src/main/java/com/gy/pgcm/nb/model/param/NbContractQueryParam.java @@ -0,0 +1,32 @@ +package com.gy.pgcm.nb.model.param; + +import com.gy.pgcm.sys.consts.dict.Dict; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; + +/** + *

TODO

+ * + * @author zg + * @since 2023/12/25 + */ +@ApiModel("宁波系统数据接口-合同查询参数") +@Data +public class NbContractQueryParam { + + /** + * 合同编号 + */ + @ApiModelProperty(value = "合同编号") + private String contractCode; + + /** + * 合同名称 + */ + @ApiModelProperty(value = "合同名称") + private String contractName; + +} diff --git a/src/main/java/com/gy/pgcm/nb/model/param/NbInvoiceAccountParam.java b/src/main/java/com/gy/pgcm/nb/model/param/NbInvoiceAccountParam.java new file mode 100644 index 0000000..6a5fced --- /dev/null +++ b/src/main/java/com/gy/pgcm/nb/model/param/NbInvoiceAccountParam.java @@ -0,0 +1,55 @@ +package com.gy.pgcm.nb.model.param; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; + +/** + *

TODO

+ * + * @author zg + * @since 2023/12/26 + */ +@ApiModel("宁波系统数据接口-发票确认到账参数") +@Data +public class NbInvoiceAccountParam { + + /** + * 确认到账Id + */ + @ApiModelProperty(value = "确认到账Id 删除时必传") + private String accountId; + + /** + * 关联开票单号 + */ + @ApiModelProperty(value = "关联开票单号 新增时必传") + private String invoiceNo; + + /** + * 确认到账日期yyyy-MM-dd + */ + @ApiModelProperty(value = "确认到账日期yyyy-MM-dd 新增时必传") + private String accountDate; + + /** + * 确认到账金额 + */ + @ApiModelProperty(value = "确认到账金额 新增时必传") + private BigDecimal accountAmount; + + /** + * 操作标记 0 新增;1 删除 + */ + @ApiModelProperty(value = "操作标记 0 新增;1 删除 默认0") + private Integer opFlag; + + /** + * 操作员工编码 + */ + @ApiModelProperty(value = "操作员工编码", required = true) + private String opUserCode; + +} diff --git a/src/main/java/com/gy/pgcm/nb/model/param/NbInvoiceConfirmParam.java b/src/main/java/com/gy/pgcm/nb/model/param/NbInvoiceConfirmParam.java new file mode 100644 index 0000000..2d308e5 --- /dev/null +++ b/src/main/java/com/gy/pgcm/nb/model/param/NbInvoiceConfirmParam.java @@ -0,0 +1,37 @@ +package com.gy.pgcm.nb.model.param; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; + +/** + *

TODO

+ * + * @author zg + * @since 2023/12/26 + */ +@ApiModel("宁波系统数据接口-开票确认参数") +@Data +public class NbInvoiceConfirmParam { + + /** + * 开票单号 + */ + @ApiModelProperty(value = "开票单号", required = true) + private String invoiceNo; + + /** + * 开票确认日期yyyy-MM-dd + */ + @ApiModelProperty(value = "开票确认日期yyyy-MM-dd", required = true) + private String confirmDate; + + /** + * 确认员工编码 + */ + @ApiModelProperty(value = "确认员工编码", required = true) + private String confirmUserCode; + +} diff --git a/src/main/java/com/gy/pgcm/nb/model/param/NbInvoiceIncomeParam.java b/src/main/java/com/gy/pgcm/nb/model/param/NbInvoiceIncomeParam.java new file mode 100644 index 0000000..da4dd22 --- /dev/null +++ b/src/main/java/com/gy/pgcm/nb/model/param/NbInvoiceIncomeParam.java @@ -0,0 +1,57 @@ +package com.gy.pgcm.nb.model.param; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; + +/** + *

TODO

+ * + * @author zg + * @since 2023/12/26 + */ +@ApiModel("宁波系统数据接口-发票确认收入参数") +@Data +public class NbInvoiceIncomeParam { + + /** + * 确认收入Id + */ + @ApiModelProperty(value = "确认收入Id 删除时必传") + private String incomeId; + + /** + * 关联开票单号 + */ + @ApiModelProperty(value = "关联开票单号 新增时必传") + private String invoiceNo; + + /** + * 确认收入日期yyyy-MM-dd + */ + @ApiModelProperty(value = "确认收入日期yyyy-MM-dd 新增时必传") + private String incomeDate; + + /** + * 确认收入金额 + */ + @ApiModelProperty(value = "确认收入金额 新增时必传") + private BigDecimal incomeAmount; + + /** + * 操作标记 0 新增;1 删除 + */ + @ApiModelProperty(value = "操作标记 0 新增;1 删除 默认0") + private Integer opFlag; + + /** + * 操作员工编码 + */ + @ApiModelProperty(value = "操作员工编码", required = true) + private String opUserCode; + +} diff --git a/src/main/java/com/gy/pgcm/nb/model/param/NbInvoiceParam.java b/src/main/java/com/gy/pgcm/nb/model/param/NbInvoiceParam.java new file mode 100644 index 0000000..e481f69 --- /dev/null +++ b/src/main/java/com/gy/pgcm/nb/model/param/NbInvoiceParam.java @@ -0,0 +1,115 @@ +package com.gy.pgcm.nb.model.param; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; + +/** + *

TODO

+ * + * @author zg + * @since 2023/12/26 + */ +@ApiModel("宁波系统数据接口-开票信息参数") +@Data +public class NbInvoiceParam { + + /** + * 申请单号 + */ + @ApiModelProperty(value = "申请单号, 新增时传空,修改时必传") + private String invoiceNo; + + /** + * 开票日期yyyy-MM-dd + */ + @ApiModelProperty(value = "开票日期yyyy-MM-dd", required = true) + private String invoiceDate; + + /** + * 项目Id + */ + @ApiModelProperty(value = "项目编号 开票申请时必传") + private String projectNo; + + /** + * 合同收款进度 + */ + @ApiModelProperty(value = "合同收款进度") + private String receiptScheduleName; + + /** + * 付款方名称 + */ + @ApiModelProperty(value = "付款方名称 开票申请时必传") + private String payerName; + + /** + * 纳税人识别号 + */ + @ApiModelProperty(value = "纳税人识别号 开票申请时必传") + private String payerNumber; + + /** + * 开票金额 + */ + @ApiModelProperty(value = "开票金额", required = true) + private BigDecimal invoiceAmount; + + /** + * 开票内容 + */ + @ApiModelProperty(value = "开票内容 字典(开票内容) 开票申请时必传") + private String invoiceContent; + + /** + * 付款方式 + */ + @ApiModelProperty(value = "付款方式 字典(付款方式) 开票申请时必传") + private String paymentMode; + + /** + * 发票类型 + */ + @ApiModelProperty(value = "发票类型 字典(发票类型) 开票申请时必传") + private String invoiceType; + + /** + * 备注 + */ + @ApiModelProperty(value = "备注 退票时必传") + private String remarkInfo; + + /** + * 特殊说明 + */ + @ApiModelProperty(value = "特殊说明") + private String specialInfo; + + /** + * 证明文件Id + */ + @ApiModelProperty(value = "证明文件Id 多个用逗号分割") + private String evidenceId; + + /** + * 是否退票 1 是;0 否 + */ + @ApiModelProperty(value = "是否退票 1 是;0 否", required = true) + private Integer isReturn; + + /** + * 退票原始单号 退票时必填 + */ + @ApiModelProperty(value = "退票原始单号 退票时必填") + private String returnInvoiceNo; + + /** + * 申请员工编号 + */ + @ApiModelProperty(value = "申请员工编号", required = true) + private String applyUserCode; + +} diff --git a/src/main/java/com/gy/pgcm/nb/model/param/NbInvoiceStatusResult.java b/src/main/java/com/gy/pgcm/nb/model/param/NbInvoiceStatusResult.java new file mode 100644 index 0000000..75a393f --- /dev/null +++ b/src/main/java/com/gy/pgcm/nb/model/param/NbInvoiceStatusResult.java @@ -0,0 +1,44 @@ +package com.gy.pgcm.nb.model.param; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.List; + +/** + *

TODO

+ * + * @author zg + * @since 2023/12/26 + */ +@ApiModel("宁波系统数据接口-开票状态返回结果") +@Data +public class NbInvoiceStatusResult { + + /** + * 申请单号 + */ + @ApiModelProperty(value = "申请单号") + private String invoiceNo; + + /** + * 状态 0 未提交, 1 审批中, 2 已通过(未确认), 3 已驳回, 4 已确认, 5 已退回, 6 已撤回 + */ + @ApiModelProperty(value = "状态 0 未提交, 1 审批中, 2 已通过(未确认), 3 已驳回, 4 已确认, 5 已退回, 6 已撤回") + private Integer status; + + /** + * 审批信息 + */ + @ApiModelProperty(value = "审批信息") + private String approveMsg; + + /** + * 审批记录 + */ + @ApiModelProperty(value = "审批记录") + private List approveItems; + +} diff --git a/src/main/java/com/gy/pgcm/nb/model/param/NbProjectParam.java b/src/main/java/com/gy/pgcm/nb/model/param/NbProjectParam.java new file mode 100644 index 0000000..716f9dd --- /dev/null +++ b/src/main/java/com/gy/pgcm/nb/model/param/NbProjectParam.java @@ -0,0 +1,146 @@ +package com.gy.pgcm.nb.model.param; + +import com.gy.pgcm.sys.consts.dict.Dict; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; + +/** + *

TODO

+ * + * @author zg + * @since 2023/12/25 + */ +@ApiModel("宁波系统数据接口-项目参数") +@Data +public class NbProjectParam { + + /** + * 项目编号 + */ + @ApiModelProperty(value = "项目编号 新增项目时传空;修改时必传") + private String projectNo; + + /** + * 项目名称 + */ + @ApiModelProperty(value = "项目名称", required = true) + private String projectName; + + /** + * 项目类型 + */ + @ApiModelProperty(value = "项目类型("+ Dict.PROJECT_TYPE +")", required = true) + private String projectType; + + /** + * 所属区域 + */ + @ApiModelProperty(value = "所属区域("+ Dict.AREA +")", required = true) + private String areaCode; + + /** + * 是否涉密->客户类别 + */ + @ApiModelProperty(value = "客户类别(ProjectSecretEnum)", required = true) + private Integer projectSecret; + + /** + * 销售负责人 + */ + @ApiModelProperty(value = "销售负责人员工编号", required = true) + private String salesLeaderCode; + + /** + * 名义总监 + */ + @ApiModelProperty(value = "名义总监员工编号") + private String nominalDirectorCode; + + /** + * 项目实施部门 + */ + @ApiModelProperty(value = "项目实施部门编码", required = true) + private String deptCode; + + /** + * 实施负责人 + */ + @ApiModelProperty(value = "实施负责人员工编号", required = true) + private String projectManagerCode; + + /** + * 项目金额 + */ + @ApiModelProperty(value = "项目金额", required = true) + private BigDecimal contractAmount; + + /** + * 投资金额(万元) + */ + @ApiModelProperty(value = "投资金额(万元)") + private BigDecimal projectConstructionScale; + + /** + * 甲方单位名称 + */ + @ApiModelProperty(value = "甲方单位名称") + private String projectCompany; + + /** + * 项目起始时间 + */ + @ApiModelProperty(value = "项目起始时间 yyyy-MM-dd", required = true) + private String projectStartDate; + + /** + * 项目截止时间 + */ + @ApiModelProperty(value = "项目截止时间 yyyy-MM-dd", required = true) + private String projectEndDate; + + /** + * 是否直接实施 + */ + @ApiModelProperty(value = "是否直接实施 0 否; 1 是 默认0") + private Integer directImplementation = 1; + + /** + * 项目所属类型 + */ + @ApiModelProperty(value = "项目所属类型", required = true) + private String projectCaseType; + + /** + * 项目所属行业 + */ + @ApiModelProperty(value = "项目所属行业", required = true) + private String projectIndustry; + + /** + * 所属用户类型 + */ + @ApiModelProperty(value = "所属用户类型", required = true) + private String projectUserProperty; + + /** + * 项目描述 + */ + @ApiModelProperty(value = "项目描述") + private String projectDescription; + + /** + * 备注 + */ + @ApiModelProperty(value = "备注") + private String remarks; + + /** + * 项目状态(0 商务、 1 未启动、 2 实施中、 3 验收中、 4 已验收、 9 申请结项、 10 已结项、 11 已关闭) + */ + @ApiModelProperty(value = "项目状态(0 商务、 1 未启动、 2 实施中、 3 验收中、 4 已验收、 9 申请结项、 10 已结项、 11 已关闭) 查询项目信息时使用") + private Integer projectStatus; + +} diff --git a/src/main/java/com/gy/pgcm/nb/model/param/NbProjectQueryParam.java b/src/main/java/com/gy/pgcm/nb/model/param/NbProjectQueryParam.java new file mode 100644 index 0000000..a49e0f8 --- /dev/null +++ b/src/main/java/com/gy/pgcm/nb/model/param/NbProjectQueryParam.java @@ -0,0 +1,32 @@ +package com.gy.pgcm.nb.model.param; + +import com.gy.pgcm.sys.consts.dict.Dict; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; + +/** + *

TODO

+ * + * @author zg + * @since 2023/12/25 + */ +@ApiModel("宁波系统数据接口-项目查询参数") +@Data +public class NbProjectQueryParam { + + /** + * 项目编号 + */ + @ApiModelProperty(value = "项目编号") + private String projectNo; + + /** + * 项目名称 + */ + @ApiModelProperty(value = "项目名称") + private String projectName; + +} diff --git a/src/main/java/com/gy/pgcm/nb/service/INbService.java b/src/main/java/com/gy/pgcm/nb/service/INbService.java new file mode 100644 index 0000000..f3080a3 --- /dev/null +++ b/src/main/java/com/gy/pgcm/nb/service/INbService.java @@ -0,0 +1,107 @@ +package com.gy.pgcm.nb.service; + +import com.gy.pgcm.nb.model.param.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; + +/** + *

TODO

+ * + * @author zg + * @since 2023/12/25 + */ +public interface INbService { + + /** + * 同步项目信息 + * @param param + * @return + */ + NbProjectParam project(NbProjectParam param); + + /** + * 同步合同信息 + * @param param + * @return + */ + NbContractParam contract(NbContractParam param); + + /** + * + * @param param + * @return + */ + NbInvoiceParam invoice(NbInvoiceParam param); + + /** + * + * @param invoiceNo + * @return + */ + NbInvoiceStatusResult invoiceDelete(String invoiceNo); + + /** + * + * @param file + * @return + */ + String uploadEvidence(MultipartFile file); + + /** + * 开票确认 + * @param param + * @return + */ + NbInvoiceConfirmParam invoiceConfirm(NbInvoiceConfirmParam param); + + /** + * 同步开票确认收入信息 + * @param param + * @return + */ + NbInvoiceIncomeParam invoiceIncome(NbInvoiceIncomeParam param); + + /** + * 同步开票确认到账信息 + * @param param + * @return + */ + NbInvoiceAccountParam invoiceAccount(NbInvoiceAccountParam param); + + /** + * 获取开票信息审批信息 + * @param invoiceNo + * @return + */ + NbInvoiceStatusResult invoiceStatus(String invoiceNo); + + /** + * 获取开票申请单文件 + * @param invoiceNo + * @param response + */ + void invoiceForm(String invoiceNo, HttpServletResponse response); + + /** + * 获取项目信息 + * @param param + * @return + */ + NbProjectParam getProject(NbProjectQueryParam param); + + /** + * 获取合同信息 + * @param param + * @return + */ + NbContractParam getContract(NbContractQueryParam param); + + /** + * 调整项目状态 + * @param status + * @param projectNo + * @return + */ + Boolean changeProject(String status, String projectNo); +} diff --git a/src/main/java/com/gy/pgcm/nb/service/impl/NbServiceImpl.java b/src/main/java/com/gy/pgcm/nb/service/impl/NbServiceImpl.java new file mode 100644 index 0000000..f73f55c --- /dev/null +++ b/src/main/java/com/gy/pgcm/nb/service/impl/NbServiceImpl.java @@ -0,0 +1,1205 @@ +package com.gy.pgcm.nb.service.impl; + +import cn.bespinglobal.amg.common.exception.ClientException; +import cn.bespinglobal.amg.common.exception.ServerException; +import cn.bespinglobal.amg.common.tool.JSONTool; +import cn.bespinglobal.amg.common.util.DateUtil; +import cn.bespinglobal.amg.common.util.UserContextHolder; +import cn.bespinglobal.amg.flowable.process.idm.Group; +import cn.bespinglobal.amg.flowable.process.idm.User; +import cn.bespinglobal.amg.tool.poi.word.DocxBuilder; +import cn.bespinglobal.amg.tool.storage.pojo.SObject; +import com.gy.pgcm.biz.enums.BizContractTypeEnum; +import com.gy.pgcm.biz.mapper.BizContractMapper; +import com.gy.pgcm.biz.model.entity.BizContractDO; +import com.gy.pgcm.biz.service.IBizContractService; +import com.gy.pgcm.common.constant.ProjectTypeConst; +import com.gy.pgcm.common.enums.*; +import com.gy.pgcm.common.mapper.ProjectInfoMapper; +import com.gy.pgcm.common.model.entity.ProjectInfoDO; +import com.gy.pgcm.common.service.FileService; +import com.gy.pgcm.fin.common.FinCodeType; +import com.gy.pgcm.fin.entity.*; +import com.gy.pgcm.fin.entity.extend.FinInvoiceInfoExtendDO; +import com.gy.pgcm.fin.enums.FinEnumInvoiceStatus; +import com.gy.pgcm.fin.mapper.*; +import com.gy.pgcm.fin.service.IFinInvoiceService; +import com.gy.pgcm.fin.vo.param.FinInvoiceReturnParam; +import com.gy.pgcm.fin.vo.param.FinInvoiceUpdateParam; +import com.gy.pgcm.hr.mapper.HrOrgMapper; +import com.gy.pgcm.hr.mapper.HrStaffMapper; +import com.gy.pgcm.hr.model.entity.HrOrgDO; +import com.gy.pgcm.hr.model.vo.HrStaffVO; +import com.gy.pgcm.nb.enums.NbErrorCode; +import com.gy.pgcm.nb.enums.NbRecordTypeEnum; +import com.gy.pgcm.nb.mapper.NbLogMapper; +import com.gy.pgcm.nb.mapper.NbRecordMapper; +import com.gy.pgcm.nb.model.entity.NbLogDO; +import com.gy.pgcm.nb.model.entity.NbRecordDO; +import com.gy.pgcm.nb.model.param.*; +import com.gy.pgcm.nb.service.INbService; +import com.gy.pgcm.sale.service.ISaleProjectService; +import com.gy.pgcm.sys.consts.dict.Dict; +import com.gy.pgcm.sys.mapper.SysDictValMapper; +import com.gy.pgcm.sys.model.entity.SysDictValDO; +import com.gy.pgcm.sys.model.vo.ext.ProcessAssigneeTaskVO; +import com.gy.pgcm.sys.model.vo.ext.SysFileRes; +import com.gy.pgcm.sys.service.ISysFileService; +import com.gy.pgcm.sys.service.ISysProcessService; +import jodd.util.StringUtil; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletResponse; +import java.io.InputStream; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +/** + *

TODO

+ * + * @author zg + * @since 2023/12/25 + */ +@Slf4j +@Service +public class NbServiceImpl implements INbService { + + @Autowired + private NbRecordMapper recordMapper; + @Autowired + private NbLogMapper logMapper; + + @Autowired + private ProjectInfoMapper projectInfoMapper; + @Autowired + private BizContractMapper contractMapper; + @Autowired + private FinInvoiceMapper invoiceMapper; + @Autowired + private SysDictValMapper dictValMapper; + @Autowired + private HrOrgMapper orgMapper; + @Autowired + private HrStaffMapper staffMapper; + @Autowired + private FinCodeMapper finCodeMapper; + @Autowired + private FinInvoiceIncomeMapper invoiceIncomeMapper; + @Autowired + private FinInvoiceAccountMapper invoiceAccountMapper; + @Autowired + private FinReportBaseMapper finReportBaseMapper; + + @Autowired + private ISaleProjectService saleProjectService; + @Autowired + private IBizContractService contractService; + @Autowired + private IFinInvoiceService finInvoiceService; + @Autowired + private ISysProcessService sysProcessService; + @Autowired + private FileService fileService; + @Autowired + private FileService fileStorageService; + @Autowired + private ISysFileService sysFileService; + + private static final String LogTypeProject = "project"; + private static final String LogTypeProjectInfo = "projectInfo"; + private static final String LogTypeProjectChange = "projectChange"; + private static final String LogTypeContract = "contract"; + private static final String LogTypeContractInfo = "contractInfo"; + private static final String LogTypeInvoice = "invoice"; + private static final String LogTypeInvoiceDelete = "invoiceDelete"; + private static final String LogTypeInvoiceConfirm = "invoiceConfirm"; + private static final String LogTypeInvoiceIncome = "invoiceIncome"; + private static final String LogTypeInvoiceAccount = "invoiceAccount"; + private static final String LogTypeInvoiceStatus = "invoiceStatus"; + private static final String LogTypeInvoiceForm = "invoiceForm"; + + @Override + public NbProjectParam project(NbProjectParam param) { + try { + // 验证用户 + this.verifyCurrentUser(); + // 1. 验证参数 + ProjectInfoDO projectDO; + boolean isUpd = false; + // 1.2 验证项目编号 + if (!StringUtil.isEmpty(param.getProjectNo())) { // 项目编号存在、更新项目 + projectDO = this.projectInfoMapper.getByProjectNo(param.getProjectNo()); + if (null == projectDO) { + throw new ClientException("项目编号不存在", NbErrorCode.INVALID_PARAM); + } + // 验证项目来源 + if (null == this.recordMapper.findByKey(NbRecordTypeEnum.Type_Project.getValue(), param.getProjectNo())) { + throw new ClientException("该项目无修改权限", NbErrorCode.INVALID_PARAM); + } + isUpd = true; + } else { + projectDO = new ProjectInfoDO(); + } + // 1.3 验证项目名称名称 + if (StringUtil.isEmpty(param.getProjectName())) { + throw new ClientException("项目名称不能为空", NbErrorCode.INVALID_PARAM); + } + if (null != this.projectInfoMapper.findProjectByProjectName(param.getProjectName(), projectDO.getId())) { + throw new ClientException("项目名称不能重复", NbErrorCode.INVALID_PARAM); + } + projectDO.setProjectName(param.getProjectName()); + // 1.4 验证项目类型 + if (!ProjectTypeConst.verify(param.getProjectType())) { + throw new ClientException("无效的项目类型", NbErrorCode.INVALID_PARAM); + } + projectDO.setProjectType(param.getProjectType()); + // 1.5 验证区域 + if (StringUtil.isEmpty(param.getAreaCode())) { + throw new ClientException("项目所属区域不能为空", NbErrorCode.INVALID_PARAM); + } + if (null == this.dictValMapper.getByDictCodeAndVal(Dict.AREA, param.getAreaCode())) { + throw new ClientException("所属区域编码不存在", NbErrorCode.INVALID_PARAM); + } + projectDO.setAreaId(param.getAreaCode()); + // 1.6 验证客户类别 + ProjectSecretEnum pse = ProjectSecretEnum.verify(param.getProjectSecret()); + if (null == pse) { + throw new ClientException("无效的客户类别", NbErrorCode.INVALID_PARAM); + } + projectDO.setProjectSecret(pse); + // 1.7 验证销售负责人 + if (StringUtil.isEmpty(param.getSalesLeaderCode())) { + throw new ClientException("销售负责人员工编号不能为空", NbErrorCode.INVALID_PARAM); + } + HrStaffVO staffVO = this.staffMapper.getByStaffCode(param.getSalesLeaderCode()); + if (null == staffVO) { + throw new ClientException("销售负责人员工编号不存在", NbErrorCode.INVALID_PARAM); + } + projectDO.setSalesLeaderId(staffVO.getId()); + projectDO.setBearDeptId(staffVO.getDeptId()); + // 1.8 验证名义总监 + if (StringUtil.isNotEmpty(param.getNominalDirectorCode())) { + staffVO = this.staffMapper.getByStaffCode(param.getNominalDirectorCode()); + if (null == staffVO) { + throw new ClientException("名义总监员工编号不存在", NbErrorCode.INVALID_PARAM); + } + projectDO.setNominalDirectorId(staffVO.getId()); + } + // 1.9 验证项目实施部门 + HrOrgDO orgDO = this.orgMapper.getDeptByCode(param.getDeptCode()); + if (null == orgDO) { + throw new ClientException("项目实施部门编码不存在", NbErrorCode.INVALID_PARAM); + } + projectDO.setDeptId(orgDO.getId()); + // 1.10 验证实施负责人 + if (StringUtil.isEmpty(param.getProjectManagerCode())) { + throw new ClientException("实施负责人员工编号不能为空", NbErrorCode.INVALID_PARAM); + } + staffVO = this.staffMapper.getByStaffCode(param.getProjectManagerCode()); + if (null == staffVO) { + throw new ClientException("实施负责人员工编号不存在", NbErrorCode.INVALID_PARAM); + } + projectDO.setProjectManagerId(staffVO.getId()); + // 1.11 验证项目金额 + if (null == param.getContractAmount() || param.getContractAmount().compareTo(BigDecimal.ZERO) < 0) { + throw new ClientException("无效的项目金额(金额大于等于0)", NbErrorCode.INVALID_PARAM); + } + projectDO.setContractAmount(param.getContractAmount()); + // 1.12 验证起始、截止时间 + DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + if (!DateUtil.isValidDate(param.getProjectStartDate(), DateUtil.Format_YMD) || + !DateUtil.isValidDate(param.getProjectEndDate(), DateUtil.Format_YMD)) { + throw new ClientException("无效的项目起止时间,必传且格式yyyy-MM-dd", NbErrorCode.INVALID_PARAM); + } + projectDO.setProjectStartDate(LocalDate.parse(param.getProjectStartDate(), df)); + projectDO.setProjectEndDate(LocalDate.parse(param.getProjectEndDate(), df)); + // 1.13 是否直接实施 + if (null == param.getDirectImplementation() || 1 != param.getDirectImplementation()) + param.setDirectImplementation(0); + projectDO.setDirectImplementation(1 == param.getDirectImplementation()); + // 1.14 验证项目所属类型 + if (StringUtil.isEmpty(param.getProjectCaseType())) { + throw new ClientException("项目所属类型不能为空", NbErrorCode.INVALID_PARAM); + } + projectDO.setProjectCaseType(param.getProjectCaseType()); + // 1.15 验证项目所属行业 + if (StringUtil.isEmpty(param.getProjectIndustry())) { + throw new ClientException("项目所属行业不能为空", NbErrorCode.INVALID_PARAM); + } + if (null == this.dictValMapper.getByDictCodeAndName(Dict.Project_Industry, param.getProjectIndustry())) { + throw new ClientException("项目所属行业不存在", NbErrorCode.INVALID_PARAM); + } + projectDO.setProjectIndustry(param.getProjectIndustry()); + // 1.16 验证所属用户类型 + if (StringUtil.isEmpty(param.getProjectUserProperty())) { + throw new ClientException("所属用户类型不能为空", NbErrorCode.INVALID_PARAM); + } + if (null == this.dictValMapper.getByDictCodeAndName(Dict.Project_User_Property, param.getProjectUserProperty())) { + throw new ClientException("所属用户类型不存在", NbErrorCode.INVALID_PARAM); + } + projectDO.setProjectUserProperty(param.getProjectUserProperty()); + projectDO.setProjectConstructionScale(param.getProjectConstructionScale()); + projectDO.setProjectCompany(param.getProjectCompany()); + projectDO.setProjectDescription(param.getProjectDescription()); + projectDO.setRemarks(param.getRemarks()); + // 2. + if (isUpd) { + // 2.1 修改项目信息 + this.projectInfoMapper.updateById(projectDO); + this.saveExecLog(LogTypeProject, true, param, projectDO, "success"); + // 2.2 更新关联销售合同信息 + BizContractDO contractDO = this.contractMapper.getSaleContractByProjectId(projectDO.getId()); + if (null != contractDO) { + contractDO.setAmount(projectDO.getContractAmount()); + contractDO.setProjectStartDate(projectDO.getProjectStartDate()); + contractDO.setProjectEndDate(projectDO.getProjectEndDate()); + contractDO.setAreaId(projectDO.getAreaId()); + contractDO.setSalesLeaderId(projectDO.getSalesLeaderId()); + contractDO.setCompanyName(projectDO.getProjectCompany()); + contractDO.setDeptId(projectDO.getBearDeptId()); + this.contractMapper.updateById(contractDO); + } + } else { + // 2.1 新增项目 + projectDO.setProjectNo(saleProjectService.generateFormalProjectNo(param.getAreaCode())); + projectDO.setProjectStatus(ProjectStatusEnum.NOT_INITIATED); + this.projectInfoMapper.insert(projectDO); + this.saveExecLog(LogTypeProject, true, param, projectDO, "success"); + // 2.2 添加记录 + this.saveExecRecord(NbRecordTypeEnum.Type_Project, projectDO.getProjectNo()); + + param.setProjectNo(projectDO.getProjectNo()); + } + return param; + } catch (Exception e) { + this.saveExecLog(LogTypeProject, false, param, null, e.getMessage()); + throw e; + } + } + + @Override + public NbContractParam contract(NbContractParam param) { + try { + // 验证用户 + this.verifyCurrentUser(); + // 1. 验证参数 + BizContractDO contractDO; + boolean isUpd = false; + // 1.2 验证合同编号 + if (!StringUtil.isEmpty(param.getContractCode())) { // 合同编号存在,更新合同信息 + contractDO = this.contractMapper.getSaleContractByCode(param.getContractCode()); + if (null == contractDO) { + throw new ClientException("销售合同编号不存在", NbErrorCode.INVALID_PARAM); + } + isUpd = true; + } else { + contractDO = new BizContractDO(); + } + // 1.3 验证合同名称 + if (StringUtil.isEmpty(param.getContractName())) { + throw new ClientException("合同名称不能为空", NbErrorCode.INVALID_PARAM); + } + contractDO.setName(param.getContractName()); + // 1.4 项目编号 + if (StringUtil.isEmpty(param.getProjectNo())) { + throw new ClientException("项目编号不能为空", NbErrorCode.INVALID_PARAM); + } + // 验证项目是否存在 + ProjectInfoDO projectInfoDO = this.projectInfoMapper.getByProjectNo(param.getProjectNo()); + if (null == projectInfoDO) { + throw new ClientException("项目不存在", NbErrorCode.INVALID_PARAM); + } + // 验证项目来源 + if (null == this.recordMapper.findByKey(NbRecordTypeEnum.Type_Project.getValue(), param.getProjectNo())) { + throw new ClientException("该项目无权限", NbErrorCode.INVALID_PARAM); + } + // 验证合同与项目是否匹配 + if (isUpd && !projectInfoDO.getId().equals(contractDO.getProjectId())) { + throw new ClientException("无法修改合同关联的项目编号", NbErrorCode.INVALID_PARAM); + } + // 验证项目是否已存在合同 + if (!isUpd && null != this.contractMapper.getSaleContractByProjectId(projectInfoDO.getId())) { + throw new ClientException("项目已存在销售合同,无法添加", NbErrorCode.INVALID_PARAM); + } + contractDO.setProjectId(projectInfoDO.getId()); + // 1.5 验证合同金额 + if (null != param.getContractAmount() && projectInfoDO.getContractAmount().compareTo(param.getContractAmount()) != 0) { + throw new ClientException("合同金额无效(应与项目金额一致)", NbErrorCode.INVALID_PARAM); + } + contractDO.setAmount(projectInfoDO.getContractAmount()); + // 1.6 是否高新 + contractDO.setHighTech(null != param.getHighTech() && 1 == param.getHighTech()); + // 1.7 验证中标方式 + if (StringUtil.isEmpty(param.getWinningBidWay())) { + throw new ClientException("中标方式不能为空", NbErrorCode.INVALID_PARAM); + } + SysDictValDO dictValDO = this.dictValMapper.getByDictCodeAndName(Dict.WINNING_BID_WAY, param.getWinningBidWay()); + if (null == dictValDO) { + throw new ClientException("中标方式不存在", NbErrorCode.INVALID_PARAM); + } + contractDO.setWinningBidWay(dictValDO.getValue()); + // 1.8 签入、签出 + contractDO.setSignIn(null != param.getSignIn() && 1 == param.getSignIn()); + contractDO.setSignOut(null != param.getSignOut() && 1 == param.getSignOut()); + // 1.9 验证确认日期 + if (StringUtil.isNotEmpty(param.getConfirmDate()) && !DateUtil.isValidDate(param.getConfirmDate(), DateUtil.Format_YMD)) { + throw new ClientException("确认日期格式错误 (yyyy-MM-dd)", NbErrorCode.INVALID_PARAM); + } + DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + if (StringUtil.isNotEmpty(param.getConfirmDate())) { + contractDO.setConfirmDate(LocalDate.parse(param.getConfirmDate(), df)); + } + // 2. + if (isUpd) { // 修改 + this.contractMapper.updateById(contractDO); + this.saveExecLog(LogTypeContract, true, param, contractDO, "success"); + } else { + // 2.1 新增合同 + contractDO.setType(BizContractTypeEnum.SALE); + contractDO.setProjectStartDate(projectInfoDO.getProjectStartDate()); + contractDO.setProjectEndDate(projectInfoDO.getProjectEndDate()); + contractDO.setAreaId(projectInfoDO.getAreaId()); + contractDO.setSalesLeaderId(projectInfoDO.getSalesLeaderId()); + contractDO.setCompanyName(projectInfoDO.getProjectCompany()); + contractDO.setState(CheckStateEnum.APPROVED); + contractDO.setDeptId(projectInfoDO.getBearDeptId()); + contractDO.setCode(this.contractService.generateContractCode(contractDO.getAreaId(), BizContractTypeEnum.SALE)); + this.contractMapper.insert(contractDO); + this.saveExecLog(LogTypeContract, true, param, contractDO, "success"); + // 2.2 添加记录 + this.saveExecRecord(NbRecordTypeEnum.Type_Contract, contractDO.getCode()); + + param.setContractCode(contractDO.getCode()); + } + return param; + } catch (Exception e) { + this.saveExecLog(LogTypeContract, false, param, null, e.getMessage()); + throw e; + } + } + + @Override + public NbInvoiceParam invoice(NbInvoiceParam param) { + if (null != param.getIsReturn() && 1 == param.getIsReturn()) { + // 退票申请 + return this.invoiceReturn(param); + } else { + // 开票申请 +// return this.invoiceApply(param); + return this.applyInvoice(param); + } + } + + /** + * 开票申请、修改 + * @param param + * @return + */ + private NbInvoiceParam applyInvoice(NbInvoiceParam param) { + try { + // 验证用户 + this.verifyCurrentUser(); + // 1. 验证参数 + FinInvoiceUpdateParam updateParam = new FinInvoiceUpdateParam(); + String invoiceId = null; + boolean isUpd = false; + // 1.2 验证申请单号 + if (!StringUtil.isEmpty(param.getInvoiceNo())) { // 申请单号存在,更新开票信息 + FinInvoiceDO existInvoiceDO = this.invoiceMapper.getInvoiceByNo(param.getInvoiceNo()); + if (null == existInvoiceDO) { + throw new ClientException("开票申请单不存在", NbErrorCode.INVALID_PARAM); + } + invoiceId = existInvoiceDO.getId(); + // 验证开票来源 + if (null == this.recordMapper.findByKey(NbRecordTypeEnum.Type_Invoice.getValue(), param.getInvoiceNo())) { + throw new ClientException("该开票申请单无修改权限", NbErrorCode.INVALID_PARAM); + } + isUpd = true; + } + // 1.3 验证开票日期 + if (!DateUtil.isValidDate(param.getInvoiceDate(), DateUtil.Format_YMD)) { + throw new ClientException("无效的开票日期,必传且格式yyyy-MM-dd", NbErrorCode.INVALID_PARAM); + } + updateParam.setInvoiceDate(param.getInvoiceDate()); + // 1.4 项目编号 + if (StringUtil.isEmpty(param.getProjectNo())) { + throw new ClientException("项目编号不能为空", NbErrorCode.INVALID_PARAM); + } + // 验证项目是否存在 + ProjectInfoDO projectInfoDO = this.projectInfoMapper.getByProjectNo(param.getProjectNo()); + if (null == projectInfoDO) { + throw new ClientException("项目不存在", NbErrorCode.INVALID_PARAM); + } + // 项目项目状态 + if (projectInfoDO.getProjectStatus() == ProjectStatusEnum.CLOSED) { + throw new ClientException("项目已关闭", NbErrorCode.INVALID_PARAM); + } + // 验证项目来源 + if (null == this.recordMapper.findByKey(NbRecordTypeEnum.Type_Project.getValue(), param.getProjectNo())) { + throw new ClientException("该项目无权限", NbErrorCode.INVALID_PARAM); + } + // 验证合同 + BizContractDO contractDO = this.contractMapper.getSaleContractByProjectId(projectInfoDO.getId()); + if (null == contractDO || contractDO.getState() != CheckStateEnum.APPROVED) { + throw new ClientException("该项目无合同信息或合同状态无效", NbErrorCode.INVALID_PARAM); + } + updateParam.setProjectId(projectInfoDO.getId()); + // 1.5 验证付款方名称 + if (StringUtil.isEmpty(param.getPayerName())) { + throw new ClientException("付款方名称不能为空", NbErrorCode.INVALID_PARAM); + } + updateParam.setPayerName(param.getPayerName()); + // 1.6 验证纳税人识别号 + if (StringUtil.isEmpty(param.getPayerNumber())) { + throw new ClientException("纳税人识别号不能为空", NbErrorCode.INVALID_PARAM); + } + updateParam.setPayerNumber(param.getPayerNumber()); + // 1.7 验证开票金额 + if (null == param.getInvoiceAmount() || param.getInvoiceAmount().compareTo(BigDecimal.ZERO) == 0) { + throw new ClientException("无效的开票金额", NbErrorCode.INVALID_PARAM); + } + updateParam.setInvoiceAmount(param.getInvoiceAmount()); + // 1.8 验证开票内容 + FinCodeDO invContentDO = this.finCodeMapper.findByTypeAndName(FinCodeType.TYPE_INVOICE_INFO, param.getInvoiceContent()); + if (null == invContentDO) { + throw new ClientException("无效的开票内容", NbErrorCode.INVALID_PARAM); + } + updateParam.setInvoiceContent(invContentDO.getId()); + // 1.9 验证付款方式 + FinCodeDO invModeDO = this.finCodeMapper.findByTypeAndName(FinCodeType.TYPE_PAYMENT_TYPE, param.getPaymentMode()); + if (null == invModeDO) { + throw new ClientException("无效的付款方式", NbErrorCode.INVALID_PARAM); + } + updateParam.setPaymentMode(invModeDO.getId()); + // 1.10 验证发票类型 + FinCodeDO invTypeDO = this.finCodeMapper.findByTypeAndName(FinCodeType.TYPE_INVOICE_TYPE, param.getInvoiceType()); + if (null == invTypeDO) { + throw new ClientException("无效的发票类型", NbErrorCode.INVALID_PARAM); + } + updateParam.setInvoiceType(invTypeDO.getId()); + // 1.11 验证申请员工编号 + if (StringUtil.isEmpty(param.getApplyUserCode())) { + throw new ClientException("申请员工编号不能为空", NbErrorCode.INVALID_PARAM); + } + HrStaffVO staffVO = this.staffMapper.getByStaffCode(param.getApplyUserCode()); + if (null == staffVO) { + throw new ClientException("申请员工编号不存在", NbErrorCode.INVALID_PARAM); + } + // 验证开票权限 + if (!staffVO.getId().equals(projectInfoDO.getSalesLeaderId()) && !staffVO.getId().equals(projectInfoDO.getProjectManagerId())) { + throw new ClientException("申请员工无项目的开票权限(需要项目的销售人员或实施负责人)", NbErrorCode.INVALID_PARAM); + } + // 1.12 验证证明文件 + int evidenceFlag = 0; // 是否有证明文件0无1有 + List evidenceNames = new ArrayList<>(); + List evidenceUrls = new ArrayList<>(); + if (StringUtil.isNotEmpty(param.getEvidenceId())) { + String[] dbIds = param.getEvidenceId().split(","); + List fileResList = this.sysFileService.listFile(Arrays.asList(dbIds)); + if (fileResList.size() > 0) { + for (SysFileRes fileRes : fileResList) { + evidenceNames.add(fileRes.getOriginalFileName()); + evidenceUrls.add(fileRes.getDbId()); + } + evidenceFlag = 1; + } + } + updateParam.setEvidenceFlag(evidenceFlag); + if (1 == evidenceFlag) { + updateParam.setEvidenceNames(evidenceNames); + updateParam.setEvidenceUrls(evidenceUrls); + } + // + updateParam.setReceiptScheduleName(param.getReceiptScheduleName()); + updateParam.setRemarkInfo(param.getRemarkInfo()); + updateParam.setSpecialInfo(param.getSpecialInfo()); + // 2.1 保存发票信息并提交审批 + FinInvoiceDO invoiceDO = this.finInvoiceService.nbApplyInvoice(staffVO.getId(), invoiceId, updateParam); + this.saveExecLog(LogTypeInvoice, true, param, invoiceDO, "success"); + // 2.3 添加记录 + if (!isUpd) { + this.saveExecRecord(NbRecordTypeEnum.Type_Invoice, invoiceDO.getInvoiceNo()); + param.setInvoiceNo(invoiceDO.getInvoiceNo()); + } + return param; + } catch (Exception e) { + this.saveExecLog(LogTypeInvoice, false, param, null, e.getMessage()); + throw e; + } + } + + /** + * 退票申请 + * @param param + * @return + */ + private NbInvoiceParam invoiceReturn(NbInvoiceParam param) { + try { + // 验证用户 + this.verifyCurrentUser(); + // 1. 验证参数 + FinInvoiceReturnParam returnParam = new FinInvoiceReturnParam(); + // 1.2 检查退票单号是否存在 + if (StringUtil.isEmpty(param.getReturnInvoiceNo())) { + throw new ClientException("退票原始单号不能为空", NbErrorCode.INVALID_PARAM); + } + // 退票原始单号是否存在 + FinInvoiceDO invoiceDO = this.invoiceMapper.getInvoiceByNo(param.getReturnInvoiceNo()); + if (null == invoiceDO || FinEnumInvoiceStatus.STATUS_DELETED.getValue().equals(invoiceDO.getApplyStatus())) { + throw new ClientException("退票原始单信息不存在", NbErrorCode.INVALID_PARAM); + } + // 1.3 验证开票日期 + if (!DateUtil.isValidDate(param.getInvoiceDate(), DateUtil.Format_YMD)) { + throw new ClientException("无效的开票日期,必传且格式yyyy-MM-dd", NbErrorCode.INVALID_PARAM); + } + returnParam.setInvoiceDate(param.getInvoiceDate()); + // 1.4 验证开票金额 + if (null == param.getInvoiceAmount() || param.getInvoiceAmount().compareTo(BigDecimal.ZERO) <= 0) { + throw new ClientException("无效的开票金额", NbErrorCode.INVALID_PARAM); + } + returnParam.setRtnAmount(param.getInvoiceAmount()); + // 退款标记 0 全部退款; 1 部分退款 + int rtnFlag = 0; + if (param.getInvoiceAmount().compareTo(invoiceDO.getInvoiceAmount()) != 0) rtnFlag = 1; + returnParam.setRtnFlag(rtnFlag); + // 1.5 验证备注信息 + if (StringUtil.isEmpty(param.getRemarkInfo())) { + throw new ClientException("备注信息不能为空", NbErrorCode.INVALID_PARAM); + } + returnParam.setRemarkInfo(param.getRemarkInfo()); + // 1.6 验证证明文件 + int evidenceFlag = 0; // 是否有证明文件0无1有 + List evidenceNames = new ArrayList<>(); + List evidenceUrls = new ArrayList<>(); + if (StringUtil.isNotEmpty(param.getEvidenceId())) { + String[] dbIds = param.getEvidenceId().split(","); + List fileResList = this.sysFileService.listFile(Arrays.asList(dbIds)); + if (fileResList.size() > 0) { + for (SysFileRes fileRes : fileResList) { + evidenceNames.add(fileRes.getOriginalFileName()); + evidenceUrls.add(fileRes.getDbId()); + } + evidenceFlag = 1; + } + } + returnParam.setEvidenceFlag(evidenceFlag); + if (1 == evidenceFlag) { + returnParam.setEvidenceNames(evidenceNames); + returnParam.setEvidenceUrls(evidenceUrls); + } + // 1.7 验证申请员工编号 + if (StringUtil.isEmpty(param.getApplyUserCode())) { + throw new ClientException("申请员工编号不能为空", NbErrorCode.INVALID_PARAM); + } + HrStaffVO staffVO = this.staffMapper.getByStaffCode(param.getApplyUserCode()); + if (null == staffVO) { + throw new ClientException("申请员工编号不存在", NbErrorCode.INVALID_PARAM); + } + returnParam.setReceiptScheduleName(param.getReceiptScheduleName()); + // 2.1 执行退票流程并提交审批 + FinInvoiceDO returnInvoiceDO = this.finInvoiceService.nbReturnInvoice(staffVO.getId(), invoiceDO.getId(), returnParam); + this.saveExecLog(LogTypeInvoice, true, param, returnInvoiceDO, "success"); + // 2.2 添加记录 + this.saveExecRecord(NbRecordTypeEnum.Type_Invoice, returnInvoiceDO.getInvoiceNo()); + param.setInvoiceNo(returnInvoiceDO.getInvoiceNo()); + return param; + } catch (Exception e) { + this.saveExecLog(LogTypeInvoice, false, param, null, e.getMessage()); + throw e; + } + } + + @Override + public NbInvoiceStatusResult invoiceDelete(String invoiceNo) { + try { + // 验证用户 + String userId = this.verifyCurrentUser(); + // 1. 验证参数 + // 1.2 验证申请单号 + if (StringUtil.isEmpty(invoiceNo)) { + throw new ClientException("发票申请单号不能为空", NbErrorCode.INVALID_PARAM); + } + // 验证发票记录是否存在 + FinInvoiceDO invoiceDO = this.invoiceMapper.getInvoiceByNo(invoiceNo); + if (null == invoiceDO) { + throw new ClientException("开票申请单不存在", NbErrorCode.INVALID_PARAM); + } + // 验证开票来源 + if (null == this.recordMapper.findByKey(NbRecordTypeEnum.Type_Invoice.getValue(), invoiceNo)) { + throw new ClientException("该开票申请单无权限", NbErrorCode.INVALID_PARAM); + } + // 验证开票状态 + if (null != invoiceDO.getState() && invoiceDO.getState() == CheckStateEnum.APPROVED) { + throw new ClientException("该开票申请单已审批通过,无法删除", NbErrorCode.INVALID_PARAM); + } + // 1.3 审批 + if (invoiceDO.getState() == CheckStateEnum.WAIT_APPROVAL && StringUtil.isNotEmpty(invoiceDO.getProcessInstanceId())) { + this.sysProcessService.undoThenDeleteInstance(invoiceDO.getProcessInstanceId(), "取消申请"); + } + // 2. + invoiceDO.setState(CheckStateEnum.WAIT_SUBMIT); + invoiceDO.setApplyStatus(FinEnumInvoiceStatus.STATUS_DELETED.getValue()); + invoiceDO.setUpdateUser(userId); + invoiceDO.setUpdateTime(LocalDateTime.now()); + this.invoiceMapper.updateById(invoiceDO); + + NbInvoiceStatusResult res = new NbInvoiceStatusResult(); + res.setInvoiceNo(invoiceDO.getInvoiceNo()); + res.setStatus(invoiceDO.getApplyStatus()); + + this.saveExecLog(LogTypeInvoiceDelete, true, invoiceNo, res, "success"); + return res; + } catch (Exception e) { + this.saveExecLog(LogTypeInvoiceDelete, false, invoiceNo, null, e.getMessage()); + throw e; + } + } + + @Override + public String uploadEvidence(MultipartFile file) { + try { + // 验证用户 + this.verifyCurrentUser(); + // 上传文件 + MultipartFile[] files = new MultipartFile[1]; + files[0] = file; + List sObjects = this.fileService.upload(FileModuleEnum.PUBLIC, "nb", true, true, files); + if (null == sObjects || sObjects.size() == 0) { + throw new ClientException("文件上传失败(返回空)", NbErrorCode.ERROR_DO); + } + this.saveExecLog(LogTypeInvoice, true, "uploadEvidence", sObjects.get(0), "success"); + return sObjects.get(0).getDbId(); + } catch (Exception e) { + this.saveExecLog(LogTypeInvoice, false, "uploadEvidence", null, e.getMessage()); + throw e; + } + } + + @Override + public NbInvoiceConfirmParam invoiceConfirm(NbInvoiceConfirmParam param) { + try { + // 验证用户 + this.verifyCurrentUser(); + // 1.1 验证开票单号 + if (StringUtil.isEmpty(param.getInvoiceNo())) { + throw new ClientException("开票申请单号不能为空", NbErrorCode.INVALID_PARAM); + } + // 开票单是否存在 + FinInvoiceDO invoiceDO = this.invoiceMapper.getInvoiceByNo(param.getInvoiceNo()); + if (null == invoiceDO) { + throw new ClientException("开票申请单不存在", NbErrorCode.INVALID_PARAM); + } + // 验证开票来源 + if (null == this.recordMapper.findByKey(NbRecordTypeEnum.Type_Invoice.getValue(), param.getInvoiceNo())) { + throw new ClientException("该开票申请单无修改权限", NbErrorCode.INVALID_PARAM); + } + // 1.2 验证开票确认日期 + if (!DateUtil.isValidDate(param.getConfirmDate(), DateUtil.Format_YMD)) { + throw new ClientException("无效的开票确认日期,必传且格式yyyy-MM-dd", NbErrorCode.INVALID_PARAM); + } + // 1.3 验证确认员工编号 + if (StringUtil.isEmpty(param.getConfirmUserCode())) { + throw new ClientException("确认员工编码不能为空", NbErrorCode.INVALID_PARAM); + } + HrStaffVO staffVO = this.staffMapper.getByStaffCode(param.getConfirmUserCode()); + if (null == staffVO) { + throw new ClientException("确认员工编码不存在", NbErrorCode.INVALID_PARAM); + } + // 2. 开票确认 + this.finInvoiceService.nbConfirmInvoice(invoiceDO.getId(), staffVO.getId(), param.getConfirmDate()); + this.saveExecLog(LogTypeInvoiceConfirm, true, param, param, "success"); + + return param; + } catch (Exception e) { + this.saveExecLog(LogTypeInvoiceConfirm, false, param, null, e.getMessage()); + throw e; + } + } + + @Override + public NbInvoiceIncomeParam invoiceIncome(NbInvoiceIncomeParam param) { + try { + // 验证用户 + this.verifyCurrentUser(); + // 1.1 操作标记 + int opFlag = 0; + if (null != param.getOpFlag() && 1 == param.getOpFlag()) opFlag = 1; + // 1.2 验证操作员工编号 + if (StringUtil.isEmpty(param.getOpUserCode())) { + throw new ClientException("操作员工编码不能为空", NbErrorCode.INVALID_PARAM); + } + HrStaffVO staffVO = this.staffMapper.getByStaffCode(param.getOpUserCode()); + if (null == staffVO) { + throw new ClientException("操作员工编码不存在", NbErrorCode.INVALID_PARAM); + } + // 1.3 验证参数 + String invoiceId = null; + String incomeId = null; + if (1 == opFlag) { // 删除 + if (StringUtil.isEmpty(param.getIncomeId())) { + throw new ClientException("确认收入Id不能为空", NbErrorCode.INVALID_PARAM); + } + // 检查确认收入记录 + FinInvoiceIncomeDO incomeDO = this.invoiceIncomeMapper.selectById(param.getIncomeId()); + if (null == incomeDO || 1 == incomeDO.getIncomeStatus()) { + throw new ClientException("确认收入记录不存在", NbErrorCode.INVALID_PARAM); + } + // 检查开票记录 + if (StringUtil.isEmpty(incomeDO.getInvoiceId())) { + throw new ClientException("确认收入记录错误", NbErrorCode.INVALID_PARAM); + } + FinInvoiceDO invoiceDO = this.invoiceMapper.selectById(incomeDO.getInvoiceId()); + if (null == invoiceDO) { + throw new ClientException("确认收入记录关联开票记录不存在", NbErrorCode.INVALID_PARAM); + } + // 验证开票来源 + if (null == this.recordMapper.findByKey(NbRecordTypeEnum.Type_Invoice.getValue(), invoiceDO.getInvoiceNo())) { + throw new ClientException("该开票申请单无修改权限", NbErrorCode.INVALID_PARAM); + } + invoiceId = invoiceDO.getId(); + incomeId = incomeDO.getId(); + } else { // 新增 + if (StringUtil.isEmpty(param.getInvoiceNo())) { + throw new ClientException("关联开票单号不能为空", NbErrorCode.INVALID_PARAM); + } + // 验证开票记录 + FinInvoiceDO invoiceDO = this.invoiceMapper.getInvoiceByNo(param.getInvoiceNo()); + if (null == invoiceDO) { + throw new ClientException("开票记录不存在", NbErrorCode.INVALID_PARAM); + } + // 验证开票来源 + if (null == this.recordMapper.findByKey(NbRecordTypeEnum.Type_Invoice.getValue(), param.getInvoiceNo())) { + throw new ClientException("该开票申请单无修改权限", NbErrorCode.INVALID_PARAM); + } + invoiceId = invoiceDO.getId(); + // 验证确认收入日期 + if (!DateUtil.isValidDate(param.getIncomeDate(), DateUtil.Format_YMD)) { + throw new ClientException("无效的确认收入日期,必传且格式yyyy-MM-dd", NbErrorCode.INVALID_PARAM); + } + // 验证确认收入金额 + if (null == param.getIncomeAmount() || param.getIncomeAmount().compareTo(BigDecimal.ZERO) == 0) { + throw new ClientException("无效的确认收入金额", NbErrorCode.INVALID_PARAM); + } + } + // 2. 收入确认 + FinInvoiceIncomeDO incomeDO = this.finInvoiceService.nbIncomeInvoice(incomeId, invoiceId, param.getIncomeDate(), param.getIncomeAmount(), staffVO.getId()); + this.saveExecLog(LogTypeInvoiceIncome, true, param, param, "success"); + + param.setIncomeId(null == incomeDO ? "" : incomeDO.getId()); + return param; + } catch (Exception e) { + this.saveExecLog(LogTypeInvoiceIncome, false, param, null, e.getMessage()); + throw e; + } + } + + @Override + public NbInvoiceAccountParam invoiceAccount(NbInvoiceAccountParam param) { + try { + // 验证用户 + this.verifyCurrentUser(); + // 1.1 操作标记 + int opFlag = 0; + if (null != param.getOpFlag() && 1 == param.getOpFlag()) opFlag = 1; + // 1.2 验证操作员工编号 + if (StringUtil.isEmpty(param.getOpUserCode())) { + throw new ClientException("操作员工编码不能为空", NbErrorCode.INVALID_PARAM); + } + HrStaffVO staffVO = this.staffMapper.getByStaffCode(param.getOpUserCode()); + if (null == staffVO) { + throw new ClientException("操作员工编码不存在", NbErrorCode.INVALID_PARAM); + } + // 1.3 验证参数 + String invoiceId = null; + String accountId = null; + if (1 == opFlag) { // 删除 + if (StringUtil.isEmpty(param.getAccountId())) { + throw new ClientException("确认到账Id不能为空", NbErrorCode.INVALID_PARAM); + } + // 检查确认到账记录 + FinInvoiceAccountDO accountDO = this.invoiceAccountMapper.selectById(param.getAccountId()); + if (null == accountDO || 1 == accountDO.getAccountStatus()) { + throw new ClientException("确认到账记录不存在", NbErrorCode.INVALID_PARAM); + } + // 检查开票记录 + if (StringUtil.isEmpty(accountDO.getInvoiceId())) { + throw new ClientException("确认到账记录错误", NbErrorCode.INVALID_PARAM); + } + FinInvoiceDO invoiceDO = this.invoiceMapper.selectById(accountDO.getInvoiceId()); + if (null == invoiceDO) { + throw new ClientException("确认到账记录关联开票记录不存在", NbErrorCode.INVALID_PARAM); + } + // 验证开票来源 + if (null == this.recordMapper.findByKey(NbRecordTypeEnum.Type_Invoice.getValue(), invoiceDO.getInvoiceNo())) { + throw new ClientException("该开票申请单无修改权限", NbErrorCode.INVALID_PARAM); + } + invoiceId = invoiceDO.getId(); + accountId = accountDO.getId(); + } else { // 新增 + if (StringUtil.isEmpty(param.getInvoiceNo())) { + throw new ClientException("关联开票单号不能为空", NbErrorCode.INVALID_PARAM); + } + // 验证开票记录 + FinInvoiceDO invoiceDO = this.invoiceMapper.getInvoiceByNo(param.getInvoiceNo()); + if (null == invoiceDO) { + throw new ClientException("开票记录不存在", NbErrorCode.INVALID_PARAM); + } + // 验证开票来源 + if (null == this.recordMapper.findByKey(NbRecordTypeEnum.Type_Invoice.getValue(), param.getInvoiceNo())) { + throw new ClientException("该开票申请单无修改权限", NbErrorCode.INVALID_PARAM); + } + invoiceId = invoiceDO.getId(); + // 验证确认到账日期 + if (!DateUtil.isValidDate(param.getAccountDate(), DateUtil.Format_YMD)) { + throw new ClientException("无效的确认到账日期,必传且格式yyyy-MM-dd", NbErrorCode.INVALID_PARAM); + } + // 验证确认到账金额 + if (null == param.getAccountAmount() || param.getAccountAmount().compareTo(BigDecimal.ZERO) == 0) { + throw new ClientException("无效的确认到账金额", NbErrorCode.INVALID_PARAM); + } + } + // 2. 到账确认 + FinInvoiceAccountDO accountDO = this.finInvoiceService.nbAccountInvoice(accountId, invoiceId, param.getAccountDate(), param.getAccountAmount(), staffVO.getId()); + this.saveExecLog(LogTypeInvoiceAccount, true, param, param, "success"); + + param.setAccountId(null == accountDO ? "" : accountDO.getId()); + return param; + } catch (Exception e) { + this.saveExecLog(LogTypeInvoiceAccount, false, param, null, e.getMessage()); + throw e; + } + } + + @Override + public NbInvoiceStatusResult invoiceStatus(String invoiceNo) { + try { + // 验证用户 + this.verifyCurrentUser(); + // 1. 验证参数 + // 1.2 验证申请单号 + if (StringUtil.isEmpty(invoiceNo)) { + throw new ClientException("发票申请单号不能为空", NbErrorCode.INVALID_PARAM); + } + // 验证发票记录是否存在 + FinInvoiceDO invoiceDO = this.invoiceMapper.getInvoiceByNo(invoiceNo); + if (null == invoiceDO) { + throw new ClientException("开票申请单不存在", NbErrorCode.INVALID_PARAM); + } + // 验证开票来源 + if (null == this.recordMapper.findByKey(NbRecordTypeEnum.Type_Invoice.getValue(), invoiceNo)) { + throw new ClientException("该开票申请单无权限", NbErrorCode.INVALID_PARAM); + } + // 1.3 审批记录 + String approveMsg = ""; + List approveItems = new ArrayList<>(); + if (StringUtil.isNotEmpty(invoiceDO.getProcessInstanceId())) { + List tasks = this.sysProcessService.getInstanceTaskList(invoiceDO.getProcessInstanceId(), false); + if (null != tasks) { + for (ProcessAssigneeTaskVO task : tasks) { + NbApproveItem item = new NbApproveItem(); + item.setStepName(task.getName()); + int approveStatus = 0; + if ("提交单据".equals(task.getName())) { + if (null != task.getIsFinished() && task.getIsFinished()) approveStatus = 1; + } else { + if (null != task.getIsFinished() && task.getIsFinished()) { + approveStatus = (null != task.getIsApproved() && task.getIsApproved()) ? 1 : 2; + } + } + item.setApproveStatus(approveStatus); + if (null != task.getAuditTime()) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + item.setApproveTime(sdf.format(task.getAuditTime())); + } + if (2 == approveStatus) { + item.setApproveRejectReason(task.getRejectReason()); + approveMsg = task.getRejectReason(); + } + if (task.getIsFinished()) { + if (null != task.getAssignee()) { + item.setApproveDept(task.getAssignee().getDeptName()); + item.setApproveStaff(task.getAssignee().getName()); + } + } + List candidateItems = new ArrayList<>(); + if (null != task.getCandidateUsers()) { + for (User user : task.getCandidateUsers()) { + if (null == user) continue; + NbApproveCandidateItem one = new NbApproveCandidateItem(); + one.setDeptName(user.getDeptName()); + one.setStaffName(user.getName()); + candidateItems.add(one); + } + } else if (null != task.getCandidateGroups()) { + for (Group group : task.getCandidateGroups()) { + if (null == group) continue; + NbApproveCandidateItem one = new NbApproveCandidateItem(); + one.setDeptName(group.getDeptName()); + one.setStaffName(group.getName()); + candidateItems.add(one); + } + } + item.setCandidateItems(candidateItems); + approveItems.add(item); + } + } + } + // 2. + NbInvoiceStatusResult res = new NbInvoiceStatusResult(); + res.setInvoiceNo(invoiceDO.getInvoiceNo()); + res.setStatus(invoiceDO.getApplyStatus()); + res.setApproveMsg(approveMsg); + res.setApproveItems(approveItems); + + this.saveExecLog(LogTypeInvoiceStatus, true, invoiceNo, res, "success"); + return res; + } catch (Exception e) { + this.saveExecLog(LogTypeInvoiceStatus, false, invoiceNo, null, e.getMessage()); + throw e; + } + } + + @Override + public void invoiceForm(String invoiceNo, HttpServletResponse response) { + try { + // 验证用户 + this.verifyCurrentUser(); + // 1.1 验证申请单号 + if (StringUtil.isEmpty(invoiceNo)) { + throw new ClientException("发票申请单号不能为空", NbErrorCode.INVALID_PARAM); + } + // 验证发票记录是否存在 + FinInvoiceDO invoiceDO = this.invoiceMapper.getInvoiceByNo(invoiceNo); + if (null == invoiceDO) { + throw new ClientException("开票申请单不存在", NbErrorCode.INVALID_PARAM); + } + // 验证开票来源 + if (null == this.recordMapper.findByKey(NbRecordTypeEnum.Type_Invoice.getValue(), invoiceNo)) { + throw new ClientException("该开票申请单无权限", NbErrorCode.INVALID_PARAM); + } + // 1.2 文件模板 + FinReportBaseDO modeDO = this.finReportBaseMapper.getInvoiceModeItem(200, "[NB-SYS]"); + if (null == modeDO || StringUtil.isEmpty(modeDO.getBName())) { + throw new ClientException("开票申请单模板文件不存在,无法下载", NbErrorCode.INVALID_PARAM); + } + // 2. 下载文件 + Map vars = this.finInvoiceService.exportInvoiceForm(invoiceDO.getId()); + // 导出模版文件 默认路径 + String exportTempDir = ExportTemplateEnum.FIN_INVOICE_FORM_PATH.getTemplateDir() + modeDO.getBName(); + InputStream inputStream = getClass().getResourceAsStream(exportTempDir); + String fileName = "开票申请单(" + vars.get("invoiceNo") + ").pdf"; + DocxBuilder.create().template(inputStream) + .putAll(vars) + .convert2PDF() + .out(response, fileName); + this.saveExecLog(LogTypeInvoiceForm, true, invoiceNo, null, "success"); + } catch (ClientException ex) { + this.saveExecLog(LogTypeInvoiceForm, false, invoiceNo, null, ex.getMessage()); + throw ex; + } catch (Exception e) { + this.saveExecLog(LogTypeInvoiceForm, false, invoiceNo, null, e.getMessage()); + throw new ServerException(CommonErrorCode.HTTP_RESPONSE_OUTPUT_STREAM_FETCH_FAILED, e); + } + } + + @Override + public NbProjectParam getProject(NbProjectQueryParam param) { + try { + // 验证用户 + this.verifyCurrentUser(); + // 1.1 验证参数 + if (null == param || (StringUtil.isEmpty(param.getProjectNo()) && StringUtil.isEmpty(param.getProjectName()))) { + throw new ClientException("项目编号、项目名称不能同时为空", NbErrorCode.INVALID_PARAM); + } + // 2. + NbProjectParam projectRes = null; + if (StringUtil.isNotEmpty(param.getProjectNo())) { + // 1.2 验证项目来源 + if (null == this.recordMapper.findByKey(NbRecordTypeEnum.Type_Project.getValue(), param.getProjectNo())) { + throw new ClientException("项目编号不存在(无效的编号或不是同步项目)", NbErrorCode.INVALID_PARAM); + } + projectRes = this.projectInfoMapper.getNbProjectInfo(param.getProjectNo()); + } else { + projectRes = this.projectInfoMapper.getNbProjectInfoByName(param.getProjectName()); + if (null != projectRes && StringUtil.isNotEmpty(projectRes.getProjectNo())) { + // 1.2 验证项目来源 + if (null == this.recordMapper.findByKey(NbRecordTypeEnum.Type_Project.getValue(), projectRes.getProjectNo())) { + throw new ClientException("项目名称不存在(无效的名称或不是同步项目)", NbErrorCode.INVALID_PARAM); + } + } + } + if (null == projectRes) { + throw new ClientException("项目信息不存在", NbErrorCode.INVALID_PARAM); + } + this.saveExecLog(LogTypeProjectInfo, true, param, projectRes, "success"); + return projectRes; + } catch (Exception e) { + this.saveExecLog(LogTypeProjectInfo, false, param, null, e.getMessage()); + throw e; + } + } + + @Override + public NbContractParam getContract(NbContractQueryParam param) { + try { + // 验证用户 + this.verifyCurrentUser(); + // 1.1 验证参数 + if (null == param || (StringUtil.isEmpty(param.getContractCode()) && StringUtil.isEmpty(param.getContractName()))) { + throw new ClientException("合同编号、合同名称不能同时为空", NbErrorCode.INVALID_PARAM); + } + + // 2. + NbContractParam contractRes = null; + if (StringUtil.isNotEmpty(param.getContractCode())) { + // 1.2 验证合同来源 + if (null == this.recordMapper.findByKey(NbRecordTypeEnum.Type_Contract.getValue(), param.getContractCode())) { + throw new ClientException("合同编号不存在(无效的编号或不是同步合同)", NbErrorCode.INVALID_PARAM); + } + contractRes = this.contractMapper.getNbContractInfo(param.getContractCode()); + } else { + contractRes = this.contractMapper.getNbContractInfoByName(param.getContractName()); + if (null != contractRes && StringUtil.isNotEmpty(contractRes.getContractCode())) { + // 1.2 验证合同来源 + if (null == this.recordMapper.findByKey(NbRecordTypeEnum.Type_Contract.getValue(), contractRes.getContractCode())) { + throw new ClientException("合同名称不存在(无效的名称或不是同步合同)", NbErrorCode.INVALID_PARAM); + } + } + } + + if (null == contractRes) { + throw new ClientException("合同信息不存在", NbErrorCode.INVALID_PARAM); + } + this.saveExecLog(LogTypeContractInfo, true, param, param, "success"); + return contractRes; + } catch (Exception e) { + this.saveExecLog(LogTypeContractInfo, false, param, null, e.getMessage()); + throw e; + } + } + + private static final String OP_CLOSE = "CLOSE"; + private static final String OP_RESTART = "RESTART"; + + @Data + class ProjectChangeParam { + private String status; + private String projectNo; + public ProjectChangeParam(String s, String p) { + this.status = s; + this.projectNo = p; + } + } + + @Override + public Boolean changeProject(String status, String projectNo) { + ProjectChangeParam param = new ProjectChangeParam(status, projectNo); + try { + // 验证用户 + String userId = this.verifyCurrentUser(); + // 1.1 验证status参数 + if (StringUtil.isEmpty(status) || (!OP_CLOSE.equals(status) && !OP_RESTART.equals(status))) { + throw new ClientException("调整状态无效(CLOSE、RESTART)", NbErrorCode.INVALID_PARAM); + } + // 1.2 验证 projectNo + if (StringUtil.isEmpty(projectNo)) { + throw new ClientException("项目编号不能为空", NbErrorCode.INVALID_PARAM); + } + // 验证项目信息 + ProjectInfoDO projectInfoDO = this.projectInfoMapper.getByProjectNo(projectNo); + if (null == projectInfoDO) { + throw new ClientException("项目信息不存在", NbErrorCode.INVALID_PARAM); + } + // 验证项目来源 + if (null == this.recordMapper.findByKey(NbRecordTypeEnum.Type_Project.getValue(), projectNo)) { + throw new ClientException("项目编号不存在(无效的编号或不是同步项目)", NbErrorCode.INVALID_PARAM); + } + // 验证项目状态 + if (null == projectInfoDO.getProjectStatus()) { + throw new ClientException("项目信息-项目状态错误", NbErrorCode.INVALID_PARAM); + } + // 2. + if (OP_CLOSE.equals(status)) { // 关闭项目 + if (ProjectStatusEnum.CLOSED.equals(projectInfoDO.getProjectStatus())) { + throw new ClientException("项目已关闭,无需关闭", NbErrorCode.INVALID_PARAM); + } + // 2.1 检查合同 删除已存在 + BizContractDO contractDO = this.contractMapper.getSaleContractByProjectId(projectInfoDO.getId()); + if (null != contractDO) { + this.saveExecLog(LogTypeProjectChange, true, param, contractDO, "success-save contract"); + this.contractMapper.deleteById(contractDO.getId()); + // 更新记录 + NbRecordDO recordDO = this.recordMapper.findByKey(NbRecordTypeEnum.Type_Contract.getValue(), contractDO.getCode()); + if (null != recordDO) { + recordDO.setIsDelete(1); + recordDO.setUpdateUser(userId); + recordDO.setUpdateTime(LocalDateTime.now()); + this.recordMapper.updateById(recordDO); + } + } + // 2.3 调整项目状态 + projectInfoDO.setProjectStatus(ProjectStatusEnum.CLOSED); + } else { // 重新启动项目 + if (!ProjectStatusEnum.CLOSED.equals(projectInfoDO.getProjectStatus())) { + throw new ClientException("项目不是关闭状态,无需重新启动", NbErrorCode.INVALID_PARAM); + } + // 2.3 调整项目状态 + projectInfoDO.setProjectStatus(ProjectStatusEnum.NOT_INITIATED); + } + projectInfoDO.setCreateTime(LocalDateTime.now()); + projectInfoDO.setCreateUser("nb-sys"); + this.projectInfoMapper.updateById(projectInfoDO); + this.saveExecLog(LogTypeProjectChange, true, param, true, "success"); + return true; + } catch (Exception e) { + this.saveExecLog(LogTypeProjectChange, false, param, null, e.getMessage()); + throw e; + } + } + + private String verifyCurrentUser() { + // 当前用户 + String userId = UserContextHolder.currentUser(); + if (StringUtil.isEmpty(userId)) { + throw new ClientException("用户未登录", NbErrorCode.NO_LOGIN); + } + // 验证权限 + List users = this.finReportBaseMapper.listBaseByName(301, userId, null); + if (null == users || users.size() == 0) { + throw new ClientException("用户无权限", NbErrorCode.NO_LOGIN); + } + return userId; + } + + private void saveExecRecord(NbRecordTypeEnum recordType, String key) { + NbRecordDO recordDO = new NbRecordDO(); + recordDO.setRecordType(null == recordType ? "null" : recordType.getValue()); + recordDO.setRecordKey(key); + recordDO.setRecordFlag(0); + recordDO.setIsDelete(0); + this.recordMapper.insert(recordDO); + } + + private void saveExecLog(String logType, boolean isSuc, Object param, Object res, String errMsg) { + NbLogDO logDO = new NbLogDO(); + logDO.setLogType(logType); + logDO.setLogParam(JSONTool.convertToString(param)); + logDO.setLogRes(JSONTool.convertToString(res)); + logDO.setIsSuc(isSuc ? 1 : 0); + logDO.setErrMsg(errMsg); + this.logMapper.insert(logDO); + } +} diff --git a/src/main/java/com/gy/pgcm/nb/web/NbController.java b/src/main/java/com/gy/pgcm/nb/web/NbController.java new file mode 100644 index 0000000..f1df284 --- /dev/null +++ b/src/main/java/com/gy/pgcm/nb/web/NbController.java @@ -0,0 +1,125 @@ +package com.gy.pgcm.nb.web; + +import cn.bespinglobal.amg.common.auth.PassAuth; +import cn.bespinglobal.amg.common.result.Response; +import com.gy.pgcm.nb.model.param.*; +import com.gy.pgcm.nb.service.INbService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import springfox.documentation.annotations.ApiIgnore; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + +/** + *

TODO

+ * + * @author zg + * @since 2023/12/25 + */ +@Api(tags = "宁波系统数据对接接口") +@RestController +@RequestMapping("/api/nb") +public class NbController { + + @Autowired + private INbService nbService; + + @PassAuth + @ApiOperation(value = "同步项目信息", notes = "同步项目信息", produces = "application/json") + @PostMapping("/project") + public Response project(@Valid @RequestBody NbProjectParam param) { + return Response.ok(this.nbService.project(param)); + } + + @PassAuth + @ApiOperation(value = "同步合同信息", notes = "同步合同信息", produces = "application/json") + @PostMapping("/contract") + public Response contract(@Valid @RequestBody NbContractParam param) { + return Response.ok(this.nbService.contract(param)); + } + + @PassAuth + @ApiOperation(value = "同步开票信息", notes = "同步开票信息", produces = "application/json") + @PostMapping("/invoice") + public Response invoice(@Valid @RequestBody NbInvoiceParam param) { + return Response.ok(this.nbService.invoice(param)); + } + + @PassAuth + @ApiOperation(value = "同步开票信息-删除", notes = "同步开票信息-删除", produces = "application/json") + @DeleteMapping("/invoice/{invoiceNo}") + public Response invoiceDelete(@ApiParam(value = "发票申请单号", required = true) @PathVariable String invoiceNo) { + return Response.ok(this.nbService.invoiceDelete(invoiceNo)); + } + + @PassAuth + @ApiOperation(value = "发票证明文件上传", notes = "发票证明文件上传") + @PostMapping(value = "/invoice/uploadEvidence") + public Response uploadEvidence(@ApiParam(value = "文件") @RequestParam("file") MultipartFile file) { + return Response.ok(this.nbService.uploadEvidence(file)); + } + + @PassAuth + @ApiOperation(value = "开票确认", notes = "开票确认", produces = "application/json") + @PostMapping("/invoice/confirm") + public Response invoiceConfirm(@Valid @RequestBody NbInvoiceConfirmParam param) { + return Response.ok(this.nbService.invoiceConfirm(param)); + } + + @PassAuth + @ApiOperation(value = "同步开票确认收入信息(新增、删除)", notes = "同步开票确认收入信息(新增、删除)", produces = "application/json") + @PostMapping("/invoice/income") + public Response invoiceIncome(@Valid @RequestBody NbInvoiceIncomeParam param) { + return Response.ok(this.nbService.invoiceIncome(param)); + } + + @PassAuth + @ApiOperation(value = "同步开票确认到账信息(新增、删除)", notes = "同步开票确认到账信息(新增、删除)", produces = "application/json") + @PostMapping("/invoice/account") + public Response invoiceAccount(@Valid @RequestBody NbInvoiceAccountParam param) { + return Response.ok(this.nbService.invoiceAccount(param)); + } + + @PassAuth + @ApiOperation(value = "获取开票申请审批信息", notes = "获取开票申请审批信息", produces = "application/json") + @GetMapping("/invoice/status/{invoiceNo}") + public Response invoiceStatus(@ApiParam(value = "发票申请单号", required = true) @PathVariable String invoiceNo) { + return Response.ok(this.nbService.invoiceStatus(invoiceNo)); + } + + @PassAuth + @ApiOperation(value = "获取开票申请单文件", notes = "获取开票申请单文件") + @GetMapping("/invoice/form/{invoiceNo}") + public void invoiceForm(@ApiParam(value = "发票申请单号", required = true)@PathVariable String invoiceNo, + @ApiIgnore HttpServletResponse response) { + this.nbService.invoiceForm(invoiceNo, response); + } + + @PassAuth + @ApiOperation(value = "获取项目信息", notes = "获取项目信息") + @GetMapping("/project") + public Response getProject(@Valid NbProjectQueryParam param) { + return Response.ok(this.nbService.getProject(param)); + } + + @PassAuth + @ApiOperation(value = "获取合同信息", notes = "获取合同信息") + @GetMapping("/contract") + public Response getContract(@Valid NbContractQueryParam param) { + return Response.ok(this.nbService.getContract(param)); + } + + @PassAuth + @ApiOperation(value = "关闭、重新启动项目", notes = "关闭、重新启动项目") + @PutMapping("/project/{status}/{projectNo}") + public Response changeProject(@ApiParam(value = "调整状态 CLOSE 关闭; RESTART 重新启动", required = true) @PathVariable String status, + @ApiParam(value = "项目编号", required = true) @PathVariable String projectNo) { + return Response.ok(this.nbService.changeProject(status, projectNo)); + } + +} diff --git a/src/main/resources/mapper/nb/NbRecordMapper.xml b/src/main/resources/mapper/nb/NbRecordMapper.xml new file mode 100644 index 0000000..eff33cd --- /dev/null +++ b/src/main/resources/mapper/nb/NbRecordMapper.xml @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file