|
@@ -1296,7 +1296,8 @@ public class ExpenseOrderServiceImpl implements ExpenseOrderService {
|
|
|
for (int i = 0; i < orderItems.size(); i++) {
|
|
for (int i = 0; i < orderItems.size(); i++) {
|
|
|
ExpenseOrderItemDO expenseOrderItemDO = orderItems.get(i);
|
|
ExpenseOrderItemDO expenseOrderItemDO = orderItems.get(i);
|
|
|
orderActualAmount = orderActualAmount.add(expenseOrderItemDO.getTotalAmount());
|
|
orderActualAmount = orderActualAmount.add(expenseOrderItemDO.getTotalAmount());
|
|
|
- setExpenseOrderType(expenseOrderItemDO);
|
|
|
|
|
|
|
+ // 若明细未带 type,则根据“费用标识类型”字典的关键词(label/remark)从名称中推断 type
|
|
|
|
|
+ setExpenseOrderType(expenseOrderItemDO, dictDataDOList);
|
|
|
|
|
|
|
|
if (identificationTypeMap.containsKey(expenseOrderItemDO.getType())) {
|
|
if (identificationTypeMap.containsKey(expenseOrderItemDO.getType())) {
|
|
|
BigDecimal add = expenseOrderItemDO.getTotalAmount()
|
|
BigDecimal add = expenseOrderItemDO.getTotalAmount()
|
|
@@ -3579,105 +3580,95 @@ public class ExpenseOrderServiceImpl implements ExpenseOrderService {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 设置费用项目详情类型,临时使用
|
|
|
|
|
- * @param expenseOrderItemDO
|
|
|
|
|
|
|
+ * 设置费用项目详情类型(从字典动态匹配)。
|
|
|
|
|
+ *
|
|
|
|
|
+ * <p>背景:历史数据中部分账单明细未写入 type(为 null/0),导出时需要按分类汇总;
|
|
|
|
|
+ * 以前通过 if/else 写死匹配规则,新增一种类型就要改代码。
|
|
|
|
|
+ *
|
|
|
|
|
+ * <p>当前策略:基于字典 {@code fee_identification_type} 的配置进行匹配:
|
|
|
|
|
+ * <ul>
|
|
|
|
|
+ * <li>{@link DictDataDO#getValue()}:目标 type(必须是数字字符串)</li>
|
|
|
|
|
+ * <li>{@link DictDataDO#getLabel()}:匹配关键词(同时也是导出表头)</li>
|
|
|
|
|
+ * <li>{@link DictDataDO#getRemark()}:可选,同义词/额外关键词,支持用 ,,;;| 分隔</li>
|
|
|
|
|
+ * </ul>
|
|
|
|
|
+ *
|
|
|
|
|
+ * <p>匹配字段:优先在 {@code itemName} 命中,其次 {@code itemCategoryName}。
|
|
|
|
|
+ * 另外对包含“标准/类型”的关键词,会自动尝试去掉“标准/类型”后的匹配,减少配置成本。
|
|
|
*/
|
|
*/
|
|
|
- private void setExpenseOrderType(ExpenseOrderItemDO expenseOrderItemDO){
|
|
|
|
|
- if(expenseOrderItemDO.getType() != null && expenseOrderItemDO.getType() != 0){
|
|
|
|
|
|
|
+ private void setExpenseOrderType(ExpenseOrderItemDO expenseOrderItemDO, List<DictDataDO> identificationTypeDictList) {
|
|
|
|
|
+ // 明细已带 type 时不处理,避免覆盖正确值
|
|
|
|
|
+ if (expenseOrderItemDO.getType() != null && expenseOrderItemDO.getType() != 0) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ // 无字典配置时无法推断
|
|
|
|
|
+ if (CollectionUtil.isEmpty(identificationTypeDictList)) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
- if(expenseOrderItemDO.getItemName().contains("气垫床管理费")){
|
|
|
|
|
- expenseOrderItemDO.setType(23);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemName().contains("预备金")){
|
|
|
|
|
- expenseOrderItemDO.setType(22);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemName().contains("居家服务费")){
|
|
|
|
|
- expenseOrderItemDO.setType(21);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemName().contains("陪护费")){
|
|
|
|
|
- expenseOrderItemDO.setType(20);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemName().contains("炖汤票")){
|
|
|
|
|
- expenseOrderItemDO.setType(19);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemName().contains("匀浆膳")){
|
|
|
|
|
- expenseOrderItemDO.setType(18);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemName().contains("电器管理费")){
|
|
|
|
|
- expenseOrderItemDO.setType(17);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemName().contains("洗衣")){
|
|
|
|
|
- expenseOrderItemDO.setType(16);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemName().contains("善后处理费")){
|
|
|
|
|
- expenseOrderItemDO.setType(15);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemName().contains("注射费")){
|
|
|
|
|
- expenseOrderItemDO.setType(14);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemName().contains("西药费")){
|
|
|
|
|
- expenseOrderItemDO.setType(13);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemName().contains("材料费")){
|
|
|
|
|
- expenseOrderItemDO.setType(12);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemName().contains("药品管理费") || expenseOrderItemDO.getItemName().contains("药品保管费")){
|
|
|
|
|
- expenseOrderItemDO.setType(11);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemName().contains("治疗费")){
|
|
|
|
|
- expenseOrderItemDO.setType(10);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemName().contains("护理用品费")){
|
|
|
|
|
- expenseOrderItemDO.setType(9);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemName().contains("一次性费用")){
|
|
|
|
|
- expenseOrderItemDO.setType(8);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemName().contains("服务标准")){
|
|
|
|
|
- expenseOrderItemDO.setType(7);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemName().contains("水电费")){
|
|
|
|
|
- expenseOrderItemDO.setType(6);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemName().contains("试住费用")){
|
|
|
|
|
- expenseOrderItemDO.setType(5);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemName().contains("押金")){
|
|
|
|
|
- expenseOrderItemDO.setType(4);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemName().contains("餐饮标准")){
|
|
|
|
|
- expenseOrderItemDO.setType(3);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemName().contains("护理标准")){
|
|
|
|
|
- expenseOrderItemDO.setType(2);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemName().contains("床位类型")){
|
|
|
|
|
- expenseOrderItemDO.setType(1);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemCategoryName().contains("气垫床管理费")){
|
|
|
|
|
- expenseOrderItemDO.setType(23);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemCategoryName().contains("预备金")){
|
|
|
|
|
- expenseOrderItemDO.setType(22);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemCategoryName().contains("居家服务费")){
|
|
|
|
|
- expenseOrderItemDO.setType(21);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemCategoryName().contains("陪护费")){
|
|
|
|
|
- expenseOrderItemDO.setType(20);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemCategoryName().contains("炖汤票")){
|
|
|
|
|
- expenseOrderItemDO.setType(19);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemCategoryName().contains("匀浆膳")){
|
|
|
|
|
- expenseOrderItemDO.setType(18);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemCategoryName().contains("电器管理费")){
|
|
|
|
|
- expenseOrderItemDO.setType(17);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemCategoryName().contains("洗衣")){
|
|
|
|
|
- expenseOrderItemDO.setType(16);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemCategoryName().contains("善后处理费")){
|
|
|
|
|
- expenseOrderItemDO.setType(15);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemCategoryName().contains("注射费")){
|
|
|
|
|
- expenseOrderItemDO.setType(14);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemCategoryName().contains("西药费")){
|
|
|
|
|
- expenseOrderItemDO.setType(13);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemCategoryName().contains("材料费")){
|
|
|
|
|
- expenseOrderItemDO.setType(12);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemCategoryName().contains("药品管理费") || expenseOrderItemDO.getItemCategoryName().contains("药品保管费")){
|
|
|
|
|
- expenseOrderItemDO.setType(11);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemCategoryName().contains("治疗费")){
|
|
|
|
|
- expenseOrderItemDO.setType(10);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemCategoryName().contains("护理用品费")){
|
|
|
|
|
- expenseOrderItemDO.setType(9);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemCategoryName().contains("一次性费用")){
|
|
|
|
|
- expenseOrderItemDO.setType(8);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemCategoryName().contains("服务")){
|
|
|
|
|
- expenseOrderItemDO.setType(7);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemCategoryName().contains("水电费")){
|
|
|
|
|
- expenseOrderItemDO.setType(6);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemCategoryName().contains("试住费用")){
|
|
|
|
|
- expenseOrderItemDO.setType(5);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemCategoryName().contains("押金")){
|
|
|
|
|
- expenseOrderItemDO.setType(4);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemCategoryName().contains("餐饮")){
|
|
|
|
|
- expenseOrderItemDO.setType(3);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemCategoryName().contains("护理")){
|
|
|
|
|
- expenseOrderItemDO.setType(2);
|
|
|
|
|
- }else if(expenseOrderItemDO.getItemCategoryName().contains("床位")){
|
|
|
|
|
- expenseOrderItemDO.setType(1);
|
|
|
|
|
|
|
+
|
|
|
|
|
+ String itemName = StringUtils.defaultString(expenseOrderItemDO.getItemName());
|
|
|
|
|
+ String itemCategoryName = StringUtils.defaultString(expenseOrderItemDO.getItemCategoryName());
|
|
|
|
|
+
|
|
|
|
|
+ for (DictDataDO dictDataDO : identificationTypeDictList) {
|
|
|
|
|
+ if (dictDataDO == null) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (StringUtils.isBlank(dictDataDO.getValue())) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ // 收集候选关键词:label + remark(分隔后)
|
|
|
|
|
+ List<String> keywords = new ArrayList<>();
|
|
|
|
|
+ if (StringUtils.isNotBlank(dictDataDO.getLabel())) {
|
|
|
|
|
+ keywords.add(dictDataDO.getLabel());
|
|
|
|
|
+ }
|
|
|
|
|
+ if (StringUtils.isNotBlank(dictDataDO.getRemark())) {
|
|
|
|
|
+ String[] remarkKeywords = dictDataDO.getRemark().split("[,,;;|]");
|
|
|
|
|
+ for (String keyword : remarkKeywords) {
|
|
|
|
|
+ if (StringUtils.isNotBlank(keyword)) {
|
|
|
|
|
+ keywords.add(keyword.trim());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 扩展关键词:自动补充去掉“标准/类型”后的版本(例如“服务标准”->“服务”)
|
|
|
|
|
+ List<String> expandedKeywords = new ArrayList<>(keywords.size() * 2);
|
|
|
|
|
+ for (String keyword : keywords) {
|
|
|
|
|
+ if (StringUtils.isBlank(keyword)) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ expandedKeywords.add(keyword);
|
|
|
|
|
+ if (keyword.contains("标准")) {
|
|
|
|
|
+ expandedKeywords.add(keyword.replace("标准", ""));
|
|
|
|
|
+ }
|
|
|
|
|
+ if (keyword.contains("类型")) {
|
|
|
|
|
+ expandedKeywords.add(keyword.replace("类型", ""));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ expandedKeywords.removeIf(StringUtils::isBlank);
|
|
|
|
|
+ // 先匹配更长的关键词,避免短关键词抢占(例如“护理”比“护理用品费”更容易误命中)
|
|
|
|
|
+ expandedKeywords.sort((a, b) -> Integer.compare(b.length(), a.length()));
|
|
|
|
|
+
|
|
|
|
|
+ boolean matched = false;
|
|
|
|
|
+ for (String keyword : expandedKeywords) {
|
|
|
|
|
+ if (StringUtils.isNotBlank(itemName) && itemName.contains(keyword)) {
|
|
|
|
|
+ matched = true;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (StringUtils.isNotBlank(itemCategoryName) && itemCategoryName.contains(keyword)) {
|
|
|
|
|
+ matched = true;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!matched) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 命中后写入 type,供后续汇总统计使用
|
|
|
|
|
+ expenseOrderItemDO.setType(Integer.valueOf(dictDataDO.getValue()));
|
|
|
|
|
+ return;
|
|
|
|
|
+ } catch (NumberFormatException ignored) {
|
|
|
|
|
+ // value 不是数字时忽略该字典项,继续尝试下一项
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|