Merge branch 'feature/CBS8对接' into custom/艾志工业

This commit is contained in:
钱涛 2025-03-05 17:18:18 +08:00
commit 98ab42d4e1
38 changed files with 3618 additions and 61 deletions

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="GB2312"?>
<config name="CBS字段映射配置">
<table name="境内账户明细" key="uf_jnzhmx" modeId="10">
<field name="交易流水号" key="jylsh" ebsKey="transactionSerialNumber" unique="true"/>
<field name="收款日期" key="skrq" ebsKey="bankTransactionDate"/>
<field name="汇款人" key="hkr" ebsKey="unitName"/>
<field name="对应客户" key="dykh" ebsKey="unitName"/>
<field name="金额" key="je" ebsKey="incurredAmount"/>
</table>
<table name="票据收款明细" key="uf_pjskmx" modeId="11">
<field name="收款日期" key="skrq" ebsKey="acceptorDate"/>
<field name="汇款人" key="hkr" ebsKey="drawerName"/>
<field name="对应客户" key="dykh" ebsKey="drawerName"/>
<field name="金额" key="je" ebsKey="billAmount"/>
<field name="票据编号" key="pjbh" ebsKey="billNbr" unique="true"/>
<field name="出票日期" key="cprq" ebsKey="issueDate"/>
<field name="到期日期" key="dqrq" ebsKey="dueDate"/>
<field name="承兑银行" key="cdyx" ebsKey="acceptorName"/>
</table>
<table name="票据池" key="uf_pjc" modeId="13">
<field name="收到日期/开具日期" key="sdrqkjrq" ebsKey="acceptorDate"/>
<field name="回款人/收款人" key="hkrskr" ebsKey="drawerName"/>
<field name="票面金额" key="pmje" ebsKey="billAmount"/>
<field name="票据编号" key="pjbh" ebsKey="billNbr" unique="true"/>
<field name="出票日期" key="cprq" ebsKey="issueDate"/>
<field name="到期日期" key="dqrq" ebsKey="dueDate"/>
<field name="承兑银行/付款银行" key="cdyhfkyh" ebsKey="acceptorName/"/>
</table>
</config>

View File

@ -0,0 +1,12 @@
# ??ID
app_id=Yg8fWSvs
# ????
app_secret=1f23768c02219d7864b0009c30a1b6a59fe84606
# ????
bodyEncryptionKey=0467E11F7CA86D884C990D4F3F5C2A1EFEEBB02B9878F4FDDCB7899DFABADCC8F38FC23F007A8AF9B2EB8A1D313959647CD8A1542F0414116AE6CFCA792346A802
# ????????
signEncryptionPrivateKey=135d6d61d5e820a979e58f4939abbd528c82528c8c276852445854377e1df247
# ????????
bodyDecryptionKey=135d6d61d5e820a979e58f4939abbd528c82528c8c276852445854377e1df247
# ????
host=https://cbs8-openapi-reprd.csuat.cmburl.cn

View File

@ -439,11 +439,11 @@ public class SIAccountBiz extends Service {
public List<Long> listCanPayEmpIds(Long paymentOrganization, String billMonth) {
List<Long> listCanPayEmpIds = new ArrayList<>();
//社保档案中可进行缴纳的人员
List<Long> socialCanPayEmpIds = getSocialSchemeMapper().listCanPayEmpIds(paymentOrganization, billMonth);
List<Long> socialCanPayEmpIds = getSocialSchemeMapper().listCanPayEmpIds(paymentOrganization, billMonth, 0);
//公积金档案中可进行缴纳的人员
List<Long> fundCanPayEmpIds = getFundSchemeMapper().listCanPayEmpIds(paymentOrganization, billMonth);
List<Long> fundCanPayEmpIds = getFundSchemeMapper().listCanPayEmpIds(paymentOrganization, billMonth, 0);
//其他福利档案中可进行缴纳的人员
List<Long> otherCanPayEmpIds = getOtherSchemeMapper().listCanPayEmpIds(paymentOrganization, billMonth);
List<Long> otherCanPayEmpIds = getOtherSchemeMapper().listCanPayEmpIds(paymentOrganization, billMonth, 0);
if (socialCanPayEmpIds != null && socialCanPayEmpIds.size() > 0) {
listCanPayEmpIds.addAll(socialCanPayEmpIds);
}

View File

@ -23,4 +23,6 @@ public class OtherDeductionDetailDeleteParam {
// 主键id
private List<Long> ids;
private Long mainId;
}

View File

@ -17,4 +17,6 @@ public interface SQLMapper {
List<Map> runSQL(@Param("sql") String sql);
List<Long> listLong(@Param("sql") String sql);
List<String> listString(@Param("sql") String sql);
}

View File

@ -9,4 +9,8 @@
<select id="listLong" resultType="long">
${sql}
</select>
<select id="listString" resultType="string">
${sql}
</select>
</mapper>

View File

@ -0,0 +1,57 @@
package com.engine.salary.mapper.cbs;
import com.engine.salary.remote.cbs8.po.UfHkrdzbPO;
import java.util.List;
public interface UfHkrdzbMapper {
/**
* 查询所有记录
*
* @return 返回集合没有返回空List
*/
List<UfHkrdzbPO> listAll();
/**
* 条件查询
*
* @return 返回集合没有返回空List
*/
List<UfHkrdzbPO> listSome(UfHkrdzbPO ufHkrdzb);
/**
* 根据主键查询
*
* @param id 主键
* @return 返回记录没有返回null
*/
UfHkrdzbPO getById(Integer id);
/**
* 新增忽略null字段
*
* @param ufHkrdzb 新增的记录
* @return 返回影响行数
*/
int insertIgnoreNull(UfHkrdzbPO ufHkrdzb);
/**
* 修改修改所有字段
*
* @param ufHkrdzb 修改的记录
* @return 返回影响行数
*/
int update(UfHkrdzbPO ufHkrdzb);
/**
* 修改忽略null字段
*
* @param ufHkrdzb 修改的记录
* @return 返回影响行数
*/
int updateIgnoreNull(UfHkrdzbPO ufHkrdzb);
}

View File

@ -0,0 +1,322 @@
<?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.engine.salary.mapper.cbs.UfHkrdzbMapper">
<resultMap id="BaseResultMap" type="com.engine.salary.remote.cbs8.po.UfHkrdzbPO">
<result column="id" property="id"/>
<result column="requestId" property="requestId"/>
<result column="formmodeid" property="formmodeid"/>
<result column="modedatacreater" property="modedatacreater"/>
<result column="modedatacreatertype" property="modedatacreatertype"/>
<result column="modedatacreatedate" property="modedatacreatedate"/>
<result column="modedatacreatetime" property="modedatacreatetime"/>
<result column="MODEUUID" property="modeuuid"/>
<result column="form_biz_id" property="formBizId"/>
<result column="gsbm" property="gsbm"/>
<result column="khbm" property="khbm"/>
<result column="khmc" property="khmc"/>
<result column="bmbm" property="bmbm"/>
<result column="bmd" property="bmd"/>
<result column="bm" property="bm"/>
<result column="modedatamodifier" property="modedatamodifier"/>
<result column="modedatamodifydatetime" property="modedatamodifydatetime"/>
<result column="departmentId" property="departmentId"/>
</resultMap>
<!-- 表字段 -->
<sql id="baseColumns">
t
.
id
, t.requestId
, t.formmodeid
, t.modedatacreater
, t.modedatacreatertype
, t.modedatacreatedate
, t.modedatacreatetime
, t.MODEUUID
, t.form_biz_id
, t.gsbm
, t.khbm
, t.khmc
, t.bmbm
, t.bmd
, t.bm
, t.modedatamodifier
, t.modedatamodifydatetime
</sql>
<!-- 查询全部 -->
<select id="listAll" resultMap="BaseResultMap">
SELECT
<include refid="baseColumns"/>
,d.id as departmentId
FROM uf_hkrdzb t
left join hrmdepartment d on t.bmbm = d.departmentcode
</select>
<!-- 根据主键获取单条记录 -->
<select id="getById" resultMap="BaseResultMap" parameterType="Integer">
SELECT
<include refid="baseColumns"/>
FROM uf_hkrdzb t
WHERE id = #{id}
</select>
<!-- 条件查询 -->
<select id="listSome" resultMap="BaseResultMap" parameterType="com.engine.salary.remote.cbs8.po.UfHkrdzbPO">
SELECT
<include refid="baseColumns"/>
FROM uf_hkrdzb t
WHERE 1=1
<if test="requestId != null">
AND requestId = #{requestId}
</if>
<if test="formmodeid != null">
AND formmodeid = #{formmodeid}
</if>
<if test="modedatacreater != null">
AND modedatacreater = #{modedatacreater}
</if>
<if test="modedatacreatertype != null">
AND modedatacreatertype = #{modedatacreatertype}
</if>
<if test="modedatacreatedate != null">
AND modedatacreatedate = #{modedatacreatedate}
</if>
<if test="modedatacreatetime != null">
AND modedatacreatetime = #{modedatacreatetime}
</if>
<if test="modeuuid != null">
AND MODEUUID = #{modeuuid}
</if>
<if test="formBizId != null">
AND form_biz_id = #{formBizId}
</if>
<if test="gsbm != null">
AND gsbm = #{gsbm}
</if>
<if test="khbm != null">
AND khbm = #{khbm}
</if>
<if test="khmc != null">
AND khmc = #{khmc}
</if>
<if test="bmbm != null">
AND bmbm = #{bmbm}
</if>
<if test="bmd != null">
AND bmd = #{bmd}
</if>
<if test="bm != null">
AND bm = #{bm}
</if>
<if test="modedatamodifier != null">
AND modedatamodifier = #{modedatamodifier}
</if>
<if test="modedatamodifydatetime != null">
AND modedatamodifydatetime = #{modedatamodifydatetime}
</if>
<if test="ids != null and ids.size()>0">
AND id IN
<foreach collection="ids" open="(" item="id" separator="," close=")">
#{id}
</foreach>
</if>
ORDER BY id DESC
</select>
<!-- 插入不为NULL的字段 -->
<insert id="insertIgnoreNull" parameterType="com.engine.salary.remote.cbs8.po.UfHkrdzbPO">
INSERT INTO uf_hkrdzb
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="requestId != null">
requestId,
</if>
<if test="formmodeid != null">
formmodeid,
</if>
<if test="modedatacreater != null">
modedatacreater,
</if>
<if test="modedatacreatertype != null">
modedatacreatertype,
</if>
<if test="modedatacreatedate != null">
modedatacreatedate,
</if>
<if test="modedatacreatetime != null">
modedatacreatetime,
</if>
<if test="modeuuid != null">
MODEUUID,
</if>
<if test="formBizId != null">
form_biz_id,
</if>
<if test="gsbm != null">
gsbm,
</if>
<if test="khbm != null">
khbm,
</if>
<if test="khmc != null">
khmc,
</if>
<if test="bmbm != null">
bmbm,
</if>
<if test="bmd != null">
bmd,
</if>
<if test="bm != null">
bm,
</if>
<if test="modedatamodifier != null">
modedatamodifier,
</if>
<if test="modedatamodifydatetime != null">
modedatamodifydatetime,
</if>
</trim>
<trim prefix="VALUES (" suffix=")" suffixOverrides=",">
<if test="requestId != null">
#{requestId},
</if>
<if test="formmodeid != null">
#{formmodeid},
</if>
<if test="modedatacreater != null">
#{modedatacreater},
</if>
<if test="modedatacreatertype != null">
#{modedatacreatertype},
</if>
<if test="modedatacreatedate != null">
#{modedatacreatedate},
</if>
<if test="modedatacreatetime != null">
#{modedatacreatetime},
</if>
<if test="modeuuid != null">
#{modeuuid},
</if>
<if test="formBizId != null">
#{formBizId},
</if>
<if test="gsbm != null">
#{gsbm},
</if>
<if test="khbm != null">
#{khbm},
</if>
<if test="khmc != null">
#{khmc},
</if>
<if test="bmbm != null">
#{bmbm},
</if>
<if test="bmd != null">
#{bmd},
</if>
<if test="bm != null">
#{bm},
</if>
<if test="modedatamodifier != null">
#{modedatamodifier},
</if>
<if test="modedatamodifydatetime != null">
#{modedatamodifydatetime},
</if>
</trim>
</insert>
<!-- 更新,更新全部字段 -->
<update id="update" parameterType="com.engine.salary.remote.cbs8.po.UfHkrdzbPO">
UPDATE uf_hkrdzb
<set>
requestId=#{requestId},
formmodeid=#{formmodeid},
modedatacreater=#{modedatacreater},
modedatacreatertype=#{modedatacreatertype},
modedatacreatedate=#{modedatacreatedate},
modedatacreatetime=#{modedatacreatetime},
MODEUUID=#{modeuuid},
form_biz_id=#{formBizId},
gsbm=#{gsbm},
khbm=#{khbm},
khmc=#{khmc},
bmbm=#{bmbm},
bmd=#{bmd},
bm=#{bm},
modedatamodifier=#{modedatamodifier},
modedatamodifydatetime=#{modedatamodifydatetime},
</set>
WHERE id = #{id}
</update>
<!-- 更新不为NULL的字段 -->
<update id="updateIgnoreNull" parameterType="com.engine.salary.remote.cbs8.po.UfHkrdzbPO">
UPDATE uf_hkrdzb
<set>
<if test="requestId != null">
requestId=#{requestId},
</if>
<if test="formmodeid != null">
formmodeid=#{formmodeid},
</if>
<if test="modedatacreater != null">
modedatacreater=#{modedatacreater},
</if>
<if test="modedatacreatertype != null">
modedatacreatertype=#{modedatacreatertype},
</if>
<if test="modedatacreatedate != null">
modedatacreatedate=#{modedatacreatedate},
</if>
<if test="modedatacreatetime != null">
modedatacreatetime=#{modedatacreatetime},
</if>
<if test="modeuuid != null">
MODEUUID=#{modeuuid},
</if>
<if test="formBizId != null">
form_biz_id=#{formBizId},
</if>
<if test="gsbm != null">
gsbm=#{gsbm},
</if>
<if test="khbm != null">
khbm=#{khbm},
</if>
<if test="khmc != null">
khmc=#{khmc},
</if>
<if test="bmbm != null">
bmbm=#{bmbm},
</if>
<if test="bmd != null">
bmd=#{bmd},
</if>
<if test="bm != null">
bm=#{bm},
</if>
<if test="modedatamodifier != null">
modedatamodifier=#{modedatamodifier},
</if>
<if test="modedatamodifydatetime != null">
modedatamodifydatetime=#{modedatamodifydatetime},
</if>
</set>
WHERE id = #{id}
</update>
</mapper>

View File

@ -28,6 +28,8 @@ public interface SIAccountDetailTempMapper {
*/
void batchDelByEmpIdsAndMonthAndPayOrg(@Param("employeeIds") Collection<Long> employeeIds, @Param("billMonth") String billMonth, @Param("paymentOrganization") Long paymentOrganization);
void batchDelByMonthAndPayOrg(@Param("billMonth") String billMonth, @Param("paymentOrganization") Long paymentOrganization);
/**
* 批量保存
* @param accounts

View File

@ -139,6 +139,14 @@
</foreach>
</delete>
<update id="batchDelByMonthAndPayOrg">
UPDATE hrsa_bill_detail_temp
SET delete_type = 1
WHERE delete_type = 0
AND bill_month = #{billMonth}
AND payment_organization = #{paymentOrganization}
</update>
<insert id="batchSaveAccountTempDetails">
INSERT INTO hrsa_bill_detail_temp

View File

@ -67,7 +67,7 @@ public interface FundSchemeMapper {
* @param paymentOrganization
* @return
*/
List<Long> listCanPayEmpIds(@Param("paymentOrganization")Long paymentOrganization, @Param("billMonth")String billMonth);
List<Long> listCanPayEmpIds(@Param("paymentOrganization")Long paymentOrganization, @Param("billMonth")String billMonth, @Param("nonPayment") Integer nonPayment);
List<InsuranceArchivesFundSchemePO> listAll();

View File

@ -266,6 +266,7 @@
AND fund_scheme_id is not null
AND fund_start_time is not null AND fund_start_time <![CDATA[ <= ]]> #{billMonth}
AND (fund_end_time is null OR fund_end_time <![CDATA[ >= ]]> #{billMonth} OR fund_end_time ='')
AND non_payment = #{nonPayment}
</select>
<select id="listAll" resultMap="BaseResultMap">

View File

@ -66,7 +66,7 @@ public interface OtherSchemeMapper {
* @param paymentOrganization
* @return
*/
List<Long> listCanPayEmpIds(@Param("paymentOrganization")Long paymentOrganization, @Param("billMonth")String billMonth);
List<Long> listCanPayEmpIds(@Param("paymentOrganization")Long paymentOrganization, @Param("billMonth")String billMonth, @Param("nonPayment") Integer nonPayment);
List<InsuranceArchivesOtherSchemePO> listAll();

View File

@ -249,6 +249,7 @@
AND other_scheme_id is not null
AND other_start_time is not null AND other_start_time <![CDATA[ <= ]]> #{billMonth}
AND (other_end_time is null OR other_end_time <![CDATA[ >= ]]> #{billMonth} OR other_end_time ='')
AND non_payment = #{nonPayment}
</select>
<select id="listAll" resultMap="BaseResultMap">

View File

@ -92,7 +92,7 @@ public interface SocialSchemeMapper {
* @param paymentOrganization
* @return
*/
List<Long> listCanPayEmpIds(@Param("paymentOrganization")Long paymentOrganization, @Param("billMonth")String billMonth);
List<Long> listCanPayEmpIds(@Param("paymentOrganization")Long paymentOrganization, @Param("billMonth")String billMonth, @Param("nonPayment")Integer nonPayment);
List<InsuranceArchivesSocialSchemePO> listAll();

View File

@ -909,6 +909,7 @@
AND social_scheme_id is not null
AND social_start_time is not null AND social_start_time <![CDATA[ <= ]]> #{billMonth}
AND (social_end_time is null OR social_end_time <![CDATA[ >= ]]> #{billMonth} OR social_end_time ='')
AND non_payment = #{nonPayment}
</select>
<select id="listAll" resultMap="BaseResultMap">

View File

@ -0,0 +1,60 @@
package com.engine.salary.remote.cbs8.client;
import com.engine.salary.exception.SalaryRunTimeException;
import com.engine.salary.remote.cbs8.request.GetTransactionDetailRequest;
import com.engine.salary.remote.cbs8.response.GetTransactionDetailResponse;
import com.engine.salary.util.JsonUtil;
import com.engine.salary.util.SalaryI18nUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
@Slf4j
public class AccountManagementClient extends CBS8BaseClient {
public GetTransactionDetailResponse transactionDetailQuery(GetTransactionDetailRequest requestParam) throws IOException {
String url = host + "/openapi/account/openapi/v1/transaction-detail/query";
CloseableHttpClient client = HttpClients.custom()
// 禁止HttpClient自动解压缩
.disableContentCompression()
.build();
String requestData = JsonUtil.toJsonString(requestParam);
log.info("获取cbs交易参数" + url + "\n" + requestData);
HttpPost httpPost = setupRequest(url, requestData);
try (CloseableHttpResponse response = client.execute(httpPost)) {
byte[] finalResponseData = handleResponse(response);
String req = new String(finalResponseData, StandardCharsets.UTF_8);
GetTransactionDetailResponse getTransactionDetailResponse = JsonUtil.parseBean(req, GetTransactionDetailResponse.class);
log.info("获取cbs交易结果" + "\n" + JsonUtil.toJsonString(getTransactionDetailResponse));
if (Objects.isNull(getTransactionDetailResponse)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(156449, "服务异常"));
}
if (!"0".equals(getTransactionDetailResponse.getCode())) {
throw new SalaryRunTimeException(getTransactionDetailResponse.getMsg());
}
if (getTransactionDetailResponse.getData() == null) {
throw new SalaryRunTimeException("未获取数据");
}
return getTransactionDetailResponse;
} catch (IOException ignored) {
log.error("网络连接失败或超时!",ignored);
throw new SalaryRunTimeException("网络连接失败或超时!");
} finally {
client.close();
}
}
}

View File

@ -0,0 +1,57 @@
package com.engine.salary.remote.cbs8.client;
import com.engine.salary.exception.SalaryRunTimeException;
import com.engine.salary.remote.cbs8.request.GetDtaRequest;
import com.engine.salary.remote.cbs8.response.GetDtaResponse;
import com.engine.salary.util.JsonUtil;
import com.engine.salary.util.SalaryI18nUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
@Slf4j
public class BillManagementClient extends CBS8BaseClient {
public GetDtaResponse dtaQuery(GetDtaRequest requestParam) throws IOException {
String url = host + "/openapi/draft/openapi/v1/dta/query";
CloseableHttpClient client = HttpClients.custom()
// 禁止HttpClient自动解压缩
.disableContentCompression()
.build();
String requestData = JsonUtil.toJsonString(requestParam);
log.info("获取cbs票据参数" + url + "\n" + requestData);
HttpPost httpPost = setupRequest(url, requestData);
try (CloseableHttpResponse response = client.execute(httpPost)) {
byte[] finalResponseData = handleResponse(response);
String req = new String(finalResponseData, StandardCharsets.UTF_8);
GetDtaResponse getDtaResponse = JsonUtil.parseBean(req, GetDtaResponse.class);
log.info("获取cbs票据结果" + "\n" + JsonUtil.toJsonString(getDtaResponse));
if (Objects.isNull(getDtaResponse)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(156449, "服务异常"));
}
if (!"0".equals(getDtaResponse.getCode())) {
throw new SalaryRunTimeException(getDtaResponse.getMsg());
}
if (getDtaResponse.getData() == null) {
throw new SalaryRunTimeException("未获取数据");
}
return getDtaResponse;
} catch (IOException ignored) {
throw new SalaryRunTimeException("网络连接失败或超时!");
} finally {
client.close();
}
}
}

View File

@ -0,0 +1,167 @@
package com.engine.salary.remote.cbs8.client;
import cn.hutool.core.util.StrUtil;
import com.engine.salary.exception.SalaryRunTimeException;
import com.engine.salary.remote.cbs8.common.Constants;
import com.engine.salary.remote.cbs8.response.GetTokenResponse;
import com.engine.salary.remote.cbs8.util.SM2Util;
import com.engine.salary.util.HttpUtil;
import com.engine.salary.util.JsonUtil;
import com.engine.salary.util.SalaryI18nUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.apache.http.Header;
import org.apache.http.HttpMessage;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.protocol.HTTP;
import weaver.general.BaseBean;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.zip.GZIPInputStream;
@Slf4j
public class CBS8BaseClient {
static final String appId = new BaseBean().getPropValue("hrmSalaryCBS8", "app_id");
static final String appSecret = new BaseBean().getPropValue("hrmSalaryCBS8", "app_secret");
/**
* 财资管理云公钥(平台公钥)
*/
static final String bodyEncryptionKey = new BaseBean().getPropValue("hrmSalaryCBS8", "bodyEncryptionKey");
/**
* 企业私钥加密
*/
static final String signEncryptionPrivateKey = new BaseBean().getPropValue("hrmSalaryCBS8", "signEncryptionPrivateKey");
/**
* 企业私钥解密
*/
static final String bodyDecryptionKey = new BaseBean().getPropValue("hrmSalaryCBS8", "bodyDecryptionKey");
/**
* 域名
*/
static final String host = new BaseBean().getPropValue("hrmSalaryCBS8", "host");
/**
* 获取token
*
* @return
*/
public static String getToken() {
Map<String, String> params = new HashMap<>();
params.put("app_id", appId);
params.put("app_secret", appSecret);
params.put("grant_type", "client_credentials");
// 开始请求
String paramBody = JsonUtil.toJsonString(params);
String res = HttpUtil.doPost(host + "/openapi/app/v1/app/token", new HashMap<>(), paramBody, HttpUtil.JSON_TYPE);
GetTokenResponse getTokenResponse = JsonUtil.parseBean(res, GetTokenResponse.class);
log.info("获取token params:{} res: {}", paramBody, res);
if (Objects.isNull(getTokenResponse)) {
throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(156449, "服务异常"));
}
if (!"0".equals(getTokenResponse.getCode())) {
throw new SalaryRunTimeException(getTokenResponse.getMsg());
}
if (getTokenResponse.getData() == null) {
throw new SalaryRunTimeException("未获取数据");
}
if (StrUtil.isBlank(getTokenResponse.getData().getToken())) {
throw new SalaryRunTimeException("未获取token");
}
String token = getTokenResponse.getData().getToken();
return token;
}
/**
* 生成请求报文
*/
public static HttpPost setupRequest(String url, String requestData) {
long timestamp = System.currentTimeMillis();
// 请求数据拼接 报文体+时间戳
byte[] requestDataBytes = requestData.getBytes(StandardCharsets.UTF_8);
byte[] timestampBytes = ("&timestamp=" + timestamp).getBytes(StandardCharsets.UTF_8);
byte[] newBytes = new byte[requestDataBytes.length + timestampBytes.length];
System.arraycopy(requestDataBytes, 0, newBytes, 0, requestDataBytes.length);
System.arraycopy(timestampBytes, 0, newBytes, requestDataBytes.length, timestampBytes.length);
// 生成签名
byte[] signature = SM2Util.sign(signEncryptionPrivateKey, newBytes);
String sign = Base64.encodeBase64String(SM2Util.encodeDERSignature(signature));
// 设置请求URL
HttpPost httpPost = new HttpPost(url);
// 请求头设置签名
httpPost.setHeader(Constants.SIGN_HEADER_NAME, sign);
// 请求头设置时间戳
httpPost.setHeader(Constants.TIMESTAMP_HEADER, Long.toString(timestamp));
// 请求头设置请求参数格式请根据实际情况改写
httpPost.setHeader(HTTP.CONTENT_TYPE, Constants.TARGET_CONTENT_TYPE);
// 请求头设置TOKEN
String token = getToken();
httpPost.setHeader(Constants.AUTHORIZATION, Constants.BEARER + token);
// 报文体加密
byte[] encryptedData = SM2Util.encrypt(bodyEncryptionKey, requestDataBytes);
// 设置请求体
httpPost.setEntity(new ByteArrayEntity(encryptedData));
return httpPost;
}
/**
* 处理响应报文
*/
public byte[] handleResponse(HttpResponse response) throws IOException {
InputStream content = response.getEntity().getContent();
byte[] responseData = IOUtils.toByteArray(content);
if (responseData == null || responseData.length == 0) {
return responseData == null ? new byte[0] : responseData;
}
// 步骤1 原始响应报文解密 如果服务网关获取加解密密钥失败则无法解密请求报文且无法加密响应报文 这时候网关会直接返回错误信息响应报文是未加密状态
Boolean encryptionEnable = getHeader(response, Constants.ENCRYPTION_ENABLED_HEADER_NAME);
if (Boolean.TRUE.equals(encryptionEnable)) {
responseData = SM2Util.decrypt(bodyDecryptionKey, responseData);
}
Boolean xMbcloudCompress = getHeader(response, Constants.X_MBCLOUD_COMPRESS);
if (Boolean.TRUE.equals(xMbcloudCompress)) {
responseData = decompress(responseData);
}
return responseData;
}
private static Boolean getHeader(HttpMessage message, String name) {
Header header = message.getFirstHeader(name);
return header != null;
}
public static byte[] decompress(byte[] data) throws IOException {
ByteArrayInputStream input = new ByteArrayInputStream(data);
GZIPInputStream gzipInput = new GZIPInputStream(input);
return IOUtils.toByteArray(gzipInput);
}
}

View File

@ -0,0 +1,23 @@
package com.engine.salary.remote.cbs8.common;
/**
* @author: KeXue
* @time: 2022/8/25
* @description: 常量类
*/
public interface Constants {
String TARGET_CONTENT_TYPE = "application/json";
String SIGN_HEADER_NAME = "X-MBCLOUD-API-SIGN";
String TIMESTAMP_HEADER = "X-MBCLOUD-TIMESTAMP";
String ENCRYPTION_ENABLED_HEADER_NAME = "X-MBCLOUD-ENCRYPTION-ENABLED";
String X_MBCLOUD_COMPRESS = "X-Mbcloud-Compress";
String AUTHORIZATION = "Authorization";
String BEARER = "Bearer ";
}

View File

@ -0,0 +1,63 @@
package com.engine.salary.remote.cbs8.config;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
import com.thoughtworks.xstream.annotations.XStreamImplicit;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@XStreamAlias("config")
public class EBS2ECConfig {
@XStreamAlias("name")
@XStreamAsAttribute
private String name;
@XStreamImplicit(itemFieldName = "table")
private List<Table> tables;
@Data
public static class Table {
@XStreamAlias("name")
@XStreamAsAttribute
private String name;
@XStreamAlias("key")
@XStreamAsAttribute
private String key;
@XStreamAlias("modeId")
@XStreamAsAttribute
private Integer modeId;
@XStreamImplicit(itemFieldName = "field")
private List<Field> fields;
@Data
public static class Field {
@XStreamAlias("name")
@XStreamAsAttribute
private String name;
@XStreamAlias("key")
@XStreamAsAttribute
private String key;
@XStreamAlias("ebsKey")
@XStreamAsAttribute
private String ebsKey;
@XStreamAlias("unique")
@XStreamAsAttribute
private boolean unique;
}
}
}

View File

@ -0,0 +1,155 @@
package com.engine.salary.remote.cbs8.example;
import com.engine.salary.remote.cbs8.common.Constants;
import com.engine.salary.remote.cbs8.util.SM2Util;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.apache.http.Header;
import org.apache.http.HttpMessage;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HTTP;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.zip.GZIPInputStream;
/**
* @author: KeXue
* @time: 2022/8/25
* @description: SM2请求加解密实例
*/
@Slf4j
public class SM2Example {
/**
* 财资管理云公钥(平台公钥)
*/
static final String bodyEncryptionKey = "0467E11F7CA86D884C990D4F3F5C2A1EFEEBB02B9878F4FDDCB7899DFABADCC8F38FC23F007A8AF9B2EB8A1D313959647CD8A1542F0414116AE6CFCA792346A802";
/**
* 企业私钥加密
*/
static final String signEncryptionPrivateKey = "135d6d61d5e820a979e58f4939abbd528c82528c8c276852445854377e1df247";
/**
* 企业私钥解密
*/
static final String bodyDecryptionKey = "135d6d61d5e820a979e58f4939abbd528c82528c8c276852445854377e1df247";
/**
* 根据appid和appsecert获取的token
*/
static final String token = "e4cdf00f-3fc9-4845-ac57-6baaee620895";
/**
* 接口路径
*/
static final String TARGET_URL = "https://cbs8-openapi-reprd.csuat.cmburl.cn/openapi/account/accounts-current-balance/erp/query";
/**
* 请求体数据
*/
static final String requestData = "\n" + "{\"accountNo\":\"\"}";
public static void main(String[] args) throws Exception {
CloseableHttpClient client = HttpClients.custom()
// 禁止HttpClient自动解压缩
.disableContentCompression()
.build();
HttpPost httpPost = setupRequest();
try (CloseableHttpResponse response = client.execute(httpPost)) {
byte[] finalResponseData = handleResponse(response);
log.info("\n返回结果{}", new String(finalResponseData));
}catch (IOException ignored){
throw new IOException("网络连接失败或超时!");
}finally {
client.close();
}
}
/**
* 生成请求报文
*/
private static HttpPost setupRequest() {
long timestamp = System.currentTimeMillis();
// 请求数据拼接 报文体+时间戳
byte[] requestDataBytes = requestData.getBytes(StandardCharsets.UTF_8);
byte[] timestampBytes = ("&timestamp=" + timestamp).getBytes(StandardCharsets.UTF_8);
byte[] newBytes = new byte[requestDataBytes.length + timestampBytes.length];
System.arraycopy(requestDataBytes, 0, newBytes, 0, requestDataBytes.length);
System.arraycopy(timestampBytes, 0, newBytes, requestDataBytes.length, timestampBytes.length);
// 生成签名
byte[] signature = SM2Util.sign(signEncryptionPrivateKey, newBytes);
String sign = Base64.encodeBase64String(SM2Util.encodeDERSignature(signature));
log.info("签名:{}", sign);
// 设置请求URL
HttpPost httpPost = new HttpPost(TARGET_URL);
// 请求头设置签名
httpPost.setHeader(Constants.SIGN_HEADER_NAME, sign);
// 请求头设置时间戳
httpPost.setHeader(Constants.TIMESTAMP_HEADER, Long.toString(timestamp));
// 请求头设置请求参数格式请根据实际情况改写
httpPost.setHeader(HTTP.CONTENT_TYPE, Constants.TARGET_CONTENT_TYPE);
// 请求头设置TOKEN
httpPost.setHeader(Constants.AUTHORIZATION, Constants.BEARER + token);
// 报文体加密
byte[] encryptedData = SM2Util.encrypt(bodyEncryptionKey, requestDataBytes);
// 设置请求体
httpPost.setEntity(new ByteArrayEntity(encryptedData));
return httpPost;
}
/**
* 处理响应报文
*/
private static byte[] handleResponse(HttpResponse response) throws Exception {
InputStream content = response.getEntity().getContent();
byte[] responseData = IOUtils.toByteArray(content);
if (responseData == null || responseData.length == 0) {
return responseData == null ? new byte[0] : responseData;
}
// 步骤1 原始响应报文解密 如果服务网关获取加解密密钥失败则无法解密请求报文且无法加密响应报文 这时候网关会直接返回错误信息响应报文是未加密状态
Boolean encryptionEnable = getHeader(response, Constants.ENCRYPTION_ENABLED_HEADER_NAME);
if (Boolean.TRUE.equals(encryptionEnable)) {
responseData = SM2Util.decrypt(bodyDecryptionKey, responseData);
}
Boolean xMbcloudCompress = getHeader(response, Constants.X_MBCLOUD_COMPRESS);
if (Boolean.TRUE.equals(xMbcloudCompress)) {
responseData = decompress(responseData);
}
return responseData;
}
private static Boolean getHeader(HttpMessage message, String name) {
Header header = message.getFirstHeader(name);
return header != null;
}
public static byte[] decompress(byte[] data) throws IOException {
ByteArrayInputStream input = new ByteArrayInputStream(data);
GZIPInputStream gzipInput = new GZIPInputStream(input);
return IOUtils.toByteArray(gzipInput);
}
}

View File

@ -0,0 +1,55 @@
package com.engine.salary.remote.cbs8.po;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Collection;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UfHkrdzbPO {
private Integer id;
private Integer requestId;
private Integer formmodeid;
private Integer modedatacreater;
private Integer modedatacreatertype;
private String modedatacreatedate;
private String modedatacreatetime;
private String modeuuid;
private String formBizId;
private String gsbm;
private String khbm;
private String khmc;
private String bmbm;
private Integer bmd;
private Integer bm;
private Integer modedatamodifier;
private String modedatamodifydatetime;
private Collection<Long> ids;
private Integer departmentId;
}

View File

@ -0,0 +1,10 @@
package com.engine.salary.remote.cbs8.request;
import lombok.Data;
@Data
public class CBS8BaseRequest {
private int currentPage;
private int pageSize;
}

View File

@ -0,0 +1,108 @@
package com.engine.salary.remote.cbs8.request;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
import java.util.List;
@Data
@EqualsAndHashCode(callSuper = true)
public class GetDtaRequest extends CBS8BaseRequest {
/**
* 出票日期起 格式为yyyy-mm-dd出票日期起止不允许一边有值一边无值日期间隔最大为一年
*/
private String issueDateStart;
/**
* 出票日期止 格式为yyyy-mm-dd出票日期起止不允许一边有值一边无值日期间隔最大为一年
*/
private String issueDateEnd;
/**
* 到期日期起 格式为yyyy-mm-dd到期日期起止不允许一边有值一边无值日期间隔最大为一年
*/
private String dueDateStart;
/**
* 到期日期止 格式为yyyy-mm-dd到期日期起止不允许一边有值一边无值日期间隔最大为一年
*/
private String dueDateEnd;
/**
* 票据种类 AC01-银承AC02-商承
*/
private String billType;
/**
* 票据来源 多选1-直联交易2-台账交易3-台账登记4-挑票同步5-任务同步
*/
private List<String> draftSourceList;
/**
* 持票银行类型 多选见附录4.1.1.银行类型枚举
*/
private List<String> holdBankTypeList;
/**
* 持票人单位编码 多选填在cbs系统公共设置>基础信息>组织机构维护的单位编码
*/
private List<String> displayHoldOrganizationCodeList;
/**
* 持票人账号 多选
*/
private List<String> holdAccountList;
/**
* 持票签收日期起 格式为yyyy-mm-dd持票签收日期起止不允许一边有值一边无值日期间隔最大为一年
*/
private String holdSignDateStart;
/**
* 持票签收日期止 格式为yyyy-mm-dd持票签收日期起止不允许一边有值一边无值日期间隔最大为一年
*/
private String holdSignDateEnd;
/**
* 系统票据编号
*/
private String draftNbr;
/**
* 票据()
*/
private String billNbr;
/**
* 票据金额起 大于等于0,最多为两位小数且整数位上限为13位票据金额起止不允许一边有值一边无值单位
*/
private BigDecimal billAmountStart;
/**
* 票据金额止 大于等于0,最多为两位小数且整数位上限为13位票据金额起止不允许一边有值一边无值单位
*/
private BigDecimal billAmountEnd;
/**
* 子票区间起 子票区间起止不允许一边有值一边无值最多12位
*/
private String subBillIntervalStart;
/**
* 子票区间止 子票区间起止不允许一边有值一边无值,最多12位
*/
private String subBillIntervalEnd;
/**
* 系统票据类型 多选按附录4.1.3票据类型-票据状态-流通标志级联关系表选择后按顺序填写系统票据类型枚举见附录4.1.3票据状态枚举见附录4.1.4流通标志枚举见附录4.1.5
*/
private List<String> billVarietyList;
/**
* 票据状态
*/
private List<String> billStsList;
/**
* 流通标志
*/
private List<String> billTrsStsList;
/**
* 库存状态 1-已入库2-已出库 为空时默认查询全部数据
*/
private String stockFlag;
/**
* 出库方式 0-2-背书3-质押4-解质5-贴现6-分包7-结清, 8-作废 为空时默认查询全部数据
*/
private String outInvType;
/**
* 记录状态 NOR-正常USE-占用DEL-删除 SUC-完成为空时默认查询全部数据
*/
private String lockFlag;
}

View File

@ -0,0 +1,75 @@
package com.engine.salary.remote.cbs8.request;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
@Data
@EqualsAndHashCode(callSuper = true)
public class GetTransactionDetailRequest extends CBS8BaseRequest {
/**
* 开始日期 格式为yyyy-mm-dd
*/
private String startDate;
/**
* 结束日期 格式为yyyy-mm-dd
*/
private String endDate;
/**
* 日期类型 0-交易日期
*/
private String dateType;
/**
* 账户列表 查询账户列表不传默认返回全部
*/
private List<String> accountNoList;
/**
* 银行类型列表 例如招行CMB银行类型枚举见附录4.1.5
*/
private List<String> bankTypeList;
/**
* 币种列表 见附录币种枚举4.1.1
*/
private List<String> currencyList;
/**
* 明细来源
* B银行即银行直联
* U用户即手工/ERP接口导入
* 不传默认查全部
*/
private String detailedSources;
/**
* 明细类型 1-当日明细 2-历史明细 与明细日期无关仅标识数据来源银行的不同接口
*/
private String currentFlag;
/**
* 借贷类型 1-2-
*/
private String loanType;
/**
* 账户性质列表 客户在公共设置>基础信息>账户性质查询自定义内容例如AA-综合户此处传值AA
*/
private List<String> accountNatureList;
/**
* 银行流水号 银行流水号
*/
private String bankSerialNumber;
/**
* 交易流水号 交易流水号由CBS8定义生成的唯一标识
*/
private Long transactionSerialNumber;
/**
* 单位编码列表 客户在公共设置>基础信息>组织机构维护例如0001-XX科技有限公司此处传0001
*/
private List<String> unitCodeList;
/**
* ERP业务参考号 erpSerialNumber
*/
private String erpSerialNumber;
/**
* 款项性质列表
*/
private List<String> paymentNatureList;
}

View File

@ -0,0 +1,10 @@
package com.engine.salary.remote.cbs8.response;
import lombok.Data;
@Data
public class CBS8BaseResponse {
private String code;
private String msg;
}

View File

@ -0,0 +1,77 @@
package com.engine.salary.remote.cbs8.response;
import lombok.Data;
@Data
public class CBS8PageInfo {
/**
* 当前页
*/
private int pageNum;
/**
* 每页的数量
*/
private int pageSize;
/**
* 当前页的数量
*/
private int size;
/**
* 总页数
*/
private int pages;
/**
* 上一页
*/
private int prePage;
/**
* 下一页
*/
private int nextPage;
/**
* 总记录数
*/
private long total;
/**
* 当前页面第一个元素在数据库中的行号
*/
private int startRow;
/**
* 当前页面最后一个元素在数据库中的行号
*/
private int endRow;
/**
* 是否为第一页
*/
private boolean isFirstPage;
/**
* 是否为最后一页
*/
private boolean isLastPage;
/**
* 是否有前一页
*/
private boolean hasPreviousPage;
/**
* 是否有下一页
*/
private boolean hasNextPage;
/**
* 导航页码数
*/
private int navigatePages;
/**
* 所有导航页号
*/
private int[] navigatepageNums;
/**
* 导航条上的第一页
*/
private int navigateFirstPage;
/**
* 导航条上的最后一页
*/
private int navigateLastPage;
}

View File

@ -0,0 +1,440 @@
package com.engine.salary.remote.cbs8.response;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
@Data
@EqualsAndHashCode(callSuper = true)
public class GetDtaResponse extends CBS8BaseResponse {
/**
* 返回数据
*/
private Body data;
@Data
public static class Body extends CBS8PageInfo{
/**
* 明细列表
*/
private List<Detail> list;
}
@Data
public static class Detail {
/**
* 系统票据编号
*/
private String draftNbr;
/**
* 父系统票据编号
*/
private String fatDraftNbr;
/**
* 系统票据类型 系统票据类型枚举见附录4.1.3
*/
private String billVariety;
/**
* 票据()
*/
private String billNbr;
/**
* 是否可分包 0-未分包 1-已分包
*/
private String splitFlag;
/**
* 子票区间起
*/
private String subBillIntervalStart;
/**
* 子票区间止
*/
private String subBillIntervalEnd;
/**
* 子票区间
*/
private String subBillInterval;
/**
* 票据金额 大于等于0,最多为两位小数且整数位上限为13位单位
*/
private BigDecimal billAmount;
/**
* 票据种类 AC01-银承AC02-商承
*/
private String billType;
/**
* 出票日期 格式为yyyy-mm-dd
*/
private Date issueDate;
/**
* 到期日期 格式为yyyy-mm-dd
*/
private Date dueDate;
/**
* 票面收票日期 第一手收票人签收日期格式为yyyy-mm-dd
*/
private Date receiptDate;
/**
* 持票签收日期 票据签收日期格式为yyyy-mm-dd
*/
private Date holdSignDate;
/**
* 票面不得转让标记 EM00-可转让EM01-不可转让
*/
private String trfFlag;
/**
* 背书不得转让标记 EM00-可转让EM01-不可转让
*/
private String endorsementTransferFlg;
/**
* 票据状态 票据状态枚举见附录4.1.4
*/
private String billSts;
/**
* 流通标志 流通标志枚举见附录4.1.5
*/
private String billTrsSts;
/**
* 库存状态 0-未入库1-已入库2-已出库
*/
private String stockFlag;
/**
* 出库方式 0-2-背书3-质押4-解质5-贴现6-分包7-结清, 8-作废
*/
private String outInvType;
/**
* 风险状态 RS00-非风险票据 RS01-挂失止付 RS02-公示催告 RS03-司法冻结 RS05-争议票据 RS06-除权判决
*/
private String riskFlag;
/**
* 记录状态 NOR-正常USE-占用DEL-删除 SUC-完成
*/
private String lockFlag;
/**
* 票据来源
* 1-直联交易
* 2-系统交易
* 3-台账登记
* 4-挑票同步
* 5-任务同步
*/
private String draftSource;
/**
* 承兑人类型 RC00-银行(02), RC01-企业(00) ,RC02- 人民银行(01),RC03 -被代理行(A1),RC04-被代理财务公司(A2), RC05-财务公司(03), RC06-证券公司(03) ,RC07-基金公司(03)
*/
private String acceptorType;
/**
* 是否出票保证 1-0-
*/
private String drawerEnsureFlag;
/**
* 是否承兑保证 1-0-
*/
private String acceptorEnsureFlag;
/**
* 是否背书保证 1-0-
*/
private String backEnsureFlag;
/**
* 出票人名称
*/
private String drawerName;
/**
* 出票人是否内部企业 1-0-
*/
private String drawerInternalFlag;
/**
* 出票人单位名称
*/
private String drawerOrganizationName;
/**
* 出票人单位编码
*/
private String displayDrawerOrganizationCode;
/**
* 出票人是否客商企业 1-0-
*/
private String drawerCustomerFlg;
/**
* 出票人客商名称
*/
private String drawerCustomerName;
/**
* 出票人客商编号 填在cbs系统公共设置>基础信息>客商管理>客商信息管理维护的客商编号
*/
private String drawerCustomerNbr;
/**
* 出票人账户名称
*/
private String drawerAccountName;
/**
* 出票人账号
*/
private String drawerAccount;
/**
* 出票人开户行名称
*/
private String drawerBrnName;
/**
* 出票人联行号
*/
private String drawerInterbankNbr;
/**
* 收款人名称
*/
private String payeeName;
/**
* 收款人是否内部企业 1-0-
*/
private String payeeInternalFlag;
/**
* 收款人单位名称
*/
private String payeeOrganizationName;
/**
* 收款人单位编码
*/
private String displayPayeeOrganizationCode;
/**
* 收款人是否客商企业 1-0-
*/
private String payeeCustomerFlag;
/**
* 收款人客商名称
*/
private String payeeCustomerName;
/**
* 收款人客商编号 填在cbs系统公共设置>基础信息>客商管理>客商信息管理维护的客商编号
*/
private String payeeCustomerNbr;
/**
* 收款人账户名称
*/
private String payeeAccountName;
/**
* 收款人账号
*/
private String payeeAccount;
/**
* 收款人联行号
*/
private String payeeInterbankNbr;
/**
* 收款人开户行名称
*/
private String payeeBrnName;
/**
* 承兑人名称
*/
private String acceptorName;
/**
* 承兑人是否内部企业 1-0-
*/
private String acceptorInternalFlag;
/**
* 承兑人单位名称
*/
private String acceptorOrganizationName;
/**
* 承兑人单位编码
*/
private String displayAcceptorOrganizationCode;
/**
* 承兑人是否客商企业 1-0-
*/
private String acceptorCustomerFlg;
/**
* 承兑人客商名称
*/
private String acceptorCustomerName;
/**
* 承兑人客商编号 填在cbs系统公共设置>基础信息>客商管理>客商信息管理维护的客商编号
*/
private String acceptorCustomerNbr;
/**
* 承兑人账户名称
*/
private String acceptorAccountName;
/**
* 承兑人账号
*/
private String acceptorAccount;
/**
* 承兑人开户行名称
*/
private String acceptorBrnName;
/**
* 承兑人联行号
*/
private String acceptorInterbankNbr;
/**
* 到期无条件支付委托/承诺
*/
private String expireUnconditionalPay;
/**
* 承兑日期 格式为yyyy-mm-dd
*/
private Date acceptorDate;
/**
* 出票人评级主体
*/
private String drawerRateSubject;
/**
* 出票人信用等级 信用等级枚举见附录4.1.7
*/
private String drawerCreditRating;
/**
* 出票人评级到期日 格式为yyyy-mm-dd
*/
private Date drawerRateDueDate;
/**
* 承兑人评级主体
*/
private String acceptorRateSubject;
/**
* 承兑人信用等级 信用等级枚举见附录4.1.7
*/
private String acceptorCreditRating;
/**
* 承兑人评级到期日 格式为yyyy-mm-dd
*/
private Date acceptorRateDueDate;
/**
* 持票人名称
*/
private String holdName;
/**
* 持票人单位名称
*/
private String holdOrganizationName;
/**
* 持票人单位编码
*/
private String displayHoldOrganizationCode;
/**
* 持票人账户名称
*/
private String holdAccountName;
/**
* 持票人银行类型 见附录4.1.1.银行类型枚举
*/
private String holdBankType;
/**
* 持票人账号
*/
private String holdAccount;
/**
* 持票人开户行名称
*/
private String holdBrnName;
/**
* 持票人联行号
*/
private String holdInterbankNbr;
/**
* 前手名称
*/
private String preName;
/**
* 前手是否内部企业 1-0-
*/
private String preInternalFlag;
/**
* 前手单位名称
*/
private String preOrganizationName;
/**
* 前手单位编码
*/
private String displayPreOrganizationCode;
/**
* 前手是否客商企业 1-0-
*/
private String preCustomerFlag;
/**
* 前手客商名称
*/
private String preCustomerName;
/**
* 前手客商编号 填在cbs系统公共设置>基础信息>客商管理>客商信息管理维护的客商编号
*/
private String preCustomerNbr;
/**
* 前手账户名称
*/
private String preAccountName;
/**
* 前手账号
*/
private String preAccount;
/**
* 前手开户行名称
*/
private String preBrnName;
/**
* 前手联行号
*/
private String preInterbankNbr;
/**
* 后手名称
*/
private String nextName;
/**
* 后手是否内部企业 1-0-
*/
private String nextInternalFlag;
/**
* 后手单位名称
*/
private String nextOrganizationName;
/**
* 后手单位编码
*/
private String displayNextOrganizationCode;
/**
* 后手是否客商企业 1-0-
*/
private String nextCustomerFlag;
/**
* 后手客商名称
*/
private String nextCustomerName;
/**
* 后手客商编号 填在cbs系统公共设置>基础信息>客商管理>客商信息管理维护的客商编号
*/
private String nextCustomerNbr;
/**
* 后手账户名称
*/
private String nextAccountName;
/**
* 后手账号
*/
private String nextAccount;
/**
* 后手开户行名称
*/
private String nextBrnName;
/**
* 后手联行号
*/
private String nextInterbankNbr;
/**
* 签收方式 1-收票签收2-背书签收
*/
private String signMethod;
/**
* 同步状态
* INIT-未同步
* ING-同步中
* SUC-同步完成
* FAL-同步失败
*/
private String asyncStatus;
}
}

View File

@ -0,0 +1,20 @@
package com.engine.salary.remote.cbs8.response;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
public class GetTokenResponse extends CBS8BaseResponse {
/**
* 返回数据
*/
private Body data;
@Data
public static class Body {
private Integer expires;
private String token;
private String token_type;
}
}

View File

@ -0,0 +1,268 @@
package com.engine.salary.remote.cbs8.response;
import com.alibaba.fastjson.JSON;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
@Data
@EqualsAndHashCode(callSuper = true)
public class GetTransactionDetailResponse extends CBS8BaseResponse {
/**
* 返回数据
*/
private Body data;
@Data
@EqualsAndHashCode(callSuper = true)
public static class Body extends CBS8PageInfo{
/**
* 明细列表
*/
private List<Detail> list;
}
@Data
public static class Detail {
/**
* 银行账号
*/
private String accountNo;
/**
* 账户名称
*/
private String accountName;
/**
* 银行类型 银行类型见附录4.1.5
*/
private String bankType;
/**
* 开户行名称
*/
private String openBank;
/**
* 交易日期 时间戳
*/
private Date bankTransactionDate;
/**
* 银行流水号
*/
private String bankSerialNumber;
/**
* 交易流水号
*/
private Long transactionSerialNumber;
/**
* 币种 币种枚举见附录4.1.1
*/
private String currency;
/**
* 借贷类型 1-2-
*/
private String loanType;
/**
* 发生额
*/
private BigDecimal incurredAmount;
/**
* 交易后余额
*/
private BigDecimal accountBalance;
/**
* 用途
*/
private String purpose;
/**
* 摘要
*/
private String digest;
/**
* 对方账号
*/
private String oppositeAccount;
/**
* 对方户名
*/
private String oppositeName;
/**
* 对方开户行
*/
private String oppositeOpeningBank;
/**
* 关联客户号
*/
private String associatedCustomerNumber;
/**
* 客商编号 客户在公共设置>基础信息>客商管理登记的客商编码例如C002-XX供应链管理此处返回C002
*/
private String merchantNumber;
/**
* 客商名称 客户在公共设置>基础信息>客商管理登记的客商名称例如C002-XX供应链管理此处返回XX供应链管理
*/
private String merchantName;
/**
* 起息日 时间戳
*/
private Date valueDate;
/**
* 交易代码 见附录枚举4.1.8
*/
private String transactionCode;
/**
* 款项性质匹配标记 1-未匹配2-手工处理3-系统处理4-匹配失败
*/
private String paymentNatureFlag;
/**
* 款项性质代码 客户在公共设置>基础信息>款项性质查询登记的款项性质例如A001-往来款此处返回A001
*/
private String paymentNature;
/**
* 明细来源 B银行即银行直联 U用户即手工/ERP接口导入
*/
private String detailSource;
/**
* 明细类型 1-当日明细 2-历史明细 与明细日期无关仅标识数据来源银行的不同接口
*/
private String detailType;
/**
* 账户状态 0-正常1-销户
*/
private String accountStatus;
/**
* 账户性质 客户在公共设置>基础信息>账户性质查询自定义内容例如AA-综合户此处返回值AA
*/
private String accountNature;
/**
* 对账码 对账码是CBS8系统通过一定规则匹配交易明细与回单或交易明细与支付成功后生成的对账码
*/
private String checkCode;
/**
* 单位编码 客户在公共设置>基础信息>组织机构维护例如0001-XX科技有限公司此处返回0001
*/
private String unitCode;
/**
* 单位名称
*/
private String unitName;
/**
* 备注
*/
private String remark;
/**
* ERP业务参考号 此字段为支付接口的referenceNum业务参考号
*/
private String erpSerialNumber;
/**
* 支付申请备注1
*/
private String PayApplyRemark1;
/**
* 支付申请备注2
*/
private String PayApplyRemark2;
/**
* 支付申请备注3
*/
private String PayApplyRemark3;
/**
* 交易识别码
*/
private String corporateIdentityCode;
/**
* 预留字段1
*/
private String reserveField1;
/**
* 预留字段2
*/
private String reserveField2;
/**
* 预留字段3
*/
private String reserveField3;
/**
* 预留字段4
*/
private String reserveField4;
/**
* 扩展字段信息 fieldKey字段KEY title : 标题 content : 字段内容
*/
private List<JSON> extensionMsg;
/**
* 附言
*/
private String postscript;
/**
* 凭证编号
*/
private String voucherCode;
/**
* 记账日期
*/
private Date bookingDate;
/**
* 银行个性化字段1 银行个性化字段见附录4.1.20
*/
private String personalizeField1;
/**
* 银行个性化字段2 银行个性化字段见附录4.1.20
*/
private String personalizeField2;
/**
* 银行个性化字段3 银行个性化字段见附录4.1.20
*/
private String personalizeField3;
/**
* 银行个性化字段4 银行个性化字段见附录4.1.20
*/
private String personalizeField4;
/**
* 银行个性化字段5 银行个性化字段见附录4.1.20
*/
private String personalizeField5;
/**
* 虚拟户账号
*/
private String virtualAccount;
/**
* 虚拟户账号名称
*/
private String virtualAccountName;
/**
* 交易类型
*/
private String protocolType;
/**
* 交易类型名称
*/
private String protocolTypeName;
/**
* /子公司账号
*/
private String parentSubCompanyAccount;
/**
* /子公司名称母/子公司名称
*/
private String parentSubCompanyName;
/**
* 通过9091->公共设置->业务配置->
* 通用参数管理->账户管理->erp_trans_detail_mark_return_flag(交易明细查询ERP接口是否返回关联业务表字段)设置可开启字段返回参数关闭时字段为null
* id:关联业务id
* bizCode:关联业务(见附录4.1.22)
* bizFlag:关联业务标记
* (0-手工标记
* 1-按规则标记
* 2-模块关联标记
* 3-ERP接口标记)
* moduleCode:关联模块
* menuName:关联菜单
* bizOrderNo:业务编号
*/
private List<JSON> markingList;
}
}

View File

@ -0,0 +1,215 @@
package com.engine.salary.remote.cbs8.util;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.asn1.*;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.*;
import org.bouncycastle.crypto.signers.SM2Signer;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.encoders.Hex;
import java.io.ByteArrayInputStream;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Enumeration;
/**
* @author: KeXue
* @time: 2022/8/25
* @description: SM2加解密工具类
*/
@Slf4j
public class SM2Util {
private SM2Util() {
throw new IllegalStateException("Utility class");
}
private static final String STD_NAME = "sm2p256v1";
/**
* SM2加密算法
*
* @param publicKey 公钥
* @param data 明文数据
* @return
*/
public static byte[] encrypt(String publicKey, byte[] data) {
ECPublicKeyParameters ecPublicKeyParameters = encodePublicKey(Hex.decode(publicKey));
SM2Engine engine = new SM2Engine();
engine.init(true, new ParametersWithRandom(ecPublicKeyParameters, new SecureRandom()));
byte[] bytes = null;
try {
byte[] cipherText = engine.processBlock(data, 0, data.length);
bytes = C1C2C3ToC1C3C2(cipherText);
} catch (Exception e) {
log.warn("SM2加密时出现异常:" + e.getMessage());
}
return bytes;
}
/**
* SM2解密算法
*
* @param privateKey 私钥
* @param cipherData 密文数据
* @return
*/
public static byte[] decrypt(String privateKey, byte[] cipherData) {
ECPrivateKeyParameters ecPrivateKeyParameters = encodePrivateKey(Hex.decode(privateKey));
SM2Engine engine = new SM2Engine();
engine.init(false, ecPrivateKeyParameters);
byte[] bytes = null;
try {
cipherData = C1C3C2ToC1C2C3(cipherData);
bytes = engine.processBlock(cipherData, 0, cipherData.length);
} catch (Exception e) {
log.warn("SM2解密时出现异常:" + e.getMessage());
}
return bytes;
}
/**
* 签名算法
*
* @param privateKey 私钥
* @param data 明文数据
* @return
*/
public static byte[] sign(String privateKey, byte[] data) {
ECPrivateKeyParameters ecPrivateKeyParameters = encodePrivateKey(hexToByte(privateKey));
SM2Signer signer = new SM2Signer();
ParametersWithID parameters = new ParametersWithID(ecPrivateKeyParameters, "1234567812345678".getBytes());
signer.init(true, parameters);
signer.update(data, 0, data.length);
byte[] signature = null;
try {
signature = decodeDERSignature(signer.generateSignature());
} catch (Exception e) {
log.warn("SM2签名时出现异常:" + e.getMessage());
}
return signature;
}
private static byte[] hexToByte(String hex)
throws IllegalArgumentException {
if (hex.length() % 2 != 0) {
throw new IllegalArgumentException();
}
char[] arr = hex.toCharArray();
byte[] b = new byte[hex.length() / 2];
for (int i = 0, j = 0, l = hex.length(); i < l; i++, j++) {
String swap = "" + arr[i++] + arr[i];
int byteInt = Integer.parseInt(swap, 16) & 0xFF;
b[j] = BigInteger.valueOf(byteInt).byteValue();
}
return b;
}
private static byte[] C1C2C3ToC1C3C2(byte[] cipherText) throws Exception {
if (cipherText != null && cipherText.length >= 97) {
byte[] bytes = new byte[cipherText.length];
System.arraycopy(cipherText, 0, bytes, 0, 65);
System.arraycopy(cipherText, cipherText.length - 32, bytes, 65, 32);
System.arraycopy(cipherText, 65, bytes, 97, cipherText.length - 97);
return bytes;
} else {
throw new Exception("SM2 cipher text error, must be more than 96 bytes and in the format C1||C3||C2.");
}
}
private static byte[] C1C3C2ToC1C2C3(byte[] cipherText) throws Exception {
if (cipherText != null && cipherText.length >= 97) {
byte[] bytes = new byte[cipherText.length];
System.arraycopy(cipherText, 0, bytes, 0, 65);
System.arraycopy(cipherText, 97, bytes, 65, cipherText.length - 97);
System.arraycopy(cipherText, 65, bytes, cipherText.length - 32, 32);
return bytes;
} else {
throw new Exception("SM2 cipher text error, must be more than 96 bytes and in the format C1||C3||C2.");
}
}
private static ECPublicKeyParameters encodePublicKey(byte[] value) {
byte[] x = new byte[32];
byte[] y = new byte[32];
System.arraycopy(value, 1, x, 0, 32);
System.arraycopy(value, 33, y, 0, 32);
BigInteger X = new BigInteger(1, x);
BigInteger Y = new BigInteger(1, y);
ECPoint Q = getSM2Curve().createPoint(X, Y);
return new ECPublicKeyParameters(Q, getECDomainParameters());
}
private static ECCurve getSM2Curve() {
ECParameterSpec spec = ECNamedCurveTable.getParameterSpec(STD_NAME);
return spec.getCurve();
}
private static ECPrivateKeyParameters encodePrivateKey(byte[] value) {
BigInteger d = new BigInteger(1, value);
return new ECPrivateKeyParameters(d, getECDomainParameters());
}
private static ECDomainParameters getECDomainParameters() {
ECParameterSpec spec = ECNamedCurveTable.getParameterSpec(STD_NAME);
return new ECDomainParameters(spec.getCurve(), spec.getG(), spec.getN(), spec.getH(), spec.getSeed());
}
private static byte[] decodeDERSignature(byte[] signature) {
ASN1InputStream stream = new ASN1InputStream(new ByteArrayInputStream(signature));
byte[] bytes = new byte[64];
try {
ASN1Sequence primitive = (ASN1Sequence) stream.readObject();
Enumeration enumeration = primitive.getObjects();
BigInteger R = ((ASN1Integer) enumeration.nextElement()).getValue();
BigInteger S = ((ASN1Integer) enumeration.nextElement()).getValue();
byte[] r = format(R.toByteArray());
byte[] s = format(S.toByteArray());
System.arraycopy(r, 0, bytes, 0, 32);
System.arraycopy(s, 0, bytes, 32, 32);
} catch (Exception e) {
log.warn("decodeDERSignature时出现异常:" + e.getMessage());
}
return bytes;
}
public static byte[] encodeDERSignature(byte[] signature) {
byte[] r = new byte[32];
byte[] s = new byte[32];
System.arraycopy(signature, 0, r, 0, 32);
System.arraycopy(signature, 32, s, 0, 32);
ASN1EncodableVector vector = new ASN1EncodableVector();
vector.add(new ASN1Integer(new BigInteger(1, r)));
vector.add(new ASN1Integer(new BigInteger(1, s)));
byte[] encoded = null;
try {
encoded = (new DERSequence(vector)).getEncoded();
} catch (Exception e) {
log.warn("encodeDERSignature时出现异常:" + e.getMessage());
}
return encoded;
}
private static byte[] format(byte[] value) {
if (value.length == 32) {
return value;
} else {
byte[] bytes = new byte[32];
if (value.length > 32) {
System.arraycopy(value, value.length - 32, bytes, 0, 32);
} else {
System.arraycopy(value, 0, bytes, 32 - value.length, value.length);
}
return bytes;
}
}
}

View File

@ -3,6 +3,7 @@ package com.engine.salary.service;
import com.engine.salary.entity.datacollection.dto.*;
import com.engine.salary.entity.datacollection.param.*;
import com.engine.salary.entity.datacollection.po.*;
import com.engine.salary.enums.datacollection.TaxFreeTypeEnum;
import com.engine.salary.util.page.PageInfo;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
@ -125,35 +126,75 @@ public interface OtherDeductionService {
String extendToLastMonth(OtherDeductionExtendLastParam param);
PageInfo<FreeIncomeListDTO> freeIncomeList(OtherDeductionDetailQueryParam param);
PageInfo<DerateDeductionListDTO> derateDeductionList(OtherDeductionDetailQueryParam param);
PageInfo<EndowmentInsuranceListDTO> endowmentInsuranceList(OtherDeductionDetailQueryParam param);
PageInfo<GrantDonationListDTO> grantDonationList(OtherDeductionDetailQueryParam param);
PageInfo<HealthInsuranceListDTO> healthInsuranceList(OtherDeductionDetailQueryParam param);
PageInfo<OtherDerateDeductionListDTO> otherDerateDeductionList(OtherDeductionDetailQueryParam param);
PageInfo<PersonalPensionListDTO> personalPensionList(OtherDeductionDetailQueryParam param);
List<FreeIncomePO> queryFreeIncomes(OtherDeductionFreeListQueryParam param);
List<DerateDeductionPO> queryDerateDeductions(OtherDeductionFreeListQueryParam param);
List<EndowmentInsurancePO> queryEndowmentInsurances(OtherDeductionFreeListQueryParam param);
List<GrantDonationPO> queryGrantDonations(OtherDeductionFreeListQueryParam param);
List<HealthInsurancePO> queryHealthInsurances(OtherDeductionFreeListQueryParam param);
List<OtherDerateDeductionPO> queryOtherDerateDeductions(OtherDeductionFreeListQueryParam param);
List<PersonalPensionPO> queryPersonalPensions(OtherDeductionFreeListQueryParam param);
void saveFreeIncome(FreeIncomeSaveParam param);
void saveEndowmentInsurance(EndowmentInsuranceSaveParam param);
void saveGrantDonation(GrantDonationSaveParam param);
void saveHealthInsurance(HealthInsuranceSaveParam param);
void saveOtherDerateDeduction(OtherDerateDeductionSaveParam param);
void saveDerateDeduction(DerateDeductionSaveParam param);
void savePersonalPension(PersonalPensionSaveParam param);
void deleteFreeIncome(OtherDeductionDetailDeleteParam param);
void deleteEndowmentInsurance(OtherDeductionDetailDeleteParam param);
void deleteGrantDonation(OtherDeductionDetailDeleteParam param);
void deleteHealthInsurance(OtherDeductionDetailDeleteParam param);
void deleteOtherDerateDeduction(OtherDeductionDetailDeleteParam param);
void deleteDerateDeduction(OtherDeductionDetailDeleteParam param);
void deletePersonalPension(OtherDeductionDetailDeleteParam param);
void syncMain(Long mainId, List<TaxFreeTypeEnum> taxFreeTypes);
void syncFreeIncome(OtherDeductionPO mainPO);
void syncEndowmentInsurance(OtherDeductionPO mainPO);
void syncGrantDonation(OtherDeductionPO mainPO);
void syncHealthInsurance(OtherDeductionPO mainPO);
void syncOtherDerateDeduction(OtherDeductionPO mainPO);
void syncDerateDeduction(OtherDeductionPO mainPO);
void syncPersonalPension(OtherDeductionPO mainPO);
}

View File

@ -21,6 +21,7 @@ import com.engine.salary.entity.taxagent.po.TaxAgentPO;
import com.engine.salary.enums.OperateTypeEnum;
import com.engine.salary.enums.UserStatusEnum;
import com.engine.salary.enums.datacollection.DataCollectionEmployeeTypeEnum;
import com.engine.salary.enums.datacollection.TaxFreeTypeEnum;
import com.engine.salary.enums.sicategory.DeleteTypeEnum;
import com.engine.salary.exception.SalaryRunTimeException;
import com.engine.salary.mapper.datacollection.*;
@ -53,6 +54,7 @@ import org.apache.commons.lang3.Validate;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import weaver.file.ImageFileManager;
import weaver.general.Util;
@ -1559,6 +1561,14 @@ public class OtherDeductionServiceImpl extends Service implements OtherDeduction
l.setMainId(po.getId());
getPersonalPensionMapper().insertIgnoreNull(l);
});
syncMain(po.getId(), Arrays.asList(TaxFreeTypeEnum.FREE_INCOME,
TaxFreeTypeEnum.HEALTH_INSURANCE,
TaxFreeTypeEnum.ENDOWMENT_INSURANCE,
TaxFreeTypeEnum.GRANT_DONATION,
TaxFreeTypeEnum.DERATE_DEDUCTION,
TaxFreeTypeEnum.OTHER_DERATE_DEDUCTION,
TaxFreeTypeEnum.PERSONAL_PENSION));
});
return apidatas;
@ -2221,23 +2231,183 @@ public class OtherDeductionServiceImpl extends Service implements OtherDeduction
public XSSFWorkbook downloadDetailTemplate(OtherDeductionQueryParam param) {
List<FreeIncomeListDTO> freeIncomeList = new ArrayList<>();
List<HealthInsuranceListDTO> healthInsuranceList = new ArrayList<>();
List<EndowmentInsuranceListDTO> endowmentInsuranceList = new ArrayList<>();
List<GrantDonationListDTO> grantDonationList = new ArrayList<>();
List<DerateDeductionListDTO> derateDeductionList = new ArrayList<>();
List<OtherDerateDeductionListDTO> otherDerateDeductionList = new ArrayList<>();
List<PersonalPensionListDTO> personalPensionList = new ArrayList<>();
if (param.isHasData()) {
long employeeId = user.getUID();
//排序配置
OrderRuleVO orderRule = getSalarySysConfService(user).orderRule();
param.setOrderRule(orderRule);
List<OtherDeductionListDTO> list = getOtherDeductionMapper().list(param);
encryptUtil.decryptList(list, OtherDeductionListDTO.class);
SalaryI18nUtil.i18nList(list);
// 开启分权并且不是薪酬模块总管理员
if (getTaxAgentService(user).isOpenDevolution() && !getTaxAgentService(user).isChief(employeeId)) {
List<Long> taxAgentIdsAsAdmin = getTaxAgentService(user).listAllTaxAgentsAsAdmin(employeeId).stream().map(TaxAgentPO::getId).collect(Collectors.toList());
list = list.stream().filter(f ->
// 作为管理员
taxAgentIdsAsAdmin.contains(f.getTaxAgentId())
).collect(Collectors.toList());
}
list.forEach(dto -> {
List<FreeIncomeListDTO> freeIncomeListDTOS = freeIncomePO2DTO(getFreeIncomeMapper().listSome(FreeIncomePO.builder().mainId(dto.getId()).build()));
freeIncomeList.addAll(freeIncomeListDTOS);
List<EndowmentInsuranceListDTO> endowmentInsuranceListDTOS = endowmentInsurancePO2DTO(getEndowmentInsuranceMapper().listSome(EndowmentInsurancePO.builder().mainId(dto.getId()).build()));
endowmentInsuranceList.addAll(endowmentInsuranceListDTOS);
List<GrantDonationListDTO> grantDonationListDTOS = grantDonationPO2DTO(getGrantDonationMapper().listSome(GrantDonationPO.builder().mainId(dto.getId()).build()));
grantDonationList.addAll(grantDonationListDTOS);
List<HealthInsuranceListDTO> healthInsuranceListDTOS = healthInsurancePO2DTO(getHealthInsuranceMapper().listSome(HealthInsurancePO.builder().mainId(dto.getId()).build()));
healthInsuranceList.addAll(healthInsuranceListDTOS);
List<OtherDerateDeductionListDTO> otherDerateDeductionListDTOS = otherDerateDeductionPO2DTO(getOtherDerateDeductionMapper().listSome(OtherDerateDeductionPO.builder().mainId(dto.getId()).build()));
otherDerateDeductionList.addAll(otherDerateDeductionListDTOS);
List<DerateDeductionListDTO> derateDeductionListDTOS = derateDeductionPO2DTO(getDerateDeductionMapper().listSome(DerateDeductionPO.builder().mainId(dto.getId()).build()));
derateDeductionList.addAll(derateDeductionListDTOS);
List<PersonalPensionListDTO> personalPensionListDTOS = personalPensionPO2DTO(getPersonalPensionMapper().listSome(PersonalPensionPO.builder().mainId(dto.getId()).build()));
personalPensionList.addAll(personalPensionListDTOS);
});
}
Map<String, List<List<Object>>> map = new LinkedHashMap<>();
List<List<Object>> freeIncomeRowList = new ArrayList<>();
List<Object> freeIncomeTitle = Arrays.asList("姓名", "个税扣缴义务人", "部门", "手机号", "工号", "证件号码", "免税事项", "免税性质", "免税金额");
map.put("免税收入", Arrays.asList(freeIncomeTitle));
List<Object> healthInsuranceTitle = Arrays.asList("姓名", "个税扣缴义务人", "部门", "手机号", "工号", "证件号码", "税优识别码", "保单生效日期", "年度保费", "月度保费", "本期扣除金额");
map.put("商业健康保险", Arrays.asList(healthInsuranceTitle));
List<Object> endowmentInsuranceTitle = Arrays.asList("姓名", "个税扣缴义务人", "部门", "手机号", "工号", "证件号码", "税延养老账户编号", "报税校验码", "年度保费", "月度保费", "本期扣除金额");
map.put("税延养老保险", Arrays.asList(endowmentInsuranceTitle));
List<Object> grantDonationTitle = Arrays.asList("姓名", "个税扣缴义务人", "部门", "手机号", "工号", "证件号码", "受赠单位名称", "受赠单位纳税人识别号", "凭证号", "捐赠日期", "捐赠金额", "扣除比例", "实际扣除金额");
map.put("准予扣除的捐赠额", Arrays.asList(grantDonationTitle));
List<Object> derateDeductionTitle = Arrays.asList("姓名", "个税扣缴义务人", "部门", "手机号", "工号", "证件号码", "减免事项", "减免性质", "减免金额");
map.put("减免税额", Arrays.asList(derateDeductionTitle));
List<Object> otherDerateDeductionTitle = Arrays.asList("姓名", "个税扣缴义务人", "部门", "手机号", "工号", "证件号码", "其他免税扣除金额", "备注");
map.put("其他", Arrays.asList(otherDerateDeductionTitle));
List<Object> personalPensionTitle = Arrays.asList("姓名", "个税扣缴义务人", "部门", "手机号", "工号", "证件号码", "凭证类型", "凭证编码", "缴费金额");
map.put("个人养老金", Arrays.asList(personalPensionTitle));
freeIncomeRowList.add(freeIncomeTitle);
freeIncomeList.forEach(dto -> {
List<Object> row = new ArrayList<>();
row.add(dto.getUsername());
row.add(dto.getTaxAgentName());
row.add(dto.getDepartmentName());
row.add(dto.getMobile());
row.add(dto.getJobNum());
row.add(dto.getIdNo());
row.add(dto.getFreeItem());
row.add(dto.getFreeProperty());
row.add(dto.getFreeAmount());
freeIncomeRowList.add(row);
});
map.put("免税收入", freeIncomeRowList);
List<List<Object>> healthInsuranceRowList = new ArrayList<>();
List<Object> healthInsuranceTitle = Arrays.asList("姓名", "个税扣缴义务人", "部门", "手机号", "工号", "证件号码", "税优识别码", "保单生效日期", "年度保费", "月度保费", "本期扣除金额");
healthInsuranceRowList.add(healthInsuranceTitle);
healthInsuranceList.forEach(dto -> {
List<Object> row = new ArrayList<>();
row.add(dto.getUsername());
row.add(dto.getTaxAgentName());
row.add(dto.getDepartmentName());
row.add(dto.getMobile());
row.add(dto.getJobNum());
row.add(dto.getIdNo());
row.add(dto.getIdentificationNumber());
row.add(dto.getEffectiveDate());
row.add(dto.getYearPremium());
row.add(dto.getMonthPremium());
row.add(dto.getCurrentDeduction());
healthInsuranceRowList.add(row);
});
map.put("商业健康保险", healthInsuranceRowList);
List<List<Object>> endowmentInsuranceRowList = new ArrayList<>();
List<Object> endowmentInsuranceTitle = Arrays.asList("姓名", "个税扣缴义务人", "部门", "手机号", "工号", "证件号码", "税延养老账户编号", "报税校验码", "年度保费", "月度保费", "本期扣除金额");
endowmentInsuranceRowList.add(endowmentInsuranceTitle);
endowmentInsuranceList.forEach(dto -> {
List<Object> row = new ArrayList<>();
row.add(dto.getUsername());
row.add(dto.getTaxAgentName());
row.add(dto.getDepartmentName());
row.add(dto.getMobile());
row.add(dto.getJobNum());
row.add(dto.getIdNo());
row.add(dto.getAccountNumber());
row.add(dto.getCheckCode());
row.add(dto.getYearPremium());
row.add(dto.getMonthPremium());
row.add(dto.getCurrentDeduction());
endowmentInsuranceRowList.add(row);
});
map.put("税延养老保险", endowmentInsuranceRowList);
List<List<Object>> grantDonationRowList = new ArrayList<>();
List<Object> grantDonationTitle = Arrays.asList("姓名", "个税扣缴义务人", "部门", "手机号", "工号", "证件号码", "受赠单位名称", "受赠单位纳税人识别号", "凭证号", "捐赠日期", "捐赠金额", "扣除比例", "实际扣除金额");
grantDonationRowList.add(grantDonationTitle);
grantDonationList.forEach(dto -> {
List<Object> row = new ArrayList<>();
row.add(dto.getUsername());
row.add(dto.getTaxAgentName());
row.add(dto.getDepartmentName());
row.add(dto.getMobile());
row.add(dto.getJobNum());
row.add(dto.getIdNo());
row.add(dto.getRecipientName());
row.add(dto.getTaxCode());
row.add(dto.getDonationNumber());
row.add(dto.getDonateDate());
row.add(dto.getDonateAmount());
row.add(dto.getDeductionProportion());
row.add(dto.getActualDeduction());
grantDonationRowList.add(row);
});
map.put("准予扣除的捐赠额", grantDonationRowList);
List<List<Object>> derateDeductionRowList = new ArrayList<>();
List<Object> derateDeductionTitle = Arrays.asList("姓名", "个税扣缴义务人", "部门", "手机号", "工号", "证件号码", "减免事项", "减免性质", "减免金额");
derateDeductionRowList.add(derateDeductionTitle);
derateDeductionList.forEach(dto -> {
List<Object> row = new ArrayList<>();
row.add(dto.getUsername());
row.add(dto.getTaxAgentName());
row.add(dto.getDepartmentName());
row.add(dto.getMobile());
row.add(dto.getJobNum());
row.add(dto.getIdNo());
row.add(dto.getDerateItem());
row.add(dto.getDerateProperty());
row.add(dto.getDerateAmount());
derateDeductionRowList.add(row);
});
map.put("减免税额", derateDeductionRowList);
List<List<Object>> otherDerateDeductionRowList = new ArrayList<>();
List<Object> otherDerateDeductionTitle = Arrays.asList("姓名", "个税扣缴义务人", "部门", "手机号", "工号", "证件号码", "其他免税扣除金额", "备注");
otherDerateDeductionRowList.add(otherDerateDeductionTitle);
otherDerateDeductionList.forEach(dto -> {
List<Object> row = new ArrayList<>();
row.add(dto.getUsername());
row.add(dto.getTaxAgentName());
row.add(dto.getDepartmentName());
row.add(dto.getMobile());
row.add(dto.getJobNum());
row.add(dto.getIdNo());
row.add(dto.getOtherDeduction());
row.add(dto.getRemark());
otherDerateDeductionRowList.add(row);
});
map.put("其他", otherDerateDeductionRowList);
List<List<Object>> personalPensionRowList = new ArrayList<>();
List<Object> personalPensionTitle = Arrays.asList("姓名", "个税扣缴义务人", "部门", "手机号", "工号", "证件号码", "凭证类型", "凭证编码", "缴费金额");
personalPensionRowList.add(personalPensionTitle);
personalPensionList.forEach(dto -> {
List<Object> row = new ArrayList<>();
row.add(dto.getUsername());
row.add(dto.getTaxAgentName());
row.add(dto.getDepartmentName());
row.add(dto.getMobile());
row.add(dto.getJobNum());
row.add(dto.getIdNo());
row.add(dto.getVoucherTypeName());
row.add(dto.getVoucherNo());
row.add(dto.getPayAmount());
personalPensionRowList.add(row);
});
map.put("个人养老金", personalPensionRowList);
XSSFWorkbook book = ExcelUtil.genWorkbookV2(map);
return book;
@ -2254,6 +2424,12 @@ public class OtherDeductionServiceImpl extends Service implements OtherDeduction
}
List<FreeIncomePO> pos = getFreeIncomeMapper().listSome(build);
List<FreeIncomeListDTO> listDTOS = freeIncomePO2DTO(pos);
return SalaryPageUtil.buildPage(param.getCurrent(), param.getPageSize(), listDTOS, FreeIncomeListDTO.class);
}
@NotNull
private List<FreeIncomeListDTO> freeIncomePO2DTO(List<FreeIncomePO> pos) {
List<Long> empIds = SalaryEntityUtil.properties(pos, FreeIncomePO::getEmployeeId, Collectors.toList());
List<DataCollectionEmployee> employeeList = getSalaryEmployeeService(user).listByIds(empIds);
Map<Long, DataCollectionEmployee> employeeMap = SalaryEntityUtil.convert2Map(employeeList, DataCollectionEmployee::getEmployeeId);
@ -2272,7 +2448,7 @@ public class OtherDeductionServiceImpl extends Service implements OtherDeduction
dto.setIdNo(employee.getIdNo());
return dto;
}).collect(Collectors.toList());
return SalaryPageUtil.buildPage(param.getCurrent(), param.getPageSize(), listDTOS, FreeIncomeListDTO.class);
return listDTOS;
}
@Override
@ -2285,6 +2461,11 @@ public class OtherDeductionServiceImpl extends Service implements OtherDeduction
}
List<DerateDeductionPO> pos = getDerateDeductionMapper().listSome(build);
List<DerateDeductionListDTO> listDTOS = derateDeductionPO2DTO(pos);
return SalaryPageUtil.buildPage(param.getCurrent(), param.getPageSize(), listDTOS, DerateDeductionListDTO.class);
}
private List<DerateDeductionListDTO> derateDeductionPO2DTO(List<DerateDeductionPO> pos) {
List<Long> empIds = SalaryEntityUtil.properties(pos, DerateDeductionPO::getEmployeeId, Collectors.toList());
List<DataCollectionEmployee> employeeList = getSalaryEmployeeService(user).listByIds(empIds);
Map<Long, DataCollectionEmployee> employeeMap = SalaryEntityUtil.convert2Map(employeeList, DataCollectionEmployee::getEmployeeId);
@ -2303,7 +2484,7 @@ public class OtherDeductionServiceImpl extends Service implements OtherDeduction
dto.setIdNo(employee.getIdNo());
return dto;
}).collect(Collectors.toList());
return SalaryPageUtil.buildPage(param.getCurrent(), param.getPageSize(), listDTOS, DerateDeductionListDTO.class);
return listDTOS;
}
@Override
@ -2316,6 +2497,13 @@ public class OtherDeductionServiceImpl extends Service implements OtherDeduction
}
List<EndowmentInsurancePO> pos = getEndowmentInsuranceMapper().listSome(build);
List<EndowmentInsuranceListDTO> listDTOS = endowmentInsurancePO2DTO(pos);
return SalaryPageUtil.buildPage(param.getCurrent(), param.getPageSize(), listDTOS, EndowmentInsuranceListDTO.class);
}
@NotNull
private List<EndowmentInsuranceListDTO> endowmentInsurancePO2DTO(List<EndowmentInsurancePO> pos) {
List<Long> empIds = SalaryEntityUtil.properties(pos, EndowmentInsurancePO::getEmployeeId, Collectors.toList());
List<DataCollectionEmployee> employeeList = getSalaryEmployeeService(user).listByIds(empIds);
Map<Long, DataCollectionEmployee> employeeMap = SalaryEntityUtil.convert2Map(employeeList, DataCollectionEmployee::getEmployeeId);
@ -2334,7 +2522,7 @@ public class OtherDeductionServiceImpl extends Service implements OtherDeduction
dto.setIdNo(employee.getIdNo());
return dto;
}).collect(Collectors.toList());
return SalaryPageUtil.buildPage(param.getCurrent(), param.getPageSize(), listDTOS, EndowmentInsuranceListDTO.class);
return listDTOS;
}
@Override
@ -2347,6 +2535,12 @@ public class OtherDeductionServiceImpl extends Service implements OtherDeduction
}
List<GrantDonationPO> pos = getGrantDonationMapper().listSome(build);
List<GrantDonationListDTO> listDTOS = grantDonationPO2DTO(pos);
return SalaryPageUtil.buildPage(param.getCurrent(), param.getPageSize(), listDTOS, GrantDonationListDTO.class);
}
@NotNull
private List<GrantDonationListDTO> grantDonationPO2DTO(List<GrantDonationPO> pos) {
List<Long> empIds = SalaryEntityUtil.properties(pos, GrantDonationPO::getEmployeeId, Collectors.toList());
List<DataCollectionEmployee> employeeList = getSalaryEmployeeService(user).listByIds(empIds);
Map<Long, DataCollectionEmployee> employeeMap = SalaryEntityUtil.convert2Map(employeeList, DataCollectionEmployee::getEmployeeId);
@ -2365,7 +2559,7 @@ public class OtherDeductionServiceImpl extends Service implements OtherDeduction
dto.setIdNo(employee.getIdNo());
return dto;
}).collect(Collectors.toList());
return SalaryPageUtil.buildPage(param.getCurrent(), param.getPageSize(), listDTOS, GrantDonationListDTO.class);
return listDTOS;
}
@Override
@ -2378,6 +2572,12 @@ public class OtherDeductionServiceImpl extends Service implements OtherDeduction
}
List<HealthInsurancePO> pos = getHealthInsuranceMapper().listSome(build);
List<HealthInsuranceListDTO> listDTOS = healthInsurancePO2DTO(pos);
return SalaryPageUtil.buildPage(param.getCurrent(), param.getPageSize(), listDTOS, HealthInsuranceListDTO.class);
}
@NotNull
private List<HealthInsuranceListDTO> healthInsurancePO2DTO(List<HealthInsurancePO> pos) {
List<Long> empIds = SalaryEntityUtil.properties(pos, HealthInsurancePO::getEmployeeId, Collectors.toList());
List<DataCollectionEmployee> employeeList = getSalaryEmployeeService(user).listByIds(empIds);
Map<Long, DataCollectionEmployee> employeeMap = SalaryEntityUtil.convert2Map(employeeList, DataCollectionEmployee::getEmployeeId);
@ -2396,7 +2596,7 @@ public class OtherDeductionServiceImpl extends Service implements OtherDeduction
dto.setIdNo(employee.getIdNo());
return dto;
}).collect(Collectors.toList());
return SalaryPageUtil.buildPage(param.getCurrent(), param.getPageSize(), listDTOS, HealthInsuranceListDTO.class);
return listDTOS;
}
@Override
@ -2409,6 +2609,12 @@ public class OtherDeductionServiceImpl extends Service implements OtherDeduction
}
List<OtherDerateDeductionPO> pos = getOtherDerateDeductionMapper().listSome(build);
List<OtherDerateDeductionListDTO> listDTOS = otherDerateDeductionPO2DTO(pos);
return SalaryPageUtil.buildPage(param.getCurrent(), param.getPageSize(), listDTOS, OtherDerateDeductionListDTO.class);
}
@NotNull
private List<OtherDerateDeductionListDTO> otherDerateDeductionPO2DTO(List<OtherDerateDeductionPO> pos) {
List<Long> empIds = SalaryEntityUtil.properties(pos, OtherDerateDeductionPO::getEmployeeId, Collectors.toList());
List<DataCollectionEmployee> employeeList = getSalaryEmployeeService(user).listByIds(empIds);
Map<Long, DataCollectionEmployee> employeeMap = SalaryEntityUtil.convert2Map(employeeList, DataCollectionEmployee::getEmployeeId);
@ -2427,7 +2633,7 @@ public class OtherDeductionServiceImpl extends Service implements OtherDeduction
dto.setIdNo(employee.getIdNo());
return dto;
}).collect(Collectors.toList());
return SalaryPageUtil.buildPage(param.getCurrent(), param.getPageSize(), listDTOS, OtherDerateDeductionListDTO.class);
return listDTOS;
}
@Override
@ -2440,6 +2646,12 @@ public class OtherDeductionServiceImpl extends Service implements OtherDeduction
}
List<PersonalPensionPO> pos = getPersonalPensionMapper().listSome(build);
List<PersonalPensionListDTO> listDTOS = personalPensionPO2DTO(pos);
return SalaryPageUtil.buildPage(param.getCurrent(), param.getPageSize(), listDTOS, PersonalPensionListDTO.class);
}
@NotNull
private List<PersonalPensionListDTO> personalPensionPO2DTO(List<PersonalPensionPO> pos) {
List<Long> empIds = SalaryEntityUtil.properties(pos, PersonalPensionPO::getEmployeeId, Collectors.toList());
List<DataCollectionEmployee> employeeList = getSalaryEmployeeService(user).listByIds(empIds);
Map<Long, DataCollectionEmployee> employeeMap = SalaryEntityUtil.convert2Map(employeeList, DataCollectionEmployee::getEmployeeId);
@ -2458,7 +2670,7 @@ public class OtherDeductionServiceImpl extends Service implements OtherDeduction
dto.setIdNo(employee.getIdNo());
return dto;
}).collect(Collectors.toList());
return SalaryPageUtil.buildPage(param.getCurrent(), param.getPageSize(), listDTOS, PersonalPensionListDTO.class);
return listDTOS;
}
@Override
@ -2547,6 +2759,8 @@ public class OtherDeductionServiceImpl extends Service implements OtherDeduction
getFreeIncomeMapper().updateIgnoreNull(po);
}
syncMain(mainId, Collections.singletonList(TaxFreeTypeEnum.FREE_INCOME));
}
@Override
@ -2598,6 +2812,8 @@ public class OtherDeductionServiceImpl extends Service implements OtherDeduction
getEndowmentInsuranceMapper().updateIgnoreNull(po);
}
syncMain(mainId, Collections.singletonList(TaxFreeTypeEnum.ENDOWMENT_INSURANCE));
}
@Override
@ -2651,6 +2867,8 @@ public class OtherDeductionServiceImpl extends Service implements OtherDeduction
getGrantDonationMapper().updateIgnoreNull(po);
}
syncMain(mainId, Collections.singletonList(TaxFreeTypeEnum.GRANT_DONATION));
}
@Override
@ -2700,6 +2918,8 @@ public class OtherDeductionServiceImpl extends Service implements OtherDeduction
getHealthInsuranceMapper().updateIgnoreNull(po);
}
syncMain(mainId, Collections.singletonList(TaxFreeTypeEnum.HEALTH_INSURANCE));
}
@Override
@ -2743,6 +2963,8 @@ public class OtherDeductionServiceImpl extends Service implements OtherDeduction
getOtherDerateDeductionMapper().updateIgnoreNull(po);
}
syncMain(mainId, Collections.singletonList(TaxFreeTypeEnum.OTHER_DERATE_DEDUCTION));
}
@Override
@ -2788,6 +3010,8 @@ public class OtherDeductionServiceImpl extends Service implements OtherDeduction
getDerateDeductionMapper().updateIgnoreNull(po);
}
syncMain(mainId, Collections.singletonList(TaxFreeTypeEnum.DERATE_DEDUCTION));
}
@Override
@ -2833,41 +3057,136 @@ public class OtherDeductionServiceImpl extends Service implements OtherDeduction
getPersonalPensionMapper().updateIgnoreNull(po);
}
syncMain(mainId, Collections.singletonList(TaxFreeTypeEnum.PERSONAL_PENSION));
}
@Override
public void deleteFreeIncome(OtherDeductionDetailDeleteParam param) {
getFreeIncomeMapper().deleteByIds(param.getIds());
syncMain(param.getMainId(), Collections.singletonList(TaxFreeTypeEnum.FREE_INCOME));
}
@Override
public void deleteEndowmentInsurance(OtherDeductionDetailDeleteParam param) {
getEndowmentInsuranceMapper().deleteByIds(param.getIds());
syncMain(param.getMainId(), Collections.singletonList(TaxFreeTypeEnum.ENDOWMENT_INSURANCE));
}
@Override
public void deleteGrantDonation(OtherDeductionDetailDeleteParam param) {
getGrantDonationMapper().deleteByIds(param.getIds());
syncMain(param.getMainId(), Collections.singletonList(TaxFreeTypeEnum.GRANT_DONATION));
}
@Override
public void deleteHealthInsurance(OtherDeductionDetailDeleteParam param) {
getHealthInsuranceMapper().deleteByIds(param.getIds());
syncMain(param.getMainId(), Collections.singletonList(TaxFreeTypeEnum.HEALTH_INSURANCE));
}
@Override
public void deleteOtherDerateDeduction(OtherDeductionDetailDeleteParam param) {
getOtherDerateDeductionMapper().deleteByIds(param.getIds());
syncMain(param.getMainId(), Collections.singletonList(TaxFreeTypeEnum.OTHER_DERATE_DEDUCTION));
}
@Override
public void deleteDerateDeduction(OtherDeductionDetailDeleteParam param) {
getDerateDeductionMapper().deleteByIds(param.getIds());
syncMain(param.getMainId(), Collections.singletonList(TaxFreeTypeEnum.DERATE_DEDUCTION));
}
@Override
public void deletePersonalPension(OtherDeductionDetailDeleteParam param) {
getPersonalPensionMapper().deleteByIds(param.getIds());
syncMain(param.getMainId(), Collections.singletonList(TaxFreeTypeEnum.PERSONAL_PENSION));
}
@Override
public void syncMain(Long mainId, List<TaxFreeTypeEnum> taxFreeTypes) {
OtherDeductionPO deductionPO = getById(mainId);
if (deductionPO == null) {
throw new SalaryRunTimeException("主表不存在!");
}
if (taxFreeTypes.contains(TaxFreeTypeEnum.FREE_INCOME)) {
syncFreeIncome(deductionPO);
}
if (taxFreeTypes.contains(TaxFreeTypeEnum.HEALTH_INSURANCE)) {
syncHealthInsurance(deductionPO);
}
if (taxFreeTypes.contains(TaxFreeTypeEnum.ENDOWMENT_INSURANCE)) {
syncEndowmentInsurance(deductionPO);
}
if (taxFreeTypes.contains(TaxFreeTypeEnum.GRANT_DONATION)) {
syncGrantDonation(deductionPO);
}
if (taxFreeTypes.contains(TaxFreeTypeEnum.DERATE_DEDUCTION)) {
syncDerateDeduction(deductionPO);
}
if (taxFreeTypes.contains(TaxFreeTypeEnum.OTHER_DERATE_DEDUCTION)) {
syncOtherDerateDeduction(deductionPO);
}
if (taxFreeTypes.contains(TaxFreeTypeEnum.PERSONAL_PENSION)) {
syncPersonalPension(deductionPO);
}
}
@Override
public void syncFreeIncome(OtherDeductionPO mainPO) {
List<FreeIncomePO> freeIncomePOS = getFreeIncomeMapper().listSome(FreeIncomePO.builder().mainId(mainPO.getId()).build());
String sum = freeIncomePOS.stream().filter(po -> NumberUtil.isNumber(po.getFreeAmount())).map(po -> new BigDecimal(po.getFreeAmount())).reduce(BigDecimal.ZERO, BigDecimal::add).toPlainString();
mainPO.setFreeIncome(sum);
getOtherDeductionMapper().updateData(Collections.singletonList(mainPO));
}
@Override
public void syncEndowmentInsurance(OtherDeductionPO mainPO) {
List<EndowmentInsurancePO> endowmentInsurancePOS = getEndowmentInsuranceMapper().listSome(EndowmentInsurancePO.builder().mainId(mainPO.getId()).build());
String sum = endowmentInsurancePOS.stream().filter(po -> NumberUtil.isNumber(po.getCurrentDeduction())).map(po -> new BigDecimal(po.getCurrentDeduction())).reduce(BigDecimal.ZERO, BigDecimal::add).toPlainString();
mainPO.setTaxDelayEndowmentInsurance(sum);
getOtherDeductionMapper().updateData(Collections.singletonList(mainPO));
}
@Override
public void syncGrantDonation(OtherDeductionPO mainPO) {
List<GrantDonationPO> grantDonationPOS = getGrantDonationMapper().listSome(GrantDonationPO.builder().mainId(mainPO.getId()).build());
String sum = grantDonationPOS.stream().filter(po -> NumberUtil.isNumber(po.getActualDeduction())).map(po -> new BigDecimal(po.getActualDeduction())).reduce(BigDecimal.ZERO, BigDecimal::add).toPlainString();
mainPO.setDeductionAllowedDonation(sum);
getOtherDeductionMapper().updateData(Collections.singletonList(mainPO));
}
@Override
public void syncHealthInsurance(OtherDeductionPO mainPO) {
List<HealthInsurancePO> healthInsurancePOS = getHealthInsuranceMapper().listSome(HealthInsurancePO.builder().mainId(mainPO.getId()).build());
String sum = healthInsurancePOS.stream().filter(po -> NumberUtil.isNumber(po.getCurrentDeduction())).map(po -> new BigDecimal(po.getCurrentDeduction())).reduce(BigDecimal.ZERO, BigDecimal::add).toPlainString();
mainPO.setBusinessHealthyInsurance(sum);
getOtherDeductionMapper().updateData(Collections.singletonList(mainPO));
}
@Override
public void syncOtherDerateDeduction(OtherDeductionPO mainPO) {
List<OtherDerateDeductionPO> otherDerateDeductionPOS = getOtherDerateDeductionMapper().listSome(OtherDerateDeductionPO.builder().mainId(mainPO.getId()).build());
String sum = otherDerateDeductionPOS.stream().filter(po -> NumberUtil.isNumber(po.getOtherDeduction())).map(po -> new BigDecimal(po.getOtherDeduction())).reduce(BigDecimal.ZERO, BigDecimal::add).toPlainString();
mainPO.setOtherDeduction(sum);
getOtherDeductionMapper().updateData(Collections.singletonList(mainPO));
}
@Override
public void syncDerateDeduction(OtherDeductionPO mainPO) {
List<DerateDeductionPO> derateDeductionPOS = getDerateDeductionMapper().listSome(DerateDeductionPO.builder().mainId(mainPO.getId()).build());
String sum = derateDeductionPOS.stream().filter(po -> NumberUtil.isNumber(po.getDerateAmount())).map(po -> new BigDecimal(po.getDerateAmount())).reduce(BigDecimal.ZERO, BigDecimal::add).toPlainString();
mainPO.setDerateDeduction(sum);
getOtherDeductionMapper().updateData(Collections.singletonList(mainPO));
}
@Override
public void syncPersonalPension(OtherDeductionPO mainPO) {
List<PersonalPensionPO> personalPensionPOS = getPersonalPensionMapper().listSome(PersonalPensionPO.builder().mainId(mainPO.getId()).build());
String sum = personalPensionPOS.stream().filter(po -> NumberUtil.isNumber(po.getPayAmount())).map(po -> new BigDecimal(po.getPayAmount())).reduce(BigDecimal.ZERO, BigDecimal::add).toPlainString();
mainPO.setPrivatePension(sum);
getOtherDeductionMapper().updateData(Collections.singletonList(mainPO));
}
}

View File

@ -5089,7 +5089,7 @@ public class SIAccountServiceImpl extends Service implements SIAccountService {
// Map<Long, InsuranceArchivesAccountPO> insuranceArchivesAccountPOS = siArchivesBiz.buildBatchAccount(ids, paymentOrganization);
Map<Long, InsuranceArchivesAccountPO> insuranceArchivesAccountPOS = getSIArchivesService(user).buildBatchAccount(ids, paymentOrganization);
List<InsuranceAccountDetailPO> historyDetailData = new ArrayList<>();
List<DataCollectionEmployee> employeeList = new ArrayList<>();
List<DataCollectionEmployee> employeeList = getSalaryEmployeeService(user).listByIds(ids);
if (!isFirstFlag) {
// 不是首次核算需要把社保历史数据取出
List<List<Long>> partition = Lists.partition(ids, 100);
@ -5097,8 +5097,6 @@ public class SIAccountServiceImpl extends Service implements SIAccountService {
historyDetailData.addAll(getInsuranceAccountDetailMapper().list(InsuranceAccountDetailParam.builder().billMonth(billMonth).paymentOrganization(paymentOrganization.toString()).employeeIds(part).build()));
historyDetailData.addAll(getInsuranceAccountDetailMapper().extList(InsuranceAccountDetailParam.builder().billMonth(billMonth).paymentOrganization(paymentOrganization.toString()).employeeIds(part).build()));
});
} else {
employeeList = getSalaryEmployeeService(user).listByIds(ids);
}
Map<Long, InsuranceAccountDetailPO> historyDetailDataMap = SalaryEntityUtil.convert2Map(historyDetailData, InsuranceAccountDetailPO::getEmployeeId);
Map<Long, DataCollectionEmployee> employeeMap = SalaryEntityUtil.convert2Map(employeeList, DataCollectionEmployee::getEmployeeId);
@ -5120,7 +5118,9 @@ public class SIAccountServiceImpl extends Service implements SIAccountService {
insuranceAccountDetailPO.setResourceFrom(ResourceFromEnum.SYSTEM.getValue());
insuranceAccountDetailPO.setTenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY);
insuranceAccountDetailPO.setPaymentOrganization(paymentOrganization);
if (isFirstFlag) {
InsuranceAccountDetailPO historyDetail = historyDetailDataMap.get(k);
if (isFirstFlag || historyDetail == null) {
// 初次核算
DataCollectionEmployee employee = employeeMap.get(k);
if (employee != null) {
@ -5135,18 +5135,15 @@ public class SIAccountServiceImpl extends Service implements SIAccountService {
insuranceAccountDetailPO.setStatus(employee.getStatus());
}
} else {
InsuranceAccountDetailPO historyDetail = historyDetailDataMap.get(k);
if (historyDetail != null) {
insuranceAccountDetailPO.setSubcompanyName(historyDetail.getSubcompanyName());
insuranceAccountDetailPO.setSubcompanyId(historyDetail.getSubcompanyId());
insuranceAccountDetailPO.setDepartmentName(historyDetail.getDepartmentName());
insuranceAccountDetailPO.setDepartmentId(historyDetail.getDepartmentId());
insuranceAccountDetailPO.setJobtitleName(historyDetail.getJobtitleName());
insuranceAccountDetailPO.setJobtitleId(historyDetail.getJobtitleId());
insuranceAccountDetailPO.setJobcall(historyDetail.getJobcall());
insuranceAccountDetailPO.setJobcallId(historyDetail.getJobcallId());
insuranceAccountDetailPO.setStatus(historyDetail.getStatus());
}
insuranceAccountDetailPO.setSubcompanyName(historyDetail.getSubcompanyName());
insuranceAccountDetailPO.setSubcompanyId(historyDetail.getSubcompanyId());
insuranceAccountDetailPO.setDepartmentName(historyDetail.getDepartmentName());
insuranceAccountDetailPO.setDepartmentId(historyDetail.getDepartmentId());
insuranceAccountDetailPO.setJobtitleName(historyDetail.getJobtitleName());
insuranceAccountDetailPO.setJobtitleId(historyDetail.getJobtitleId());
insuranceAccountDetailPO.setJobcall(historyDetail.getJobcall());
insuranceAccountDetailPO.setJobcallId(historyDetail.getJobcallId());
insuranceAccountDetailPO.setStatus(historyDetail.getStatus());
}
//核算社保
@ -5176,10 +5173,12 @@ public class SIAccountServiceImpl extends Service implements SIAccountService {
}
//临时表入库前先对可能存在的历史数据进行删除
List<List<Long>> partition = Lists.partition((List<Long>) ids, 100);
partition.forEach(part -> {
getSIAccountDetailTempMapper().batchDelByEmpIdsAndMonthAndPayOrg(part, billMonth, paymentOrganization);
});
// List<List<Long>> partition = Lists.partition((List<Long>) ids, 100);
// partition.forEach(part -> {
// getSIAccountDetailTempMapper().batchDelByEmpIdsAndMonthAndPayOrg(part, billMonth, paymentOrganization);
// });
// 根据人员id删会少删不再参与社保核算的人
getSIAccountDetailTempMapper().batchDelByMonthAndPayOrg(billMonth, paymentOrganization);
//临时表数据入库
if (CollectionUtils.isNotEmpty(list)) {
encryptUtil.encryptList(list, InsuranceAccountDetailTempPO.class);
@ -5730,12 +5729,12 @@ public class SIAccountServiceImpl extends Service implements SIAccountService {
*/
public List<Long> listCanPayEmpIds(Long paymentOrganization, String billMonth) {
List<Long> listCanPayEmpIds = new ArrayList<>();
//社保档案中可进行缴纳的人员
List<Long> socialCanPayEmpIds = getSocialSchemeMapper().listCanPayEmpIds(paymentOrganization, billMonth);
//公积金档案中可进行缴纳的人员
List<Long> fundCanPayEmpIds = getFundSchemeMapper().listCanPayEmpIds(paymentOrganization, billMonth);
//其他福利档案中可进行缴纳的人员
List<Long> otherCanPayEmpIds = getOtherSchemeMapper().listCanPayEmpIds(paymentOrganization, billMonth);
//社保档案中可进行缴纳的人员 未勾选暂不缴纳
List<Long> socialCanPayEmpIds = getSocialSchemeMapper().listCanPayEmpIds(paymentOrganization, billMonth, 0);
//公积金档案中可进行缴纳的人员未勾选暂不缴纳
List<Long> fundCanPayEmpIds = getFundSchemeMapper().listCanPayEmpIds(paymentOrganization, billMonth, 0);
//其他福利档案中可进行缴纳的人员未勾选暂不缴纳
List<Long> otherCanPayEmpIds = getOtherSchemeMapper().listCanPayEmpIds(paymentOrganization, billMonth, 0);
if (socialCanPayEmpIds != null && socialCanPayEmpIds.size() > 0) {
listCanPayEmpIds.addAll(socialCanPayEmpIds);
}
@ -5763,16 +5762,23 @@ public class SIAccountServiceImpl extends Service implements SIAccountService {
log.info("核算明细临时表 hrsa_bill_detail_temp待处理数量{}", list.size());
List<List<Long>> partitionIds = Lists.partition((List<Long>) ids, 100);
log.info("bill_detail入库前删除数据数量{}", ids.size());
for (List<Long> part : partitionIds) {
getInsuranceAccountDetailMapper().batchDelAccountDetails(part, billMonth, param.getPaymentOrganization(), paymentStatus);
getInsuranceAccountDetailMapper().batchDelAccountDetails(Collections.emptyList(), billMonth, param.getPaymentOrganization(), paymentStatus);
//删除账单月份+个税扣缴义务人+人员id下的调差数据
getInsuranceCompensationMapper().deleteByBillMonthPayOrgEmpIds(InsuranceCompensationPO.builder()
.billMonth(billMonth)
.paymentOrganization(param.getPaymentOrganization())
.employeeIds(part)
.build());
}
//删除账单月份+个税扣缴义务人+人员id下的调差数据
getInsuranceCompensationMapper().deleteByBillMonthPayOrgEmpIds(InsuranceCompensationPO.builder()
.billMonth(billMonth)
.paymentOrganization(param.getPaymentOrganization())
.build());
// for (List<Long> part : partitionIds) {
// getInsuranceAccountDetailMapper().batchDelAccountDetails(part, billMonth, param.getPaymentOrganization(), paymentStatus);
//
// //删除账单月份+个税扣缴义务人+人员id下的调差数据
// getInsuranceCompensationMapper().deleteByBillMonthPayOrgEmpIds(InsuranceCompensationPO.builder()
// .billMonth(billMonth)
// .paymentOrganization(param.getPaymentOrganization())
// .employeeIds(part)
// .build());
// }
//生成bill_detail入库数据
List<InsuranceAccountDetailPO> collect = list.stream().map(item -> {

View File

@ -0,0 +1,285 @@
package com.engine.salary.timer;
import cn.hutool.core.util.StrUtil;
import com.engine.salary.exception.SalaryRunTimeException;
import com.engine.salary.mapper.SQLMapper;
import com.engine.salary.mapper.cbs.UfHkrdzbMapper;
import com.engine.salary.remote.cbs8.client.AccountManagementClient;
import com.engine.salary.remote.cbs8.config.EBS2ECConfig;
import com.engine.salary.remote.cbs8.po.UfHkrdzbPO;
import com.engine.salary.remote.cbs8.request.GetTransactionDetailRequest;
import com.engine.salary.remote.cbs8.response.GetTransactionDetailResponse;
import com.engine.salary.util.JsonUtil;
import com.engine.salary.util.SalaryEntityUtil;
import com.engine.salary.util.db.MapperProxyFactory;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.security.AnyTypePermission;
import lombok.extern.slf4j.Slf4j;
import weaver.conn.RecordSet;
import weaver.formmode.setup.ModeRightInfo;
import weaver.general.GCONST;
import weaver.general.TimeUtil;
import weaver.hrm.User;
import weaver.interfaces.schedule.BaseCronJob;
import java.io.File;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;
/**
* 获取境内账户明细
* <p>Copyright: Copyright (c) 2024</p>
* <p>Company: 泛微软件</p>
*
* @author qiantao
* @version 1.0
**/
@Slf4j
public class SyncCBSAccountDetailsJob extends BaseCronJob {
/**
* 开始日期 格式为yyyy-mm-dd
*/
private String startDate;
/**
* 结束日期 格式为yyyy-mm-dd
*/
private String endDate;
/**
* 借贷类型 1-2-
*/
private String loanType;
/**
* 款项性质列表
*/
private String paymentNatureList;
/**
* 日期类型 0-交易日期
*/
private String dateType;
/**
* 账户列表 查询账户列表不传默认返回全部
*/
private String accountNoList;
/**
* 银行类型列表 例如招行CMB银行类型枚举见附录4.1.5
*/
private String bankTypeList;
/**
* 币种列表 见附录币种枚举4.1.1
*/
private String currencyList;
/**
* 明细来源
* B银行即银行直联
* U用户即手工/ERP接口导入
* 不传默认查全部
*/
private String detailedSources;
/**
* 明细类型 1-当日明细 2-历史明细 与明细日期无关仅标识数据来源银行的不同接口
*/
private String currentFlag;
/**
* 账户性质列表 客户在公共设置>基础信息>账户性质查询自定义内容例如AA-综合户此处传值AA
*/
private String accountNatureList;
/**
* 银行流水号 银行流水号
*/
private String bankSerialNumber;
/**
* 交易流水号 交易流水号由CBS8定义生成的唯一标识
*/
private Long transactionSerialNumber;
/**
* 单位编码列表 客户在公共设置>基础信息>组织机构维护例如0001-XX科技有限公司此处传0001
*/
private String unitCodeList;
/**
* ERP业务参考号 erpSerialNumber
*/
private String erpSerialNumber;
private SQLMapper getSQLMapper() {
return MapperProxyFactory.getProxy(SQLMapper.class);
}
private UfHkrdzbMapper getUfHkrdzbMapper() {
return MapperProxyFactory.getProxy(UfHkrdzbMapper.class);
}
@Override
public void execute() {
User user = new User();
user.setUid(1);
user.setLoginid("sysadmin");
try {
GetTransactionDetailRequest requestParam = new GetTransactionDetailRequest();
requestParam.setCurrentPage(1);
requestParam.setPageSize(1000);
if (StrUtil.isNotBlank(startDate) && StrUtil.isNotBlank(endDate)) {
requestParam.setStartDate(startDate);
requestParam.setEndDate(endDate);
} else {
String nowDate = LocalDate.now().toString();
requestParam.setStartDate(nowDate);
requestParam.setEndDate(nowDate);
}
requestParam.setLoanType(loanType);
requestParam.setPaymentNatureList(paymentNatureList == null ? null :Arrays.stream(paymentNatureList.split(",")).collect(Collectors.toList()));
requestParam.setDateType(dateType);
requestParam.setAccountNoList(accountNoList== null ? null :Arrays.stream(accountNoList.split(",")).collect(Collectors.toList()));
requestParam.setBankTypeList(bankTypeList== null ? null :Arrays.stream(bankTypeList.split(",")).collect(Collectors.toList()));
requestParam.setCurrencyList(currencyList== null ? null :Arrays.stream(currencyList.split(",")).collect(Collectors.toList()));
requestParam.setDetailedSources(detailedSources);
requestParam.setCurrentFlag(currentFlag);
requestParam.setAccountNatureList(accountNatureList== null ? null :Arrays.stream(accountNatureList.split(",")).collect(Collectors.toList()));
requestParam.setBankSerialNumber(bankSerialNumber);
requestParam.setTransactionSerialNumber(transactionSerialNumber);
requestParam.setUnitCodeList(unitCodeList== null ? null :Arrays.stream(unitCodeList.split(",")).collect(Collectors.toList()));
requestParam.setErpSerialNumber(erpSerialNumber);
//查询前1000条数据
AccountManagementClient accountManagementClient = new AccountManagementClient();
GetTransactionDetailResponse response = accountManagementClient.transactionDetailQuery(requestParam);
List<GetTransactionDetailResponse.Detail> list = response.getData().getList();
//判断是否还存在数据递归查询
boolean hasNextPage = response.getData().isHasNextPage();
int nextPage = response.getData().getNextPage();
while (hasNextPage) {
requestParam.setCurrentPage(nextPage);
GetTransactionDetailResponse nextPageResponse = accountManagementClient.transactionDetailQuery(requestParam);
List<GetTransactionDetailResponse.Detail> pageData = nextPageResponse.getData().getList();
list.addAll(pageData);
hasNextPage = nextPageResponse.getData().isHasNextPage();
nextPage = nextPageResponse.getData().getNextPage();
}
//加载cbs配置
XStream xStream = new XStream();
String resource = GCONST.getRootPath() + "WEB-INF" + File.separatorChar + "CBS2ECConfig.xml";
File file = new File(resource);
xStream.addPermission(AnyTypePermission.ANY);
xStream.processAnnotations(EBS2ECConfig.class);
EBS2ECConfig dto = (EBS2ECConfig) xStream.fromXML(file);
EBS2ECConfig.Table table = dto.getTables().get(0);
Integer modeId = table.getModeId();
String tableName = table.getKey();
//获取已存在的数据
EBS2ECConfig.Table.Field uniqueField = table.getFields().stream().filter(EBS2ECConfig.Table.Field::isUnique).findFirst().orElse(null);
if (uniqueField == null) {
throw new SalaryRunTimeException("未设置唯一标识字段");
}
String uniqueKey = uniqueField.getKey();
String uniqueEbsKey = uniqueField.getEbsKey();
List<String> uniqueDataKeys = getSQLMapper().listString(String.format("select %s from %s", uniqueKey, tableName));
//获取汇款人与办事处的对照数据
List<UfHkrdzbPO> ufHkrdzbPOS = getUfHkrdzbMapper().listAll();
Map<String, Integer> customerDepartmentMap = SalaryEntityUtil.convert2Map(ufHkrdzbPOS, UfHkrdzbPO::getKhmc, UfHkrdzbPO::getDepartmentId);
for (GetTransactionDetailResponse.Detail detail : list) {
Map<String, String> detailMap = JsonUtil.parseMap(detail, String.class);
String uniqueData = detailMap.get(uniqueEbsKey);
if (StrUtil.isBlank(uniqueData)) {
log.warn("跳过cbs交易数据唯一标识返回空,uniqueKey:{},uniqueEbsKey:{}", uniqueKey, uniqueEbsKey);
continue;
}
if (uniqueDataKeys.contains(uniqueData)) {
log.warn("跳过cbs交易数据数据已存在,uniqueKey:{},uniqueEbsKey:{},值{}", uniqueKey, uniqueEbsKey, uniqueData);
continue;
}
List<String> fields = new ArrayList<String>() {{
//建模默认字段
add("formmodeid");
add("modedatacreater");
add("modedatacreatertype");
add("modedatacreatedate");
add("modedatacreatetime");
}};
String currDate = TimeUtil.getCurrentDateString();
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
String currTime = sdf.format(new Date());
List<Object> values = new ArrayList<Object>() {{
add(modeId);
add(1);
add(0);
add(String.format("'%s'", currDate));
add(String.format("'%s'", currTime));
}};
String hkr = "";
for (EBS2ECConfig.Table.Field field : table.getFields()) {
//数据库字段
String fieldName = field.getKey();
fields.add(fieldName);
// 接口值
String value = detailMap.getOrDefault(field.getEbsKey(), "");
values.add(String.format("'%s'", detailMap.getOrDefault(field.getEbsKey(), "")));
//汇款人
if ("hkr".equals(fieldName)) {
hkr = value;
}
}
//业务逻辑字段收款类型默认是银行存款
fields.add("sklx");
values.add(0);
/*
* 认领逻辑
* 根据汇款人去表里匹配汇款人与办事处的对照表
* 如果能匹配到数据则状态改为已自动认领同时把办事处部门的值同步到办事处字段中是否系统自动认领同步为是
* 如对照标准无数据则状态为未认领
*/
Integer departmentId = customerDepartmentMap.get(hkr);
if(departmentId!=null){
//认领
fields.add("zt");
values.add(1);
//是否系统认领
fields.add("sfxtzdrl");
values.add(1);
//办事处
fields.add("szbm");
values.add(departmentId);
}else {
//未认领
fields.add("zt");
values.add(0);
}
String sql = String.format("insert into %s (%s) values (%s)", tableName, String.join(",", fields), values.stream().map(Object::toString).collect(Collectors.joining(",")));
RecordSet rs = new RecordSet();
rs.execute(sql);
if (modeId != null) {
rs.executeQuery("select max(id) from " + tableName);
int mainId = 0;
if (rs.next()) {
mainId = rs.getInt(1);
}
ModeRightInfo ModeRightInfo = new ModeRightInfo();
ModeRightInfo.setNewRight(true);
ModeRightInfo.editModeDataShare(1, modeId, mainId);
}
}
} catch (Exception e) {
log.error("获取CBS交易信息失败", e);
throw new SalaryRunTimeException("获取CBS交易信息失败," + e.getMessage(), e);
}
}
}

View File

@ -0,0 +1,311 @@
package com.engine.salary.timer;
import cn.hutool.core.util.StrUtil;
import com.engine.salary.exception.SalaryRunTimeException;
import com.engine.salary.mapper.SQLMapper;
import com.engine.salary.remote.cbs8.client.BillManagementClient;
import com.engine.salary.remote.cbs8.config.EBS2ECConfig;
import com.engine.salary.remote.cbs8.request.GetDtaRequest;
import com.engine.salary.remote.cbs8.response.GetDtaResponse;
import com.engine.salary.util.JsonUtil;
import com.engine.salary.util.db.MapperProxyFactory;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.security.AnyTypePermission;
import lombok.extern.slf4j.Slf4j;
import weaver.conn.RecordSet;
import weaver.formmode.setup.ModeRightInfo;
import weaver.general.GCONST;
import weaver.general.TimeUtil;
import weaver.general.Util;
import weaver.hrm.User;
import weaver.interfaces.schedule.BaseCronJob;
import java.io.File;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;
/**
* 获取票据池
* <p>Copyright: Copyright (c) 2024</p>
* <p>Company: 泛微软件</p>
*
* @author qiantao
* @version 1.0
**/
@Slf4j
public class SyncCBSBillPoolJob extends BaseCronJob {
/**
* 持票人单位编码 多选填在cbs系统公共设置>基础信息>组织机构维护的单位编码
*/
private String displayHoldOrganizationCodeList;
/**
* 持票人账号 多选
*/
private String holdAccountList;
/**
* 系统票据类型 多选按附录4.1.3票据类型-票据状态-流通标志级联关系表选择后按顺序填写系统票据类型枚举见附录4.1.3票据状态枚举见附录4.1.4流通标志枚举见附录4.1.5
*/
private String billVarietyList;
/**
* 出票日期起 格式为yyyy-mm-dd出票日期起止不允许一边有值一边无值日期间隔最大为一年
*/
private String issueDateStart;
/**
* 出票日期止 格式为yyyy-mm-dd出票日期起止不允许一边有值一边无值日期间隔最大为一年
*/
private String issueDateEnd;
/**
* 到期日期起 格式为yyyy-mm-dd到期日期起止不允许一边有值一边无值日期间隔最大为一年
*/
private String dueDateStart;
/**
* 到期日期止 格式为yyyy-mm-dd到期日期起止不允许一边有值一边无值日期间隔最大为一年
*/
private String dueDateEnd;
/**
* 票据种类 AC01-银承AC02-商承
*/
private String billType;
/**
* 票据来源 多选1-直联交易2-台账交易3-台账登记4-挑票同步5-任务同步
*/
private String draftSourceList;
/**
* 持票银行类型 多选见附录4.1.1.银行类型枚举
*/
private String holdBankTypeList;
/**
* 持票签收日期起 格式为yyyy-mm-dd持票签收日期起止不允许一边有值一边无值日期间隔最大为一年
*/
private String holdSignDateStart;
/**
* 持票签收日期止 格式为yyyy-mm-dd持票签收日期起止不允许一边有值一边无值日期间隔最大为一年
*/
private String holdSignDateEnd;
/**
* 系统票据编号
*/
private String draftNbr;
/**
* 票据()
*/
private String billNbr;
/**
* 票据金额起 大于等于0,最多为两位小数且整数位上限为13位票据金额起止不允许一边有值一边无值单位
*/
private BigDecimal billAmountStart;
/**
* 票据金额止 大于等于0,最多为两位小数且整数位上限为13位票据金额起止不允许一边有值一边无值单位
*/
private BigDecimal billAmountEnd;
/**
* 子票区间起 子票区间起止不允许一边有值一边无值最多12位
*/
private String subBillIntervalStart;
/**
* 子票区间止 子票区间起止不允许一边有值一边无值,最多12位
*/
private String subBillIntervalEnd;
/**
* 票据状态
*/
private String billStsList;
/**
* 流通标志
*/
private String billTrsStsList;
/**
* 库存状态 1-已入库2-已出库 为空时默认查询全部数据
*/
private String stockFlag;
/**
* 出库方式 0-2-背书3-质押4-解质5-贴现6-分包7-结清, 8-作废 为空时默认查询全部数据
*/
private String outInvType;
/**
* 记录状态 NOR-正常USE-占用DEL-删除 SUC-完成为空时默认查询全部数据
*/
private String lockFlag;
private SQLMapper getSQLMapper() {
return MapperProxyFactory.getProxy(SQLMapper.class);
}
@Override
public void execute() {
User user = new User();
user.setUid(1);
user.setLoginid("sysadmin");
try {
GetDtaRequest requestParam = new GetDtaRequest();
requestParam.setCurrentPage(1);
requestParam.setPageSize(1000);
if (StrUtil.isBlank(displayHoldOrganizationCodeList)) {
throw new SalaryRunTimeException("持票人单位编码为空,请在计划任务配置此项!");
}
requestParam.setDisplayHoldOrganizationCodeList(Arrays.stream(displayHoldOrganizationCodeList.split(",")).collect(Collectors.toList()));
if (StrUtil.isBlank(holdAccountList)) {
throw new SalaryRunTimeException("持票人账号为空,请在计划任务配置此项!");
}
requestParam.setHoldAccountList(Arrays.stream(holdAccountList.split(",")).collect(Collectors.toList()));
if (StrUtil.isNotBlank(issueDateStart) && StrUtil.isNotBlank(issueDateEnd)) {
requestParam.setIssueDateStart(issueDateStart);
requestParam.setIssueDateEnd(issueDateEnd);
} else {
String nowDate = LocalDate.now().toString();
requestParam.setIssueDateStart(nowDate);
requestParam.setIssueDateEnd(nowDate);
}
//系统票据类型
requestParam.setBillVarietyList(Arrays.stream(Util.null2String(billVarietyList).split(",")).collect(Collectors.toList()));
requestParam.setDueDateStart(dueDateStart);
requestParam.setDueDateEnd(dueDateEnd);
requestParam.setBillType(billType);
requestParam.setDraftSourceList(draftSourceList==null ? null :Arrays.stream(draftSourceList.split(",")).collect(Collectors.toList()));
requestParam.setHoldBankTypeList(holdBankTypeList==null ? null :Arrays.stream(holdBankTypeList.split(",")).collect(Collectors.toList()));
requestParam.setHoldSignDateStart(holdSignDateStart);
requestParam.setHoldSignDateEnd(holdSignDateEnd);
requestParam.setDraftNbr(draftNbr);
requestParam.setBillNbr(billNbr);
requestParam.setBillAmountStart(billAmountStart);
requestParam.setBillAmountEnd(billAmountEnd);
requestParam.setSubBillIntervalStart(subBillIntervalStart);
requestParam.setSubBillIntervalEnd(subBillIntervalEnd);
requestParam.setBillStsList(billStsList==null ? null :Arrays.stream(billStsList.split(",")).collect(Collectors.toList()));
requestParam.setBillTrsStsList(billTrsStsList==null ? null :Arrays.stream(billTrsStsList.split(",")).collect(Collectors.toList()));
requestParam.setStockFlag(stockFlag);
requestParam.setOutInvType(outInvType);
requestParam.setLockFlag(lockFlag);
//查询前1000条数据
BillManagementClient bailManagementClient = new BillManagementClient();
GetDtaResponse response = bailManagementClient.dtaQuery(requestParam);
List<GetDtaResponse.Detail> list = response.getData().getList();
//判断是否还存在数据递归查询
boolean hasNextPage = response.getData().isHasNextPage();
int nextPage = response.getData().getNextPage();
while (hasNextPage) {
requestParam.setCurrentPage(nextPage);
GetDtaResponse nextPageResponse = bailManagementClient.dtaQuery(requestParam);
List<GetDtaResponse.Detail> pageData = nextPageResponse.getData().getList();
list.addAll(pageData);
hasNextPage = nextPageResponse.getData().isHasNextPage();
nextPage = nextPageResponse.getData().getNextPage();
}
//加载cbs配置
XStream xStream = new XStream();
String resource = GCONST.getRootPath() + "WEB-INF" + File.separatorChar + "CBS2ECConfig.xml";
File file = new File(resource);
xStream.addPermission(AnyTypePermission.ANY);
xStream.processAnnotations(EBS2ECConfig.class);
EBS2ECConfig dto = (EBS2ECConfig) xStream.fromXML(file);
EBS2ECConfig.Table table = dto.getTables().get(2);
Integer modeId = table.getModeId();
String tableName = table.getKey();
//获取已存在的数据
EBS2ECConfig.Table.Field uniqueField = table.getFields().stream().filter(EBS2ECConfig.Table.Field::isUnique).findFirst().orElse(null);
if (uniqueField == null) {
throw new SalaryRunTimeException("未设置唯一标识字段");
}
String uniqueKey = uniqueField.getKey();
String uniqueEbsKey = uniqueField.getEbsKey();
List<String> uniqueDataKeys = getSQLMapper().listString(String.format("select %s from %s", uniqueKey, tableName));
for (GetDtaResponse.Detail detail : list) {
Map<String, String> detailMap = JsonUtil.parseMap(detail, String.class);
String uniqueData = detailMap.get(uniqueEbsKey);
if (StrUtil.isBlank(uniqueData)) {
log.warn("跳过cbs票据池数据唯一标识返回空,uniqueKey:{},uniqueEbsKey:{}", uniqueKey, uniqueEbsKey);
continue;
}
if (uniqueDataKeys.contains(uniqueData)) {
log.warn("跳过cbs票据池数据数据已存在,uniqueKey:{},uniqueEbsKey:{},值{}", uniqueKey, uniqueEbsKey, uniqueData);
continue;
}
List<String> fields = new ArrayList<String>() {{
add("formmodeid");
add("modedatacreater");
add("modedatacreatertype");
add("modedatacreatedate");
add("modedatacreatetime");
}};
String currDate = TimeUtil.getCurrentDateString();
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
String currTime = sdf.format(new Date());
List<Object> values = new ArrayList<Object>() {{
add(modeId);
add(1);
add(0);
add(String.format("'%s'", currDate));
add(String.format("'%s'", currTime));
}};
for (EBS2ECConfig.Table.Field field : table.getFields()) {
//数据库字段
String fieldName = field.getKey();
fields.add(fieldName);
// 接口值
String value = detailMap.getOrDefault(field.getEbsKey(), "");
values.add(String.format("'%s'", value));
}
//业务逻辑字段收款类型
fields.add("pjlx");
//应付票据
Integer pjlx;
if ("ISS".equals(detail.getBillVariety())) {
pjlx = 2;
} else {
//应收票据 0银承 1商承
pjlx = "AC01".equals(detail.getBillType()) ? 0 : 1;
}
values.add(pjlx);
String sql = String.format("insert into %s (%s) values (%s)", tableName, String.join(",", fields), values.stream().map(Object::toString).collect(Collectors.joining(",")));
RecordSet rs = new RecordSet();
rs.execute(sql);
if (modeId != null) {
rs.executeQuery("select max(id) from " + tableName);
int mainId = 0;
if (rs.next()) {
mainId = rs.getInt(1);
}
ModeRightInfo ModeRightInfo = new ModeRightInfo();
ModeRightInfo.setNewRight(true);
ModeRightInfo.editModeDataShare(1, modeId, mainId);
}
}
} catch (Exception e) {
log.error("获取CBS票据池数据失败", e);
throw new SalaryRunTimeException("获取CBS票据池数据失败," + e.getMessage(), e);
}
}
}

View File

@ -0,0 +1,344 @@
package com.engine.salary.timer;
import cn.hutool.core.util.StrUtil;
import com.engine.salary.exception.SalaryRunTimeException;
import com.engine.salary.mapper.SQLMapper;
import com.engine.salary.mapper.cbs.UfHkrdzbMapper;
import com.engine.salary.remote.cbs8.client.BillManagementClient;
import com.engine.salary.remote.cbs8.config.EBS2ECConfig;
import com.engine.salary.remote.cbs8.po.UfHkrdzbPO;
import com.engine.salary.remote.cbs8.request.GetDtaRequest;
import com.engine.salary.remote.cbs8.response.GetDtaResponse;
import com.engine.salary.util.JsonUtil;
import com.engine.salary.util.SalaryEntityUtil;
import com.engine.salary.util.db.MapperProxyFactory;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.security.AnyTypePermission;
import lombok.extern.slf4j.Slf4j;
import weaver.conn.RecordSet;
import weaver.formmode.setup.ModeRightInfo;
import weaver.general.GCONST;
import weaver.general.TimeUtil;
import weaver.hrm.User;
import weaver.interfaces.schedule.BaseCronJob;
import java.io.File;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;
/**
* 获取票据收款明细
* <p>Copyright: Copyright (c) 2024</p>
* <p>Company: 泛微软件</p>
*
* @author qiantao
* @version 1.0
**/
@Slf4j
public class SyncCBSPayDetailsJob extends BaseCronJob {
/**
* 持票人单位编码 多选填在cbs系统公共设置>基础信息>组织机构维护的单位编码
*/
private String displayHoldOrganizationCodeList;
/**
* 持票人账号 多选
*/
private String holdAccountList;
/**
* 系统票据类型 多选按附录4.1.3票据类型-票据状态-流通标志级联关系表选择后按顺序填写系统票据类型枚举见附录4.1.3票据状态枚举见附录4.1.4流通标志枚举见附录4.1.5
*/
private String billVarietyList;
/**
* 出票日期起 格式为yyyy-mm-dd出票日期起止不允许一边有值一边无值日期间隔最大为一年
*/
private String issueDateStart;
/**
* 出票日期止 格式为yyyy-mm-dd出票日期起止不允许一边有值一边无值日期间隔最大为一年
*/
private String issueDateEnd;
/**
* 到期日期起 格式为yyyy-mm-dd到期日期起止不允许一边有值一边无值日期间隔最大为一年
*/
private String dueDateStart;
/**
* 到期日期止 格式为yyyy-mm-dd到期日期起止不允许一边有值一边无值日期间隔最大为一年
*/
private String dueDateEnd;
/**
* 票据种类 AC01-银承AC02-商承
*/
private String billType;
/**
* 票据来源 多选1-直联交易2-台账交易3-台账登记4-挑票同步5-任务同步
*/
private String draftSourceList;
/**
* 持票银行类型 多选见附录4.1.1.银行类型枚举
*/
private String holdBankTypeList;
/**
* 持票签收日期起 格式为yyyy-mm-dd持票签收日期起止不允许一边有值一边无值日期间隔最大为一年
*/
private String holdSignDateStart;
/**
* 持票签收日期止 格式为yyyy-mm-dd持票签收日期起止不允许一边有值一边无值日期间隔最大为一年
*/
private String holdSignDateEnd;
/**
* 系统票据编号
*/
private String draftNbr;
/**
* 票据()
*/
private String billNbr;
/**
* 票据金额起 大于等于0,最多为两位小数且整数位上限为13位票据金额起止不允许一边有值一边无值单位
*/
private BigDecimal billAmountStart;
/**
* 票据金额止 大于等于0,最多为两位小数且整数位上限为13位票据金额起止不允许一边有值一边无值单位
*/
private BigDecimal billAmountEnd;
/**
* 子票区间起 子票区间起止不允许一边有值一边无值最多12位
*/
private String subBillIntervalStart;
/**
* 子票区间止 子票区间起止不允许一边有值一边无值,最多12位
*/
private String subBillIntervalEnd;
/**
* 票据状态
*/
private String billStsList;
/**
* 流通标志
*/
private String billTrsStsList;
/**
* 库存状态 1-已入库2-已出库 为空时默认查询全部数据
*/
private String stockFlag;
/**
* 出库方式 0-2-背书3-质押4-解质5-贴现6-分包7-结清, 8-作废 为空时默认查询全部数据
*/
private String outInvType;
/**
* 记录状态 NOR-正常USE-占用DEL-删除 SUC-完成为空时默认查询全部数据
*/
private String lockFlag;
private SQLMapper getSQLMapper() {
return MapperProxyFactory.getProxy(SQLMapper.class);
}
private UfHkrdzbMapper getUfHkrdzbMapper() {
return MapperProxyFactory.getProxy(UfHkrdzbMapper.class);
}
@Override
public void execute() {
User user = new User();
user.setUid(1);
user.setLoginid("sysadmin");
try {
GetDtaRequest requestParam = new GetDtaRequest();
requestParam.setCurrentPage(1);
requestParam.setPageSize(1000);
if (StrUtil.isBlank(displayHoldOrganizationCodeList)) {
throw new SalaryRunTimeException("持票人单位编码为空,请在计划任务配置此项!");
}
requestParam.setDisplayHoldOrganizationCodeList(Arrays.stream(displayHoldOrganizationCodeList.split(",")).collect(Collectors.toList()));
if (StrUtil.isBlank(holdAccountList)) {
throw new SalaryRunTimeException("持票人账号为空,请在计划任务配置此项!");
}
requestParam.setHoldAccountList(Arrays.stream(holdAccountList.split(",")).collect(Collectors.toList()));
if (StrUtil.isNotBlank(issueDateStart) && StrUtil.isNotBlank(issueDateEnd)) {
requestParam.setIssueDateStart(issueDateStart);
requestParam.setIssueDateEnd(issueDateEnd);
} else {
String nowDate = LocalDate.now().toString();
requestParam.setIssueDateStart(nowDate);
requestParam.setIssueDateEnd(nowDate);
}
//系统票据类型
requestParam.setBillVarietyList(Arrays.stream(billVarietyList.split(",")).collect(Collectors.toList()));
requestParam.setDueDateStart(dueDateStart);
requestParam.setDueDateEnd(dueDateEnd);
requestParam.setBillType(billType);
requestParam.setDraftSourceList(draftSourceList==null ? null :Arrays.stream(draftSourceList.split(",")).collect(Collectors.toList()));
requestParam.setHoldBankTypeList(holdBankTypeList==null ? null :Arrays.stream(holdBankTypeList.split(",")).collect(Collectors.toList()));
requestParam.setHoldSignDateStart(holdSignDateStart);
requestParam.setHoldSignDateEnd(holdSignDateEnd);
requestParam.setDraftNbr(draftNbr);
requestParam.setBillNbr(billNbr);
requestParam.setBillAmountStart(billAmountStart);
requestParam.setBillAmountEnd(billAmountEnd);
requestParam.setSubBillIntervalStart(subBillIntervalStart);
requestParam.setSubBillIntervalEnd(subBillIntervalEnd);
requestParam.setBillStsList(billStsList==null ? null :Arrays.stream(billStsList.split(",")).collect(Collectors.toList()));
requestParam.setBillTrsStsList(billTrsStsList==null ? null :Arrays.stream(billTrsStsList.split(",")).collect(Collectors.toList()));
requestParam.setStockFlag(stockFlag);
requestParam.setOutInvType(outInvType);
requestParam.setLockFlag(lockFlag);
//查询前1000条数据
BillManagementClient bailManagementClient = new BillManagementClient();
GetDtaResponse response = bailManagementClient.dtaQuery(requestParam);
List<GetDtaResponse.Detail> list = response.getData().getList();
//判断是否还存在数据递归查询
boolean hasNextPage = response.getData().isHasNextPage();
int nextPage = response.getData().getNextPage();
while (hasNextPage) {
requestParam.setCurrentPage(nextPage);
GetDtaResponse nextPageResponse = bailManagementClient.dtaQuery(requestParam);
List<GetDtaResponse.Detail> pageData = nextPageResponse.getData().getList();
list.addAll(pageData);
hasNextPage = nextPageResponse.getData().isHasNextPage();
nextPage = nextPageResponse.getData().getNextPage();
}
//加载cbs配置
XStream xStream = new XStream();
String resource = GCONST.getRootPath() + "WEB-INF" + File.separatorChar + "CBS2ECConfig.xml";
File file = new File(resource);
xStream.addPermission(AnyTypePermission.ANY);
xStream.processAnnotations(EBS2ECConfig.class);
EBS2ECConfig dto = (EBS2ECConfig) xStream.fromXML(file);
EBS2ECConfig.Table table = dto.getTables().get(1);
Integer modeId = table.getModeId();
String tableName = table.getKey();
//获取已存在的数据
EBS2ECConfig.Table.Field uniqueField = table.getFields().stream().filter(EBS2ECConfig.Table.Field::isUnique).findFirst().orElse(null);
if (uniqueField == null) {
throw new SalaryRunTimeException("未设置唯一标识字段");
}
String uniqueKey = uniqueField.getKey();
String uniqueEbsKey = uniqueField.getEbsKey();
List<String> uniqueDataKeys = getSQLMapper().listString(String.format("select %s from %s", uniqueKey, tableName));
//获取汇款人与办事处的对照数据
List<UfHkrdzbPO> ufHkrdzbPOS = getUfHkrdzbMapper().listAll();
Map<String, Integer> customerDepartmentMap = SalaryEntityUtil.convert2Map(ufHkrdzbPOS, UfHkrdzbPO::getKhmc, UfHkrdzbPO::getDepartmentId);
for (GetDtaResponse.Detail detail : list) {
Map<String, String> detailMap = JsonUtil.parseMap(detail, String.class);
String uniqueData = detailMap.get(uniqueEbsKey);
if (StrUtil.isBlank(uniqueData)) {
log.warn("跳过cbs票据收款数据唯一标识返回空,uniqueKey:{},uniqueEbsKey:{}", uniqueKey, uniqueEbsKey);
continue;
}
if (uniqueDataKeys.contains(uniqueData)) {
log.warn("跳过cbs票据收款数据数据已存在,uniqueKey:{},uniqueEbsKey:{},值{}", uniqueKey, uniqueEbsKey, uniqueData);
continue;
}
List<String> fields = new ArrayList<String>() {{
add("formmodeid");
add("modedatacreater");
add("modedatacreatertype");
add("modedatacreatedate");
add("modedatacreatetime");
}};
String currDate = TimeUtil.getCurrentDateString();
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
String currTime = sdf.format(new Date());
List<Object> values = new ArrayList<Object>() {{
add(modeId);
add(1);
add(0);
add(String.format("'%s'", currDate));
add(String.format("'%s'", currTime));
}};
String hkr = "";
for (EBS2ECConfig.Table.Field field : table.getFields()) {
//数据库字段
String fieldName = field.getKey();
fields.add(fieldName);
// 接口值
String value = detailMap.getOrDefault(field.getEbsKey(), "");
values.add(String.format("'%s'", value));
//汇款人
if ("hkr".equals(fieldName)) {
hkr = value;
}
}
//业务逻辑字段收款类型
fields.add("sklx");
//应收票据 0银承 1商承
values. add("AC01".equals(detail.getBillType()) ? 0 : 1);
/*
* 认领逻辑
* 根据汇款人去表里匹配汇款人与办事处的对照表
* 如果能匹配到数据则状态改为已自动认领同时把办事处部门的值同步到办事处字段中是否系统自动认领同步为是
* 如对照标准无数据则状态为未认领
*/
Integer departmentId = customerDepartmentMap.get(hkr);
if(departmentId!=null){
//认领
fields.add("zt");
values.add(1);
//是否系统认领
fields.add("sfxtzdrl");
values.add(1);
//办事处
fields.add("szbm");
values.add(departmentId);
}else {
//未认领
fields.add("zt");
values.add(0);
}
String sql = String.format("insert into %s (%s) values (%s)", tableName, String.join(",", fields), values.stream().map(Object::toString).collect(Collectors.joining(",")));
RecordSet rs = new RecordSet();
rs.execute(sql);
if (modeId != null) {
rs.executeQuery("select max(id) from " + tableName);
int mainId = 0;
if (rs.next()) {
mainId = rs.getInt(1);
}
ModeRightInfo ModeRightInfo = new ModeRightInfo();
ModeRightInfo.setNewRight(true);
ModeRightInfo.editModeDataShare(1, modeId, mainId);
}
}
} catch (Exception e) {
log.error("获取CBS票据收款数据失败", e);
throw new SalaryRunTimeException("获取CBS票据收款数据信息失败," + e.getMessage(), e);
}
}
}