摘要生成收付款单-第一次提交
This commit is contained in:
		
							parent
							
								
									c76fd12984
								
							
						
					
					
						commit
						2ab4bee1d3
					
				|  | @ -0,0 +1,369 @@ | ||||||
|  | package shjh.jhzj7.fi.fi.plugin.convert; | ||||||
|  | 
 | ||||||
|  | import kd.bos.dataentity.entity.DynamicObject; | ||||||
|  | import kd.bos.dataentity.entity.DynamicObjectCollection; | ||||||
|  | import kd.bos.entity.ExtendedDataEntity; | ||||||
|  | import kd.bos.entity.ExtendedDataEntitySet; | ||||||
|  | import kd.bos.entity.botp.plugin.AbstractConvertPlugIn; | ||||||
|  | import kd.bos.entity.botp.plugin.args.AfterConvertEventArgs; | ||||||
|  | import kd.bos.logging.Log; | ||||||
|  | import kd.bos.logging.LogFactory; | ||||||
|  | import kd.bos.orm.query.QCP; | ||||||
|  | import kd.bos.orm.query.QFilter; | ||||||
|  | import kd.bos.servicehelper.BusinessDataServiceHelper; | ||||||
|  | import kd.sdk.plugin.Plugin; | ||||||
|  | import kd.tmc.fbp.common.helper.TmcBotpHelper; | ||||||
|  | import kd.tmc.fbp.common.helper.TmcDataServiceHelper; | ||||||
|  | import kd.tmc.fbp.common.util.EmptyUtil; | ||||||
|  | import shjh.jhzj7.fi.fi.utils.StrUtils; | ||||||
|  | 
 | ||||||
|  | import java.math.BigDecimal; | ||||||
|  | import java.math.RoundingMode; | ||||||
|  | import java.util.*; | ||||||
|  | import java.util.stream.Collectors; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * 智能付款单转换插件 | ||||||
|  |  * 功能:根据摘要解析规则生成付款单分录 | ||||||
|  |  */ | ||||||
|  | public class IntelPayConvertPlugin extends AbstractConvertPlugIn implements Plugin { | ||||||
|  | 
 | ||||||
|  |     private static final Log logger = LogFactory.getLog(IntelPayConvertPlugin.class); | ||||||
|  | 
 | ||||||
|  |     // 常量定义 | ||||||
|  |     private static final String INTEL_PAY_BILL = "bei_intelpay";//被动付款入账 | ||||||
|  |     private static final String MAPPING_BILL = "shjh_lszyykm";//摘要&会计科目映射表 | ||||||
|  |     private static final String ACCOUNT_VIEW = "bd_accountview"; | ||||||
|  |     private static final String TOLERANCE_AMOUNT = "0.01"; // 金额容差 | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void afterConvert(AfterConvertEventArgs e) { | ||||||
|  |         super.afterConvert(e); | ||||||
|  | 
 | ||||||
|  |         try { | ||||||
|  |             ExtendedDataEntitySet entitySet = e.getTargetExtDataEntitySet(); | ||||||
|  |             ExtendedDataEntity[] targetEntities = entitySet.FindByEntityKey(this.getTgtMainType().getName()); | ||||||
|  | 
 | ||||||
|  |             if (targetEntities.length == 0) { | ||||||
|  |                 logger.info("未找到目标单据实体,跳过处理"); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             processConvert(targetEntities); | ||||||
|  | 
 | ||||||
|  |         } catch (Exception ex) { | ||||||
|  |             logger.error("单据转换处理过程中发生异常", ex); | ||||||
|  |             throw new RuntimeException("转换处理失败", ex); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 处理转换逻辑 | ||||||
|  |      */ | ||||||
|  |     private void processConvert(ExtendedDataEntity[] targetEntities) { | ||||||
|  |         // 1. 收集源单ID | ||||||
|  |         Set<Long> sourceBillIds = extractSourceBillIds(targetEntities); | ||||||
|  | 
 | ||||||
|  |         // 2. 批量加载源单数据 | ||||||
|  |         Map<Long, DynamicObject> sourceBillMap = loadSourceBills(sourceBillIds); | ||||||
|  |         if (sourceBillMap.isEmpty()) { | ||||||
|  |             logger.warn("未找到对应的源单数据,跳过处理"); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // 3. 批量加载映射数据 | ||||||
|  |         Set<String> mappingBillNames = collectMappingBillNames(sourceBillMap.values()); | ||||||
|  |         Map<String, List<DynamicObject>> mappingBillCache = loadMappingBills(mappingBillNames); | ||||||
|  | 
 | ||||||
|  |         // 4. 处理每个目标实体 | ||||||
|  |         for (ExtendedDataEntity targetEntity : targetEntities) { | ||||||
|  |             processSingleEntity(targetEntity, sourceBillMap, mappingBillCache); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 提取源单ID集合 | ||||||
|  |      */ | ||||||
|  |     private Set<Long> extractSourceBillIds(ExtendedDataEntity[] entities) { | ||||||
|  |         return Arrays.stream(entities) | ||||||
|  |                 .map(entity -> entity.getDataEntity().getLong("sourcebillid")) | ||||||
|  |                 .filter(Objects::nonNull) | ||||||
|  |                 .collect(Collectors.toSet()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 批量加载源单数据 | ||||||
|  |      */ | ||||||
|  |     private Map<Long, DynamicObject> loadSourceBills(Set<Long> billIds) { | ||||||
|  |         if (billIds.isEmpty()) { | ||||||
|  |             return Collections.emptyMap(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         String selectFields = "id,billno,description,rulename,company,debitamount"; | ||||||
|  |         return TmcDataServiceHelper.loadDataAndMapById(INTEL_PAY_BILL, selectFields, billIds); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 收集所有需要查询的映射单据名称 | ||||||
|  |      */ | ||||||
|  |     private Set<String> collectMappingBillNames(Collection<DynamicObject> sourceBills) { | ||||||
|  |         return sourceBills.stream() | ||||||
|  |                 .filter(this::isValidSourceBill) | ||||||
|  |                 .map(bill -> bill.getString("description")) | ||||||
|  |                 .filter(EmptyUtil::isNotEmpty) | ||||||
|  |                 .map(StrUtils::analysisSummary) | ||||||
|  |                 .filter(Objects::nonNull) | ||||||
|  |                 .flatMap(map -> map.keySet().stream()) | ||||||
|  |                 .collect(Collectors.toSet()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 批量加载映射单据 | ||||||
|  |      */ | ||||||
|  |     private Map<String, List<DynamicObject>> loadMappingBills(Set<String> mappingBillNames) { | ||||||
|  |         if (mappingBillNames.isEmpty()) { | ||||||
|  |             return Collections.emptyMap(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         QFilter[] filters = {new QFilter("name", QCP.in, mappingBillNames.toArray())}; | ||||||
|  |         DynamicObject[] mappingBills = BusinessDataServiceHelper.load( | ||||||
|  |                 MAPPING_BILL, "id,name,shjh_kjkm,shjh_rate", filters); | ||||||
|  | 
 | ||||||
|  |         return Arrays.stream(mappingBills) | ||||||
|  |                 .collect(Collectors.groupingBy( | ||||||
|  |                         bill -> bill.getString("name"), | ||||||
|  |                         Collectors.toList() | ||||||
|  |                 )); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 处理单个目标实体 | ||||||
|  |      */ | ||||||
|  |     private void processSingleEntity(ExtendedDataEntity targetEntity, | ||||||
|  |                                      Map<Long, DynamicObject> sourceBillMap, | ||||||
|  |                                      Map<String, List<DynamicObject>> mappingBillCache) { | ||||||
|  |         DynamicObject targetData = targetEntity.getDataEntity(); | ||||||
|  |         Long sourceBillId = targetData.getLong("sourcebillid"); | ||||||
|  | 
 | ||||||
|  |         if (sourceBillId == 0L) { | ||||||
|  |             logger.warn("目标单据缺少源单ID"); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         DynamicObject sourceBill = sourceBillMap.get(sourceBillId); | ||||||
|  |         if (sourceBill == null) { | ||||||
|  |             logger.warn("未找到源单数据,源单ID: {}", sourceBillId); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (!isProcessableSourceBill(sourceBill)) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         try { | ||||||
|  |             generatePaymentEntries(targetData, sourceBill, mappingBillCache); | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             logger.error("生成付款分录失败,源单: {}", sourceBill.getString("billno"), e); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 检查源单是否可处理 | ||||||
|  |      */ | ||||||
|  |     private boolean isProcessableSourceBill(DynamicObject sourceBill) { | ||||||
|  |         String billNo = sourceBill.getString("billno"); | ||||||
|  |         String description = sourceBill.getString("description"); | ||||||
|  | 
 | ||||||
|  |         // 检查摘要是否为空 | ||||||
|  |         if (EmptyUtil.isEmpty(description)) { | ||||||
|  |             logger.info("被动付款入账 {} 摘要为空,跳过处理", billNo); | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // 检查映射功能是否开启 | ||||||
|  |         if (!StrUtils.isNeedGetMapBill(sourceBill)) { | ||||||
|  |             logger.info("被动付款入账 {} 科目映射未开启,跳过处理", billNo); | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 检查源单是否有效(用于批量预处理) | ||||||
|  |      */ | ||||||
|  |     private boolean isValidSourceBill(DynamicObject sourceBill) { | ||||||
|  |         return EmptyUtil.isNotEmpty(sourceBill.getString("description")) | ||||||
|  |                 && StrUtils.isNeedGetMapBill(sourceBill); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 生成付款分录 | ||||||
|  |      */ | ||||||
|  |     private void generatePaymentEntries(DynamicObject targetData, | ||||||
|  |                                         DynamicObject sourceBill, | ||||||
|  |                                         Map<String, List<DynamicObject>> mappingBillCache) { | ||||||
|  |         String description = sourceBill.getString("description"); | ||||||
|  |         BigDecimal debitAmount = sourceBill.getBigDecimal("debitamount"); | ||||||
|  |         Long sourceBillId = sourceBill.getLong("id"); | ||||||
|  | 
 | ||||||
|  |         // 解析摘要 | ||||||
|  |         Map<String, BigDecimal> amountMapping = StrUtils.analysisSummary(description); | ||||||
|  |         if (amountMapping == null || amountMapping.isEmpty()) { | ||||||
|  |             logger.error("摘要解析失败,源单: {},摘要: {}", sourceBill.getString("billno"), description); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // 验证金额 | ||||||
|  |         if (!validateAmounts(amountMapping, debitAmount, sourceBill.getString("billno"))) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // 生成分录 | ||||||
|  |         DynamicObjectCollection paymentEntries = targetData.getDynamicObjectCollection("entry"); | ||||||
|  |         paymentEntries.clear(); | ||||||
|  | 
 | ||||||
|  |         BigDecimal allocatedAmount = createMappedEntries(paymentEntries, amountMapping, | ||||||
|  |                 sourceBill, mappingBillCache); | ||||||
|  | 
 | ||||||
|  |         // 处理剩余金额 | ||||||
|  |         handleRemainingAmount(paymentEntries, allocatedAmount, debitAmount, sourceBill); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 验证金额合理性 | ||||||
|  |      */ | ||||||
|  |     private boolean validateAmounts(Map<String, BigDecimal> amountMapping, | ||||||
|  |                                     BigDecimal debitAmount, String billNo) { | ||||||
|  |         if (EmptyUtil.isEmpty(debitAmount)) { | ||||||
|  |             logger.error("付款金额为空,源单: {}", billNo); | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         BigDecimal amountSum = StrUtils.getAmountSum(amountMapping); | ||||||
|  |         BigDecimal tolerance = new BigDecimal(TOLERANCE_AMOUNT); | ||||||
|  | 
 | ||||||
|  |         // 允许一定的金额容差 | ||||||
|  |         if (amountSum.subtract(debitAmount).abs().compareTo(tolerance) > 0) { | ||||||
|  |             logger.error("摘要金额之和与付款金额差异过大,源单: {},摘要金额: {},付款金额: {}", | ||||||
|  |                     billNo, amountSum, debitAmount); | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 创建映射分录 | ||||||
|  |      */ | ||||||
|  |     private BigDecimal createMappedEntries(DynamicObjectCollection paymentEntries, | ||||||
|  |                                            Map<String, BigDecimal> amountMapping, | ||||||
|  |                                            DynamicObject sourceBill, | ||||||
|  |                                            Map<String, List<DynamicObject>> mappingBillCache) { | ||||||
|  |         BigDecimal totalAllocated = BigDecimal.ZERO; | ||||||
|  |         int sequence = 0; | ||||||
|  | 
 | ||||||
|  |         for (Map.Entry<String, BigDecimal> entry : amountMapping.entrySet()) { | ||||||
|  |             String mappingName = entry.getKey(); | ||||||
|  |             BigDecimal amount = entry.getValue(); | ||||||
|  | 
 | ||||||
|  |             List<DynamicObject> mappingBills = mappingBillCache.get(mappingName); | ||||||
|  |             if (mappingBills == null || mappingBills.isEmpty()) { | ||||||
|  |                 logger.warn("未找到映射单据: {}", mappingName); | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             for (DynamicObject mappingBill : mappingBills) { | ||||||
|  |                 BigDecimal allocated = createSingleEntry(paymentEntries, sequence++, | ||||||
|  |                         sourceBill, mappingBill, amount); | ||||||
|  |                 totalAllocated = totalAllocated.add(allocated); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return totalAllocated; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 创建单个分录行 | ||||||
|  |      */ | ||||||
|  |     private BigDecimal createSingleEntry(DynamicObjectCollection paymentEntries, int sequence, | ||||||
|  |                                          DynamicObject sourceBill, DynamicObject mappingBill, | ||||||
|  |                                          BigDecimal originalAmount) { | ||||||
|  |         BigDecimal rate = mappingBill.getBigDecimal("shjh_rate"); | ||||||
|  |         if (rate == null) { | ||||||
|  |             rate = BigDecimal.ONE; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         String accountCode = mappingBill.getString("shjh_kjkm.number"); | ||||||
|  |         Long orgId = sourceBill.getLong("company.id"); | ||||||
|  | 
 | ||||||
|  |         DynamicObject account = loadAccount(accountCode, orgId); | ||||||
|  |         if (account == null) { | ||||||
|  |             logger.warn("未找到会计科目,编码: {},组织: {}", accountCode, orgId); | ||||||
|  |             return BigDecimal.ZERO; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         BigDecimal allocatedAmount = originalAmount.multiply(rate) | ||||||
|  |                 .setScale(2, RoundingMode.HALF_UP); | ||||||
|  | 
 | ||||||
|  |         DynamicObject newEntry = paymentEntries.addNew(); | ||||||
|  |         newEntry.set("seq", sequence); | ||||||
|  |         newEntry.set("e_sourcebillid", sourceBill.getLong("id")); | ||||||
|  |         newEntry.set("e_sourcebillentryid", sourceBill.getLong("id")); | ||||||
|  |         newEntry.set("shjh_sapkjkm", account); | ||||||
|  |         newEntry.set("e_payableamt", allocatedAmount); | ||||||
|  |         newEntry.set("e_actamt", allocatedAmount); | ||||||
|  |         newEntry.set("e_remark", sourceBill.getString("rulename")); | ||||||
|  |         newEntry.set("shjh_abstractadd", true); | ||||||
|  | 
 | ||||||
|  |         TmcBotpHelper.addLinkEntity(newEntry, "entry", "sourcebilltype", | ||||||
|  |                 sourceBill, "e_sourcebillentryid"); | ||||||
|  | 
 | ||||||
|  |         return allocatedAmount; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 加载会计科目 | ||||||
|  |      */ | ||||||
|  |     private DynamicObject loadAccount(String accountCode, Long orgId) { | ||||||
|  |         QFilter[] filters = { | ||||||
|  |                 new QFilter("number", QCP.equals, accountCode), | ||||||
|  |                 new QFilter("org", QCP.equals, orgId) | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         try { | ||||||
|  |             return BusinessDataServiceHelper.loadSingle(ACCOUNT_VIEW, filters); | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             logger.error("加载会计科目失败,编码: {},组织: {}", accountCode, orgId, e); | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 处理剩余金额 | ||||||
|  |      */ | ||||||
|  |     private void handleRemainingAmount(DynamicObjectCollection paymentEntries, | ||||||
|  |                                        BigDecimal allocatedAmount, BigDecimal debitAmount, | ||||||
|  |                                        DynamicObject sourceBill) { | ||||||
|  |         BigDecimal remaining = debitAmount.subtract(allocatedAmount); | ||||||
|  | 
 | ||||||
|  |         // 只有剩余金额超过容差时才创建分录 | ||||||
|  |         if (remaining.abs().compareTo(new BigDecimal(TOLERANCE_AMOUNT)) > 0) { | ||||||
|  |             int lastSeq = paymentEntries.size(); | ||||||
|  |             DynamicObject remainingEntry = paymentEntries.addNew(); | ||||||
|  | 
 | ||||||
|  |             remainingEntry.set("seq", lastSeq); | ||||||
|  |             remainingEntry.set("e_sourcebillid", sourceBill.getLong("id")); | ||||||
|  |             remainingEntry.set("e_sourcebillentryid", sourceBill.getLong("id")); | ||||||
|  |             remainingEntry.set("e_payableamt", remaining); | ||||||
|  |             remainingEntry.set("e_actamt", remaining); | ||||||
|  |             remainingEntry.set("shjh_abstractadd", false); | ||||||
|  | 
 | ||||||
|  |             TmcBotpHelper.addLinkEntity(remainingEntry, "entry", "sourcebilltype", | ||||||
|  |                     sourceBill, "e_sourcebillentryid"); | ||||||
|  | 
 | ||||||
|  |             logger.info("创建剩余金额分录,源单: {},剩余金额: {}", | ||||||
|  |                     sourceBill.getString("billno"), remaining); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -92,18 +92,24 @@ public class PayBillSaveOperation extends AbstractOperationServicePlugIn impleme | ||||||
| 
 | 
 | ||||||
|                             DynamicObjectCollection entrys = bill.getDynamicObjectCollection("entry");//付款单分录 |                             DynamicObjectCollection entrys = bill.getDynamicObjectCollection("entry");//付款单分录 | ||||||
|                             if (null != entrys) { |                             if (null != entrys) { | ||||||
|                                 DynamicObject entryss = entrys.get(0);//首行(被动) |                                 for (DynamicObject entryObj : entrys) { | ||||||
|                                 DynamicObject shjhYym = entryss.getDynamicObject("shjh_yym");//若原因码为空 |                                     boolean abstractLine= entryObj.getBoolean("shjh_abstractadd"); | ||||||
|  |                                     if (!abstractLine){ | ||||||
|  |                                         DynamicObject shjhYym = entryObj.getDynamicObject("shjh_yym");//若原因码为空 | ||||||
|                                         if (null == shjhYym) { |                                         if (null == shjhYym) { | ||||||
|                                             DynamicObject shjhEBizsmall = entry.getDynamicObject("shjh_e_bizsmall");//规则--业务小类 |                                             DynamicObject shjhEBizsmall = entry.getDynamicObject("shjh_e_bizsmall");//规则--业务小类 | ||||||
|                                             if (null != shjhEBizsmall) { |                                             if (null != shjhEBizsmall) { | ||||||
|                                                 shjhEBizsmall = BusinessDataServiceHelper.loadSingle(shjhEBizsmall.getPkValue(),"shjh_bizsmalltype"); |                                                 shjhEBizsmall = BusinessDataServiceHelper.loadSingle(shjhEBizsmall.getPkValue(),"shjh_bizsmalltype"); | ||||||
|                                          entryss.set("shjh_yym", shjhEBizsmall.getDynamicObject("shjh_yym"));//规则--小类--原因码 |                                                 entryObj.set("shjh_yym", shjhEBizsmall.getDynamicObject("shjh_yym"));//规则--小类--原因码 | ||||||
|                                          entryss.set("shjh_sapkjkm", shjhEBizsmall.getDynamicObject("shjh_accountview"));//规则--小类--会计科目 |                                                 entryObj.set("shjh_sapkjkm", shjhEBizsmall.getDynamicObject("shjh_accountview"));//规则--小类--会计科目 | ||||||
|  |                                                 break; | ||||||
|                                             } |                                             } | ||||||
|                                         } |                                         } | ||||||
|                                     } |                                     } | ||||||
|                                 } |                                 } | ||||||
|  |                                 //DynamicObject entryss = entrys.get(0);//首行(被动) | ||||||
|  |                             } | ||||||
|  |                         } | ||||||
|                         DynamicObject shjhCostcenter = (DynamicObject)bill.get("shjh_costcenter"); |                         DynamicObject shjhCostcenter = (DynamicObject)bill.get("shjh_costcenter"); | ||||||
|                         if (null == shjhCostcenter) { |                         if (null == shjhCostcenter) { | ||||||
|                             bill.set("shjh_costcenter", entry.getDynamicObject("shjh_e_cc")); |                             bill.set("shjh_costcenter", entry.getDynamicObject("shjh_e_cc")); | ||||||
|  |  | ||||||
|  | @ -0,0 +1,169 @@ | ||||||
|  | package shjh.jhzj7.fi.fi.utils; | ||||||
|  | 
 | ||||||
|  | import kd.bos.dataentity.entity.DynamicObject; | ||||||
|  | import kd.bos.dataentity.entity.DynamicObjectCollection; | ||||||
|  | import kd.bos.orm.query.QCP; | ||||||
|  | import kd.bos.orm.query.QFilter; | ||||||
|  | import kd.bos.servicehelper.BusinessDataServiceHelper; | ||||||
|  | import kd.tmc.fbp.common.util.EmptyUtil; | ||||||
|  | 
 | ||||||
|  | import java.math.BigDecimal; | ||||||
|  | import java.util.HashMap; | ||||||
|  | import java.util.Map; | ||||||
|  | import java.util.regex.Matcher; | ||||||
|  | import java.util.regex.Pattern; | ||||||
|  | 
 | ||||||
|  | public class StrUtils { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 解析流水摘要中的中文和金额 | ||||||
|  |      * | ||||||
|  |      * @param summary 流水摘要 | ||||||
|  |      * @return 例: | ||||||
|  |      * 缴棁,个人所得棁1212.50————>("个人所得棁",1212.50) | ||||||
|  |      * 代理国库税收收缴,11303250————>("代理国库税收收缴",11303250) | ||||||
|  |      * 缴税,生育保险费162.26|基本医疗保险费1460.34|生育保险费0.75|基本医疗保险费6.75|生育保险费1.50|基本医疗保险费13.50————>("生育保险费",164.51)、("基本医疗保险费",1480.59) | ||||||
|  |      */ | ||||||
|  |     public static Map<String, BigDecimal> analysisSummary(String summary) { | ||||||
|  |         // 1.去除summary中的空格 | ||||||
|  |         String cleanedSummary = summary.replaceAll("\\s+", ""); | ||||||
|  | 
 | ||||||
|  |         // 如果字符串为空,直接返回空map | ||||||
|  |         if (cleanedSummary.isEmpty()) { | ||||||
|  |             return new HashMap<>(); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // 2.解析税种和金额 | ||||||
|  |         Map<String, BigDecimal> result = new HashMap<>(); | ||||||
|  | 
 | ||||||
|  |         // 特殊处理"代理国库税收收缴,数字"的格式 | ||||||
|  |         Pattern specialPattern = Pattern.compile("^(代理国库税收收缴),(\\d+(?:\\.\\d+)?)$"); | ||||||
|  |         Matcher specialMatcher = specialPattern.matcher(cleanedSummary); | ||||||
|  | 
 | ||||||
|  |         if (specialMatcher.matches()) { | ||||||
|  |             String taxName = specialMatcher.group(1); | ||||||
|  |             String amountStr = specialMatcher.group(2); | ||||||
|  |             try { | ||||||
|  |                 BigDecimal amount = new BigDecimal(amountStr); | ||||||
|  |                 result.put(taxName, amount); | ||||||
|  |                 return result; | ||||||
|  |             } catch (NumberFormatException e) { | ||||||
|  |                 return null; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // 定义正则表达式匹配模式: | ||||||
|  |         // 模式1:中文税种名称 + 数字(整数或小数) | ||||||
|  |         // 模式2:中文税种名称 + 分隔符 + 数字(整数或小数) | ||||||
|  |         Pattern pattern = Pattern.compile("([\\u4e00-\\u9fa5]+)(?:[^\\d\\u4e00-\\u9fa5]*)(\\d+(?:\\.\\d+)?)"); | ||||||
|  |         Matcher matcher = pattern.matcher(cleanedSummary); | ||||||
|  | 
 | ||||||
|  |         int lastMatchEnd = 0; | ||||||
|  |         boolean validFormat = true; | ||||||
|  | 
 | ||||||
|  |         while (matcher.find()) { | ||||||
|  |             // 检查当前匹配是否紧接上一个匹配的结束位置 | ||||||
|  |             // 如果不是,说明中间有不符合格式的内容 | ||||||
|  |             if (matcher.start() != lastMatchEnd) { | ||||||
|  |                 String between = cleanedSummary.substring(lastMatchEnd, matcher.start()); | ||||||
|  |                 // 如果中间的内容包含数字,说明格式不符合要求 | ||||||
|  |                 if (between.matches(".*\\d.*")) { | ||||||
|  |                     validFormat = false; | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             String taxName = matcher.group(1); | ||||||
|  |             String amountStr = matcher.group(2); | ||||||
|  | 
 | ||||||
|  |             try { | ||||||
|  |                 BigDecimal amount = new BigDecimal(amountStr); | ||||||
|  | 
 | ||||||
|  |                 // 合并相同税种的金额 | ||||||
|  |                 if (result.containsKey(taxName)) { | ||||||
|  |                     BigDecimal existingAmount = result.get(taxName); | ||||||
|  |                     result.put(taxName, existingAmount.add(amount)); | ||||||
|  |                 } else { | ||||||
|  |                     result.put(taxName, amount); | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 lastMatchEnd = matcher.end(); | ||||||
|  |             } catch (NumberFormatException e) { | ||||||
|  |                 validFormat = false; | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // 检查是否还有剩余内容未处理 | ||||||
|  |         if (validFormat && lastMatchEnd < cleanedSummary.length()) { | ||||||
|  |             String remaining = cleanedSummary.substring(lastMatchEnd); | ||||||
|  |             // 如果剩余内容包含数字,说明格式不符合要求 | ||||||
|  |             if (remaining.matches(".*\\d.*")) { | ||||||
|  |                 validFormat = false; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // 如果格式不符合要求,返回null | ||||||
|  |         if (!validFormat || result.isEmpty()) { | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return result; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 计算Map中所有金额的总和 | ||||||
|  |      * @param amountMap 包含金额的Map,键为字符串,值为BigDecimal | ||||||
|  |      * @return 所有金额的总和,如果Map为空或null,则返回BigDecimal.ZERO | ||||||
|  |      */ | ||||||
|  |     public static BigDecimal getAmountSum(Map<String, BigDecimal> amountMap) { | ||||||
|  |         if (amountMap == null || amountMap.isEmpty()) { | ||||||
|  |             return BigDecimal.ZERO; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         BigDecimal sum = BigDecimal.ZERO; | ||||||
|  |         for (BigDecimal amount : amountMap.values()) { | ||||||
|  |             if (amount != null) { | ||||||
|  |                 sum = sum.add(amount); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return sum; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * 是否取税种&&科目映射按钮打开 | ||||||
|  |      * @return | ||||||
|  |      */ | ||||||
|  |     public static boolean isNeedGetMapBill(DynamicObject bill) { | ||||||
|  |         boolean result=false; | ||||||
|  |         String ruleName = bill.getString("rulename"); | ||||||
|  |         if (EmptyUtil.isEmpty(ruleName)){ | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         //根据适配规则名称查询适配规则 (cas_recpayrule) | ||||||
|  |         // 单据:生单/通知规则(shjh_cas_recpayrule_ext)  单据体:入账规则(entryentity) 字段:规则项名称(e_rulesname) | ||||||
|  |         QFilter q2 = new QFilter("entryentity.e_rulesname", QCP.equals, ruleName); | ||||||
|  |         QFilter q3 = new QFilter("enable", QCP.equals, "1"); | ||||||
|  |         q2 = q2.and(q3); | ||||||
|  |         DynamicObject org = bill.getDynamicObject("company"); | ||||||
|  |         if (null != org) { | ||||||
|  |             long orgid = org.getLong("id"); | ||||||
|  |             QFilter q4 = new QFilter("org_entry.u_org.id", QCP.equals, orgid); | ||||||
|  |             q2 = q2.and(q4); | ||||||
|  |         } | ||||||
|  |         DynamicObject rule = BusinessDataServiceHelper.loadSingle("cas_recpayrule", q2.toArray()); | ||||||
|  |         if (null != rule) { | ||||||
|  |             //根据适配规则携带对应分录的业务大类,业务小类,成本中心,利润中心 | ||||||
|  |             DynamicObjectCollection collection = rule.getDynamicObjectCollection("entryentity"); | ||||||
|  |             for (DynamicObject entry : collection) { | ||||||
|  |                 if (ruleName.equals(entry.getString("e_rulesname"))) { | ||||||
|  |                     result=entry.getBoolean("shjh_zykmys"); | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return result; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue