123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385 |
- package kd.cosmic.jkjt.tmc.api;
- import com.alibaba.fastjson.JSONArray;
- import com.alibaba.fastjson.JSONObject;
- import kd.bos.coderule.api.CodeRuleInfo;
- import kd.bos.dataentity.OperateOption;
- import kd.bos.dataentity.entity.DynamicObject;
- import kd.bos.dataentity.entity.DynamicObjectCollection;
- import kd.bos.entity.operate.result.OperationResult;
- import kd.bos.logging.Log;
- import kd.bos.logging.LogFactory;
- import kd.bos.openapi.common.custom.annotation.ApiController;
- import kd.bos.openapi.common.custom.annotation.ApiPostMapping;
- import kd.bos.openapi.common.result.CustomApiResult;
- import kd.bos.orm.query.QCP;
- import kd.bos.orm.query.QFilter;
- import kd.bos.servicehelper.BusinessDataServiceHelper;
- import kd.bos.servicehelper.QueryServiceHelper;
- import kd.bos.servicehelper.coderule.CodeRuleServiceHelper;
- import kd.bos.servicehelper.operation.OperationServiceHelper;
- import kd.bos.util.StringUtils;
- import kd.cosmic.jkjt.tmc.util.CBSToolUtil;
- import kd.cosmic.jkjt.tmc.util.ParamsUtil;
- import kd.cosmic.jkjt.tmc.util.XmlUtils;
- import org.apache.commons.lang.time.DateFormatUtils;
- import java.io.Serializable;
- import java.math.BigDecimal;
- import java.sql.Timestamp;
- import java.text.ParseException;
- import java.text.SimpleDateFormat;
- import java.util.*;
- /**
- * @author wanghaiwu_kd
- * @date 2023/05/08
- * @description API插件,未开通银企直连的账户,根据CBS系统的账户余额,与星瀚中的余额比较,如果有差额,则自动生成交易明细。
- */
- @ApiController(
- desc = "未开通银企直连的账户根据CBS账户余额生产交易明细",
- value = "jkjt_cbsapi"
- )
- public class SynBentransByBalance2Plugin implements Serializable {
- private static final long serialVersionUID = -5560815141256121757L;
- private static Log logger = LogFactory.getLog(SynBentransByBalance2Plugin.class);
- //出纳初始化
- private static final String KEY_ENTITY_CASHINIT = "cas_cashmgtinit";
- //银行账户
- private static final String KEY_ENTITY_ACCOUNT = "am_accountbank";
- //离线明细引入实体编码
- private static final String KEY_ENTITY_BETRANSDETAIL = "bei_betransdetail_imp";
- @ApiPostMapping("SynBetransByBalance")
- public CustomApiResult<JSONObject> doCustomerService(){
- //先更新cbs开通状态
- List<Long> orgIds = new ArrayList<>();
- CBSToolUtil.synAccountOpenStatus(orgIds);
- String selectProperties = "bankaccountnumber, openorg, currency, bank, company";
- QFilter qFilter = new QFilter("nckd_issetcbs", QCP.equals, false);
- qFilter.and(new QFilter("acctstatus", QCP.equals, "normal"));
- // qFilter.and(new QFilter("bankaccountnumber", QCP.equals, "791909297510506"));
- DynamicObject[] acctList = BusinessDataServiceHelper.load(KEY_ENTITY_ACCOUNT, selectProperties, new QFilter[]{qFilter});
- List<DynamicObject> listObj = new ArrayList<>();
- int count = 0;
- for(DynamicObject acct : acctList){
- JSONObject lastBal = queryLastBal(acct);
- // if("500".equals(lastBal.getString("code"))){
- // continue;
- // }
- String accountNumber = acct.getString("bankaccountnumber");
- DynamicObject openOrg = acct.getDynamicObject("openorg");
- if(openOrg == null){
- continue;
- }
- Long orgId = openOrg.getLong("id");
- String cbsUrl = ParamsUtil.getCBSURLByMaster(orgId);
- if(StringUtils.isEmpty(cbsUrl)){
- logger.info("同步交易明细失败:组织【" + openOrg.getString("name") + "】(" + orgId.toString() + ")未配置相应的CBS地址");
- continue;
- }
- //账户实时余额查询ERCURBAL报文内容
- String body = getDetailBodyString(accountNumber);
- String paramBody = CBSToolUtil.getBodyString(body);
- //保存CBS调用日志
- String uuid = ParamsUtil.saveCBSLogData(cbsUrl, "detail", paramBody);
- String sTime = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");
- logger.info("调用CBS接口ERCURBAL开始时间:" + sTime);
- String sr = CBSToolUtil.sendPost(cbsUrl, paramBody);
- String eTime = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");
- logger.info("调用CBS接口ERCURBAL结束时间:" + eTime);
- //更新CBS调用日志
- ParamsUtil.updateCBSLogData(uuid, sr);
- String cbssr = CBSToolUtil.parseXMLcbs(sr);
- DynamicObject result = getBalanceDetailInfo(cbssr, acct, lastBal.getBigDecimal("bal"));
- if(result != null){
- listObj.add(result);
- }
- count++;
- //批量保存
- if(listObj.size() > 0 && count == 1000) {
- count = 0;
- OperationResult resultSave = OperationServiceHelper.executeOperate("save", KEY_ENTITY_BETRANSDETAIL, listObj.toArray(new DynamicObject[]{}), OperateOption.create());
- StringBuilder err = new StringBuilder();
- if (resultSave.getSuccessPkIds().size() <= 0) {
- for (int index = 0; index < resultSave.getAllErrorOrValidateInfo().size(); index++) {
- String message = resultSave.getAllErrorOrValidateInfo().get(index).getMessage();
- err.append("/").append(message);
- }
- }
- listObj.clear();
- }
- }
- //批量保存
- if(listObj.size() > 0) {
- OperationResult resultSave = OperationServiceHelper.executeOperate("save", KEY_ENTITY_BETRANSDETAIL, listObj.toArray(new DynamicObject[]{}), OperateOption.create());
- StringBuilder err = new StringBuilder();
- if (resultSave.getSuccessPkIds().size() <= 0) {
- for (int index = 0; index < resultSave.getAllErrorOrValidateInfo().size(); index++) {
- String message = resultSave.getAllErrorOrValidateInfo().get(index).getMessage();
- err.append("/").append(message);
- }
- }
- }
- //自动生成余额
- // try {
- // ParamsUtil.createBalance();
- // } catch (ParseException e) {
- // throw new RuntimeException(e);
- // }
- return returnResult("200", "同步成功!");
- }
- /**
- * 查询账号在星瀚的当前余额
- * @param acct
- * @return
- */
- private JSONObject queryLastBal(DynamicObject acct){
- String code = "200";
- BigDecimal bal = BigDecimal.ZERO;
- //查询是否存在交易明细
- SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
- //交易时间
- Date time = new Date();
- //交易日期
- Date date = null;
- try {
- date = sdf1.parse(sdf1.format(time));
- } catch (ParseException e) {
- throw new RuntimeException(e);
- }
- QFilter qFilter = new QFilter("accountbank.id", QCP.equals, acct.getLong("id"));
- qFilter.and(new QFilter("bizdate", QCP.less_than, date));
- String selectProperties = "transbalance";
- String orderBy = "biztime desc";
- DynamicObject[] detailList = BusinessDataServiceHelper.load(KEY_ENTITY_BETRANSDETAIL, selectProperties, qFilter.toArray(), orderBy);
- //如果没有交易明细,则查找是否有做出纳初始化初始余额
- if(detailList.length == 0){
- qFilter = new QFilter("entrybank.bank_accountbank", QCP.equals, acct.getLong("id"));
- selectProperties = "entrybank.bank_journalbalance";
- orderBy = "startperiod.number desc";
- DynamicObjectCollection objCols = QueryServiceHelper.query(KEY_ENTITY_CASHINIT, selectProperties, qFilter.toArray(), orderBy);
- if(objCols.size() > 0){
- code = "200";
- bal = objCols.get(0).getBigDecimal("entrybank.bank_journalbalance");
- }
- } else {
- code = "200";
- bal = detailList[0].getBigDecimal("transbalance");
- }
- JSONObject reslutData = new JSONObject();
- reslutData.put("code", code);
- reslutData.put("bal", bal);
- return reslutData;
- }
- /**
- * 交易明细参数body
- * @return
- */
- private String getDetailBodyString(String accountNumber){
- StringBuffer body = new StringBuffer();
- body.append("<?xml version='1.0' encoding='GB2312'?>\r\n");
- body.append("<CBSERPPGK>\r\n");
- body.append("<INFO>\r\n");
- body.append("<FUNNAM>ERCURBAL</FUNNAM>\r\n");
- body.append("</INFO>\r\n");
- body.append("<ERCURBALX>\r\n");
- body.append("<ACTNBR>").append(accountNumber).append("</ACTNBR>\r\n");
- body.append("</ERCURBALX>\r\n");
- body.append("</CBSERPPGK>\r\n");
- return body.toString();
- }
- /**
- * 处理cbs返回结果
- * @param cbssr
- * @return
- */
- private DynamicObject getBalanceDetailInfo(String cbssr, DynamicObject acct, BigDecimal lastBal){
- JSONObject cbsObj = XmlUtils.documentToJSONObject(cbssr);
- if(cbsObj != null && cbsObj.get("ACACTINFY") != null){
- JSONArray array = (JSONArray)cbsObj.get("ACACTINFY");
- JSONObject account = array.getJSONObject(0);
- List<DynamicObject> listObj = new ArrayList<>();
- DynamicObject detailInfo = null;
- try {
- detailInfo = parseBetransDetail(account, acct, lastBal);
- } catch (ParseException e) {
- throw new RuntimeException(e);
- }
- return detailInfo;
- }
- return null;
- }
- /**
- * 创建离线明细引入对象
- * @param cbsObj
- * @return
- */
- private DynamicObject parseBetransDetail(JSONObject cbsObj, DynamicObject acct, BigDecimal lastBal) throws ParseException {
- //账户余额
- BigDecimal actBal = cbsObj.getBigDecimal("ACTBAL");
- if(actBal == null){
- actBal = BigDecimal.ZERO;
- }
- //处理日期类字段
- SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
- SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
- //交易时间
- Date time = new Date();
- //交易日期
- Date date = sdf1.parse(sdf1.format(time));
- //如果当天存在cbs交易明细,则不增加交易明细
- Boolean isExistDetail = ParamsUtil.isExistsDetail(acct, date, new String[]{"curday", "history"});
- if(isExistDetail){
- return null;
- }
- DynamicObject objectInfo = ParamsUtil.getDetailInfo(acct, date, "balancecompare");
- if(objectInfo == null){
- objectInfo = BusinessDataServiceHelper.newDynamicObject(KEY_ENTITY_BETRANSDETAIL);
- }
- objectInfo.set("nckd_generatemethod", "balancecompare");
- //借贷方向:1:借方,2:贷方
- String direct = "";
- BigDecimal dayActAmt = actBal.subtract(lastBal).abs();
- if(lastBal.compareTo(actBal) > 0){
- direct = "1";
- } else if(lastBal.compareTo(actBal) < 0){
- direct = "2";
- } else {
- return null;
- }
- String detailid = UUID.randomUUID().toString().replace("-", "");
- detailid = (detailid == null) ? ("uuid" + String.valueOf(System.currentTimeMillis())) : detailid;
- objectInfo.set("oppunit", null);//对方用户名
- objectInfo.set("oppbanknumber", null);//对方账号
- objectInfo.set("oppbank", null);//对方开户行
- objectInfo.set("detailid", detailid);//明细流水号
- objectInfo.set("bizrefno", detailid);//业务参考号
- objectInfo.set("uniqueseq", detailid + "01");//银行主键
- objectInfo.set("description", null);//摘要
- //判断此明细流水号是否已存在,已存在的记录不接收
- QFilter filterBizRefNo = new QFilter("detailid", QCP.equals, objectInfo.getString("detailid"));
- QFilter filterDataSource = new QFilter("datasource", QCP.equals, "import");
- QFilter[] filters = new QFilter[]{filterBizRefNo, filterDataSource};
- DynamicObject betransDetailInfo = BusinessDataServiceHelper.loadSingle(KEY_ENTITY_BETRANSDETAIL, "id, billno", filters);
- if(betransDetailInfo != null){
- return null;
- }
- //交易时间
- objectInfo.set("bizTime", new Timestamp(time.getTime()));
- //交易日期
- objectInfo.set("bizdate", new Timestamp(date.getTime()));
- //入账状态
- if("2".equals(direct)){
- objectInfo.set("receredtype", "0");
- }
- //发生额
- objectInfo.set("debitamount", BigDecimal.ZERO);
- objectInfo.set("creditamount", BigDecimal.ZERO);
- String amountField = ParamsUtil.getAmountFieldName(direct);
- objectInfo.set(amountField, dayActAmt);
- //手续费
- // objectInfo.set("transfercharge", BigDecimal.ZERO);
- //余额
- objectInfo.set("transbalance", actBal);
- //单据状态
- objectInfo.set("billstatus", "A");
- //数据来源
- objectInfo.set("datasource", "import");
- //业务类型
- objectInfo.set("biztype", "1");
- //币别
- DynamicObjectCollection collection = acct.getDynamicObjectCollection("currency");
- Long currencyId = 0L;
- for (DynamicObject item : collection) {
- //引用该基础资料的单据id
- long pkid = item.getLong("pkid");
- // 获取该基础资料的动态对象
- DynamicObject fbasedataid = item.getDynamicObject("fbasedataid");
- //获取该基础资料的id
- currencyId = item.getLong("fbasedataid_id");
- }
- DynamicObject currency = BusinessDataServiceHelper.loadSingleFromCache(currencyId, "bd_currency");
- objectInfo.set("currency", currency);
- //银行账号
- objectInfo.set("accountbank", acct);
- objectInfo.set("bank", acct.get("bank"));
- objectInfo.set("company", acct.get("company"));
- CodeRuleInfo codeRule = CodeRuleServiceHelper.getCodeRule(objectInfo.getDataEntityType().getName(), objectInfo, null);
- String billno = CodeRuleServiceHelper.getNumber(codeRule, objectInfo);
- objectInfo.set("billno", billno);
- return objectInfo;
- }
- /**
- * 自定义返回data对象
- * @param code
- * @param message
- * @return
- */
- public CustomApiResult<JSONObject> returnResult(String code, String message){
- JSONObject reslutData = new JSONObject();
- reslutData.put("code", code);
- reslutData.put("message", message);
- CustomApiResult<JSONObject> result = CustomApiResult.success(reslutData);
- return result;
- }
- }
|