package kd.cosmic.jkjt.tmc.bei.task; import kd.bos.algo.DataSet; import kd.bos.context.RequestContext; import kd.bos.dataentity.entity.DynamicObject; import kd.bos.dataentity.entity.DynamicObjectCollection; import kd.bos.db.DB; import kd.bos.db.DBRoute; import kd.bos.entity.EntityMetadataCache; import kd.bos.entity.MainEntityType; import kd.bos.exception.KDException; import kd.bos.logging.BizLog; import kd.bos.orm.ORM; import kd.bos.orm.query.QCP; import kd.bos.orm.query.QFilter; import kd.bos.schedule.api.StopTask; import kd.bos.schedule.executor.AbstractTask; import kd.bos.servicehelper.BusinessDataServiceHelper; import kd.bos.servicehelper.QueryServiceHelper; import kd.bos.workflow.engine.msg.info.MessageInfo; import kd.cosmic.jkjt.tmc.bei.common.CommonUtils; import kd.cosmic.jkjt.tmc.bei.common.DateUtils; import kd.cosmic.jkjt.tmc.bei.common.FeishuSendMessageUtils; import kd.cosmic.jkjt.tmc.bei.common.constant.BeiBeTransDetailConstant; import kd.cosmic.jkjt.tmc.bei.common.constant.MsgWarnConfigConstant; import kd.cosmic.jkjt.tmc.bei.common.constant.MsgWarnTemplateConstant; import kd.cosmic.jkjt.tmc.bei.common.entity.MsgWarnMessageInfo; import kd.cosmic.jkjt.tmc.bei.common.enums.MsgWarnTypeEnum; import java.math.BigDecimal; import java.time.LocalDate; import java.util.*; import java.util.stream.Collectors; /** * 日常报销账户月度提醒 */ public class DailyReimMsgWarnTask extends AbstractTask implements StopTask { private MsgWarnTypeEnum WARTYPE = MsgWarnTypeEnum.DAILYREIM; @Override public void execute(RequestContext requestContext, Map map) throws KDException { // 查询生效的账户大额交易通知配置 Set largeTransIdConfig = getMsgWarnConfig(); largeTransIdConfig.forEach(configId -> transConfigSendMessage(configId)); } protected Set getMsgWarnConfig() { DynamicObjectCollection configCol = QueryServiceHelper.query(MsgWarnConfigConstant.ENTITYID, "id,nckd_company.id", new QFilter[]{ new QFilter(MsgWarnConfigConstant.KEY_NCKD_TYPE, QFilter.equals, WARTYPE.getValue()), new QFilter(MsgWarnConfigConstant.KEY_STATUS, QFilter.equals, "C"), new QFilter(MsgWarnConfigConstant.KEY_ENABLE, QFilter.equals, "1") }); Map companyIdMap = configCol.stream() .collect(Collectors.toMap(r -> r.getLong("nckd_company.id"), r -> r.getLong("id"), (a, b) -> a)); return companyIdMap.values().stream().collect(Collectors.toSet()); } protected void transConfigSendMessage(Long configId) { DynamicObject msgWarnConfig = BusinessDataServiceHelper.loadSingle(configId, MsgWarnConfigConstant.ENTITYID); DynamicObject company = msgWarnConfig.getDynamicObject(MsgWarnConfigConstant.KEY_NCKD_COMPANY); DynamicObject financeDirectors = msgWarnConfig.getDynamicObject(MsgWarnConfigConstant.KEY_NCKD_FINANCE_DIRECTOR); DynamicObject financeLeader = msgWarnConfig.getDynamicObject(MsgWarnConfigConstant.KEY_NCKD_FINANCE_LEADER); // 没有设置接收人时跳过 if(financeDirectors == null || financeLeader == null){ BizLog.log("消息接收人为空,不进行消息发送。"); return; } List receiverIdList = new ArrayList<>(); receiverIdList.add(financeDirectors.getLong("id")); receiverIdList.add(financeLeader.getLong("id")); //每月首个工作日上午9点发送上月预警信息 LocalDate today = LocalDate.now(); // 上个月第一天 LocalDate firstDayOfLastMonth = today.minusMonths(13).withDayOfMonth(1); // 本月第一天 LocalDate firstDayOfThisMonth = today.withDayOfMonth(1); Date beginDate = Date.from(firstDayOfLastMonth.atStartOfDay().atZone(java.time.ZoneId.systemDefault()).toInstant()); Date endDate = Date.from(firstDayOfThisMonth.atStartOfDay().atZone(java.time.ZoneId.systemDefault()).toInstant()); // 获取公司下,发生笔数超过20笔的账户 // 最大交易次数默认20 int maxTimes = 20; BigDecimal maxAmount = new BigDecimal("100000000"); DynamicObjectCollection transDetailData = getTransDetailData(company, beginDate, endDate,maxAmount,maxTimes); if(transDetailData == null || transDetailData.isEmpty()){ BizLog.log("没有符合条件的数据,不进行消息发送。"); return; } // 获取流水的月份,同一个月只能发送一次 String timeFlag = DateUtils.formatDateMonth(beginDate); for(DynamicObject transDetail : transDetailData){ String uniqueKey = String.join("-", WARTYPE.getValue(),timeFlag,transDetail.getString("foppunit")); if(ORM.create().exists("nckd_msgwarnlog",new QFilter("nckd_unique_key", QCP.equals,uniqueKey).toArray())){ // 消息如果已发送,就不在执行 continue; } String messageContent = getMcCenterMessage(company.getString("name"),transDetail); MessageInfo messageInfo = new MessageInfo(); messageInfo.setTitle(String.join("-",WARTYPE.getName())); messageInfo.setUserIds(receiverIdList); messageInfo.setContent(messageContent); messageInfo.setTag(WARTYPE.getName()); messageInfo.setSenderId(RequestContext.get().getCurrUserId()); messageInfo.setEntityNumber("nckd_msgwarnconfig"); messageInfo.setBizDataId(configId); String feishuMessage = MsgWarnTemplateConstant.getFeishuTemplate(WARTYPE.getName(),messageContent); MsgWarnMessageInfo warnMessageInfo = new MsgWarnMessageInfo(WARTYPE.getValue(), company.getString("name"), uniqueKey, feishuMessage, messageInfo); FeishuSendMessageUtils.sendFeishuMessage(warnMessageInfo); } } protected String getMcCenterMessage(String payerAccount , DynamicObject transDetail) { Long accountBankId = transDetail.getLong("faccountbankid"); DynamicObject accountBank = QueryServiceHelper.queryOne("bd_accountbanks", "bankaccountnumber,bank.name", new QFilter("id", QCP.equals,accountBankId).toArray()); return MsgWarnTemplateConstant.formatDailyMessage( payerAccount, accountBank.getString("bankaccountnumber"), accountBank.getString("bank.name"), transDetail.getString("foppunit"), transDetail.getString("totaltimes"), transDetail.getBigDecimal("totalamount").setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString()); } protected DynamicObjectCollection getTransDetailData(DynamicObject company , Date beginDate , Date endDate,BigDecimal maxAmount,int maxTimes){ DataSet transDetailDataSet = getTransDetailDataSet(company, beginDate, endDate,maxAmount,maxTimes); // 看报表与消息的兼容程度,再看怎么处理,暂时转成动态对象集合 return ORM.create().toPlainDynamicObjectCollection(transDetailDataSet.copy()); } protected DataSet getTransDetailDataSet(DynamicObject company , Date beginDate , Date endDate,BigDecimal maxAmount,int maxTimes){ MainEntityType dt = EntityMetadataCache.getDataEntityType(BeiBeTransDetailConstant.ENTITYID); Long defualtAccountBankId = getDefualtAccountBankId(company); String dbRouteKey = dt.getDBRouteKey(); String sumTimesSql = "SELECT faccountbankid, foppunit, COUNT(1) totaltimes, SUM(fdebitAmount) totalamount , 'times' source FROM t_bei_transdetail " + "WHERE fcompanyid = ? and faccountbankid = ? AND fbiztime > ? AND fbiztime < ? AND (HOUR(fbiztime) >= 9 AND HOUR(fbiztime) < 21) " + "AND TRIM(foppunit) <> '' AND LENGTH(foppunit) <= 4 AND fdebitAmount != 0 " + "GROUP BY faccountbankid, foppunit HAVING COUNT(1) > ?"; DataSet sumTimesDataSet = DB.queryDataSet(this.getClass().getName(), DBRoute.of(dbRouteKey), sumTimesSql, new Object[]{company.getPkValue(),defualtAccountBankId, beginDate, endDate, maxTimes}); Set oppUnitSet = CommonUtils.getFieldValue(sumTimesDataSet, "foppunit"); String sumAmountSql = "SELECT faccountbankid, foppunit, COUNT(1) totaltimes, SUM(fdebitAmount) totalamount , 'amount' source FROM t_bei_transdetail " + "WHERE fcompanyid = ? and faccountbankid = ? AND fbiztime > ? AND fbiztime < ? AND (HOUR(fbiztime) >= 9 AND HOUR(fbiztime) < 21) " + "AND TRIM(foppunit) <> '' AND LENGTH(foppunit) <= 4 AND fdebitAmount != 0 " + "GROUP BY faccountbankid, foppunit HAVING SUM(fdebitAmount) > ?"; DataSet sumAmountDataSet = DB.queryDataSet(this.getClass().getName(), DBRoute.of(dbRouteKey), sumAmountSql, new Object[]{company.getPkValue(), defualtAccountBankId,beginDate, endDate, maxAmount}); HashMap params = new HashMap<>(); params.put("var", oppUnitSet); DataSet filterSumAmountDataSet = sumAmountDataSet.filter("foppunit not in var", params); return sumTimesDataSet.union(filterSumAmountDataSet); } protected Long getDefualtAccountBankId(DynamicObject company){ DynamicObject accountBankBill = QueryServiceHelper.queryOne("bd_accountbanks", "id", new QFilter[]{ new QFilter("company", QCP.equals, company.getPkValue()), new QFilter("isdefaultpay", QCP.equals, true) }); return accountBankBill == null ? null : accountBankBill.getLong("id"); } }