摘要生成收付款单-第一次提交
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");//付款单分录 | ||||
|                             if (null != entrys) { | ||||
|                                 DynamicObject entryss = entrys.get(0);//首行(被动) | ||||
|                                 DynamicObject shjhYym = entryss.getDynamicObject("shjh_yym");//若原因码为空 | ||||
|                                 for (DynamicObject entryObj : entrys) { | ||||
|                                     boolean abstractLine= entryObj.getBoolean("shjh_abstractadd"); | ||||
|                                     if (!abstractLine){ | ||||
|                                         DynamicObject shjhYym = entryObj.getDynamicObject("shjh_yym");//若原因码为空 | ||||
|                                         if (null == shjhYym) { | ||||
|                                             DynamicObject shjhEBizsmall = entry.getDynamicObject("shjh_e_bizsmall");//规则--业务小类 | ||||
|                                             if (null != shjhEBizsmall) { | ||||
|                                                 shjhEBizsmall = BusinessDataServiceHelper.loadSingle(shjhEBizsmall.getPkValue(),"shjh_bizsmalltype"); | ||||
|                                          entryss.set("shjh_yym", shjhEBizsmall.getDynamicObject("shjh_yym"));//规则--小类--原因码 | ||||
|                                          entryss.set("shjh_sapkjkm", shjhEBizsmall.getDynamicObject("shjh_accountview"));//规则--小类--会计科目 | ||||
|                                                 entryObj.set("shjh_yym", shjhEBizsmall.getDynamicObject("shjh_yym"));//规则--小类--原因码 | ||||
|                                                 entryObj.set("shjh_sapkjkm", shjhEBizsmall.getDynamicObject("shjh_accountview"));//规则--小类--会计科目 | ||||
|                                                 break; | ||||
|                                             } | ||||
|                                         } | ||||
|                                     } | ||||
|                                 } | ||||
|                                 //DynamicObject entryss = entrys.get(0);//首行(被动) | ||||
|                             } | ||||
|                         } | ||||
|                         DynamicObject shjhCostcenter = (DynamicObject)bill.get("shjh_costcenter"); | ||||
|                         if (null == shjhCostcenter) { | ||||
|                             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