From 8c215c8be0f5076e8c95daf1b2203440ca7dfcad Mon Sep 17 00:00:00 2001
From: yxh <172933527@qq.com>
Date: 星期五, 23 十月 2026 13:42:50 +0800
Subject: [PATCH] 修改了报销校验
---
ruoyi-project/src/main/java/com/ruoyi/project/service/impl/ExpertFeeValidateService.java | 144 ++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 138 insertions(+), 6 deletions(-)
diff --git a/ruoyi-project/src/main/java/com/ruoyi/project/service/impl/ExpertFeeValidateService.java b/ruoyi-project/src/main/java/com/ruoyi/project/service/impl/ExpertFeeValidateService.java
index 6d297f4..a8be60f 100644
--- a/ruoyi-project/src/main/java/com/ruoyi/project/service/impl/ExpertFeeValidateService.java
+++ b/ruoyi-project/src/main/java/com/ruoyi/project/service/impl/ExpertFeeValidateService.java
@@ -305,6 +305,65 @@
}
log.info("[涓撳璐规牎楠宂 鍙備笌鏍¢獙鏄庣粏 {} 鏉★細{}", rows.size(), describeRows(rows));
+ // 2026-10-15锛氭寜"璐圭敤椤圭洰"鐨勬牎楠屾ā寮忥紙base_itemexpense.validate_mode锛夋媶鍒嗘槑缁嗗悗鍒嗗埆鏍¢獙
+ // 1=寮哄埗鏍¢獙锛氶噾棰濈被闂 鈫� 闃绘柇锛坋rror锛�
+ // 2=鏍¢獙鎻愰啋锛氶噾棰濈被闂 鈫� 浠呮彁閱掞紙warning锛夛紝鍏佽淇濆瓨
+ // 3=涓嶆牎楠� 锛氳烦杩囪椤圭洰鍏ㄩ儴閲戦绫昏鍒�
+ // 璇存槑锛氶噾棰濈被瑙勫垯鍏ㄩ儴鎸夐」鐩� id 鍒ゅ畾锛屽悓涓�椤圭洰鐨勬槑缁嗘墠浼氫簰鐩镐骇鐢熷悎璁$被闂锛�
+ // 鍥犳鎸夐」鐩媶鍒嗕笉浼氬奖鍝嶅悇瑙勫垯鍐呴儴閫昏緫锛涘惈璺ㄩ」鐩瘮杈冪殑瑙勫垯锛堝璇勪及鍐茬獊锛�
+ // 鍦ㄥ弻鏂归兘鏄己鍒舵ā寮忔椂浠嶇劧涓�璧峰弬涓庯紝琛屼负涓嶅彉銆�
+ List<DetailRow> forcedRows = new ArrayList<>();
+ List<DetailRow> remindRows = new ArrayList<>();
+ List<DetailRow> skippedRows = new ArrayList<>();
+ for (DetailRow row : rows) {
+ int mode = loadItemMode(row.getItemid());
+ if (mode == MODE_SKIP) {
+ skippedRows.add(row);
+ } else if (mode == MODE_REMIND) {
+ remindRows.add(row);
+ } else {
+ forcedRows.add(row);
+ }
+ }
+ log.info("[涓撳璐规牎楠宂 鏍¢獙妯″紡缁熻锛氬己鍒�={} 鎻愰啋={} 涓嶆牎楠�={}",
+ forcedRows.size(), remindRows.size(), skippedRows.size());
+
+ // 1) 寮哄埗鏍¢獙锛氭甯搁樆鏂�
+ runAmountRules(forcedRows, result);
+
+ // 2) 鏍¢獙鎻愰啋锛氬悓鏍疯窇涓�閬嶏紝浣嗘妸缁撴灉闄嶇骇涓烘彁閱掞紙涓嶉樆鏂級
+ if (!remindRows.isEmpty()) {
+ ExpertFeeCheckResult remindResult = new ExpertFeeCheckResult();
+ runAmountRules(remindRows, remindResult);
+ for (String error : remindResult.getErrors()) {
+ // 涓氬姟鏂圭‘璁ょ殑鎻愰啋鏂囨锛氶噾棰濈被闂鍦ㄣ�屾牎楠屾彁閱掋�嶆ā寮忎笅涓嶉樆鏂紝浠呮彁绀哄悗鍙户缁繚瀛�
+ result.addWarning("璇ヨ垂鐢ㄩ」瀛樺湪瓒呮爣鍑嗘儏鍐碉紝浠呬綔鎻愰啋锛屾槸鍚︾户缁繚瀛橈紵銆�" + error + "銆�");
+ }
+ if (!remindResult.getErrors().isEmpty()) {
+ log.info("[涓撳璐规牎楠宂 浠ヤ笅鏄庣粏鎵�灞為」鐩负銆屾牎楠屾彁閱掋�嶆ā寮忥紝浠呮彁閱掍笉闃绘柇锛歿}", describeRows(remindRows));
+ }
+ }
+
+ // 3) 涓嶆牎楠岋細璺宠繃閲戦绫昏鍒欙紝浠呰褰曟棩蹇楋紝渚夸簬浜嬪悗鍥炴函
+ if (!skippedRows.isEmpty()) {
+ log.info("[涓撳璐规牎楠宂 浠ヤ笅鏄庣粏鎵�灞為」鐩负銆屼笉鏍¢獙銆嶆ā寮忥紝宸茶烦杩囬噾棰濈被瑙勫垯锛歿}", describeRows(skippedRows));
+ }
+
+ // 4) 鏁版嵁璐ㄩ噺绫昏鍒欙紙閲戦涓� 0銆佹湭濉啓璐圭敤璇存槑锛夊湪涓夌妯″紡涓嬮兘寮哄埗锛�
+ // 瀵规湭鍙備笌寮哄埗鏍¢獙鐨勬槑缁嗗崟鐙窇涓�娆�"鍙煡鏁版嵁璐ㄩ噺"鐨勬鏌ワ紝閬垮厤鍑虹幇閲戦涓虹┖鐨勮剰鏁版嵁
+ checkItemStandard(remindRows, result, false);
+ checkItemStandard(skippedRows, result, false);
+
+ log.info("[涓撳璐规牎楠宂 鏍¢獙瀹屾垚 闃绘柇={} 鎻愮ず={} 闃绘柇淇℃伅={} 鎻愮ず淇℃伅={}",
+ result.getErrors().size(), result.getWarnings().size(),
+ result.getErrors(), result.getWarnings());
+ return result;
+ }
+
+ /**
+ * 閲戦绫昏鍒欙紙鍙�"鏍¢獙妯″紡"褰卞搷锛夛細鍚堣闄愰銆丒COM銆佸姪鎵嬨�佹墜鏈銆佽瘎浼板啿绐併�佽垂鐢ㄦ爣鍑嗐�佸櫒瀹樿幏鍙栧姞鎴愩��
+ */
+ private void runAmountRules(List<DetailRow> rows, ExpertFeeCheckResult result) {
// 瑙勫垯 1~4銆�7~9锛氬悎璁¢檺棰濈被锛堥樆鏂級锛屽叏閮ㄦ寜椤圭洰 id 鍒ゅ畾
checkSingleItemLimit(rows, resolveItemIds(CFG_ITEM_ORGAN_MAINTAIN, "鎹愮尞鍖婚櫌鍣ㄥ畼鍔熻兘缁存姢璐�", FALLBACK_ORGAN_MAINTAIN),
false,
@@ -321,13 +380,8 @@
// 瑙勫垯 5锛氫粎鎻愮ず锛涘熀鏈鍒欎笌鍣ㄥ畼鑾峰彇鍔犳垚锛氱‖鎷︽埅
checkAssessConflict(rows, result);
- checkItemStandard(rows, result);
+ checkItemStandard(rows, result, true);
checkDoctorOrganSecond(rows, result);
-
- log.info("[涓撳璐规牎楠宂 鏍¢獙瀹屾垚 闃绘柇={} 鎻愮ず={} 闃绘柇淇℃伅={} 鎻愮ず淇℃伅={}",
- result.getErrors().size(), result.getWarnings().size(),
- result.getErrors(), result.getWarnings());
- return result;
}
/** 鎶婂弬涓庢牎楠岀殑鏄庣粏鎷兼垚涓�琛岋紝渚夸簬鎺掓煡銆屼负浠�涔堟病鎷︿綇銆嶏紙閲戦銆侀」鐩�佸満鏅竴鐩簡鐒讹級 */
@@ -626,6 +680,18 @@
* 鑻ユ嬁绋庡墠閲戦锛堝惈绋庡姞浠峰悗鐨勫�硷級鍘绘瘮锛屼細鎶婂ぇ閲忔甯稿崟鎹鍒や负瓒呮爣鍑嗭紙瀹炴祴 3168 缁� vs 162 缁勶級銆�
*/
private void checkItemStandard(List<DetailRow> rows, ExpertFeeCheckResult result) {
+ checkItemStandard(rows, result, true);
+ }
+
+ /**
+ * 璐圭敤鏍囧噯鏍¢獙銆�
+ *
+ * @param amountCheck {@code true}=瀹屾暣鏍¢獙锛堝惈閲戦绫昏鍒欙紝鍙楅」鐩牎楠屾ā寮忓奖鍝嶏級锛�
+ * {@code false}=鍙煡鏁版嵁璐ㄩ噺锛堥噾棰濅负 0銆佹湭濉啓璐圭敤璇存槑锛夛紝
+ * 鐢ㄤ簬銆屾牎楠屾彁閱� / 涓嶆牎楠屻�嶆ā寮忎笅瀵规湭鍙備笌寮哄埗鏍¢獙鐨勬槑缁嗗仛鍏滃簳寮哄埗锛�
+ * 閬垮厤鍑虹幇閲戦涓虹┖鐨勮剰鏁版嵁銆�
+ */
+ private void checkItemStandard(List<DetailRow> rows, ExpertFeeCheckResult result, boolean amountCheck) {
Map<String, List<DetailRow>> groups = new LinkedHashMap<>();
Map<String, BigDecimal> groupStandards = new LinkedHashMap<>();
Map<String, String> groupLabels = new LinkedHashMap<>();
@@ -644,9 +710,17 @@
}
BigDecimal standard = loadItemStandard(row.getItemid(), scope);
if (standard == null) {
+ if (!amountCheck) {
+ // 銆屾湭鎵惧埌璐圭敤鏍囧噯銆嶅睘閲戦绫婚棶棰橈紝鎸夐」鐩牎楠屾ā寮忓鐞�
+ continue;
+ }
result.addError(String.format(
"%s鏈壘鍒板搴旂殑璐圭敤鏍囧噯锛堥」鐩甶d=%s锛岃垂鐢ㄨ鏄�=%s锛夛紝涓嶅厑璁告姤閿�锛岃鑱旂郴绠$悊鍛樼淮鎶よ垂鐢ㄦ爣鍑�",
itemLabel(row), row.getItemid(), scope));
+ continue;
+ }
+ if (!amountCheck) {
+ // 鍙煡鏁版嵁璐ㄩ噺锛氫笉鍐嶅仛璐圭敤鏍囧噯姣旇緝涓庨噸澶嶅綍鍏ユ彁閱�
continue;
}
String key = groupKey(row, scope);
@@ -765,6 +839,64 @@
*
* @return 鎵句笉鍒版椂杩斿洖 {@code null}锛岃皟鐢ㄦ柟鎸夈�屽尮閰嶄笉鍒版爣鍑嗐�嶉樆鏂�
*/
+ /** 鏍¢獙妯″紡锛氬己鍒舵牎楠岋紙閲戦绫婚棶棰樹笉閫氳繃鍒欎笉鑳戒繚瀛橈級 */
+ private static final int MODE_FORCE = 1;
+ /** 鏍¢獙妯″紡锛氭牎楠屾彁閱掞紙閲戦绫婚棶棰樹粎鎻愰啋锛屽厑璁镐繚瀛橈級 */
+ private static final int MODE_REMIND = 2;
+ /** 鏍¢獙妯″紡锛氫笉鏍¢獙锛堣烦杩囪椤圭洰鐨勯噾棰濈被瑙勫垯锛� */
+ private static final int MODE_SKIP = 3;
+
+ /** 椤圭洰鏍¢獙妯″紡缂撳瓨锛�60 绉掞級锛宬ey = itemid */
+ private final Map<Long, Integer> itemModeCache = new java.util.concurrent.ConcurrentHashMap<>();
+ private final Map<Long, Long> itemModeExpireCache = new java.util.concurrent.ConcurrentHashMap<>();
+
+ /**
+ * 璇诲彇璐圭敤椤圭洰鐨勬牎楠屾ā寮忥紙{@code base_itemexpense.validate_mode}锛夛紝缂撳瓨 60 绉掋��
+ *
+ * <p>璇讳笉鍒般�佸彇鍊奸潪娉曟垨鏌ヨ寮傚父鏃�**涓�寰嬫寜銆屽己鍒舵牎楠屻�嶅鐞�**锛�
+ * 淇濊瘉涓嶄細鍥犱负寮�鍏宠涓嶅埌鑰屾斁鏉炬牎楠岋紙瀹佸彲澶氭嫤锛屼笉鍙紡鎷︼級銆�
+ */
+ private int loadItemMode(Long itemid) {
+ if (itemid == null) {
+ return MODE_FORCE;
+ }
+ long now = System.currentTimeMillis();
+ Integer cached = itemModeCache.get(itemid);
+ Long expireAt = itemModeExpireCache.get(itemid);
+ if (cached != null && expireAt != null && expireAt > now) {
+ return cached;
+ }
+ int mode = MODE_FORCE;
+ try {
+ // 2026-10-15锛堜慨澶嶏級锛氫笉鑳界敤 wrapper.select("ValidateMode") + selectMaps 鍙栬繖涓�鍒楋紝涓ゅ閮戒細璁╂ā寮忓彇涓嶅埌锛�
+ // 鈶� 瀛楃涓插垪鍚嶄細琚� MyBatis-Plus 鍘熸牱鎷艰繘 SELECT锛岃�岀湡瀹炲垪鍚嶆槸 validate_mode锛�
+ // MySQL 鐩存帴鎶� Unknown column 'ValidateMode'锛屽紓甯歌涓嬮潰鐨� catch 鍚炴帀鍚庢案杩滃洖钀姐�屽己鍒舵牎楠屻�嶏紱
+ // 鈶� 鍗充娇鎶婂垪鍚嶆敼鎴� validate_mode锛宻electMaps 杩斿洖鐨� Map key 涔熸槸鍘熷鍒楁爣绛撅紙validate_mode锛�
+ // 涓嶄細杞垚椹煎嘲锛夛紝涓� "validatemode" 鍖归厤涓嶄笂锛屾ā寮忎緷鐒跺彇涓嶅埌銆�
+ // 鏀逛负涓庡悓绫� loadItemStandards 涓�鑷寸殑瀹炰綋鏄犲皠鍐欐硶锛堢粡瀹炰綋瀛楁 validateMode 鏄犲皠鍒板垪 validate_mode锛夈��
+ QueryWrapper<BaseItemexpense> wrapper = new QueryWrapper<>();
+ wrapper.eq("ItemId", itemid);
+ wrapper.eq("UseState", "1");
+ wrapper.apply("del_flag = 0");
+ wrapper.orderByAsc("Id");
+ List<BaseItemexpense> list = baseItemexpenseMapper.selectList(wrapper);
+ if (!CollectionUtils.isEmpty(list) && list.get(0) != null
+ && list.get(0).getValidateMode() != null) {
+ mode = list.get(0).getValidateMode();
+ }
+ if (mode != MODE_FORCE && mode != MODE_REMIND && mode != MODE_SKIP) {
+ log.warn("[涓撳璐规牎楠宂 椤圭洰鏍¢獙妯″紡鍙栧�奸潪娉曪紝鎸夊己鍒舵牎楠屽鐞嗭紝itemid={}锛寁alidate_mode={}", itemid, mode);
+ mode = MODE_FORCE;
+ }
+ } catch (Exception e) {
+ log.error("[涓撳璐规牎楠宂 璇诲彇椤圭洰鏍¢獙妯″紡澶辫触锛屾寜寮哄埗鏍¢獙澶勭悊锛宨temid={}", itemid, e);
+ mode = MODE_FORCE;
+ }
+ itemModeCache.put(itemid, mode);
+ itemModeExpireCache.put(itemid, now + ITEM_EXPENSE_CACHE_MILLIS);
+ return mode;
+ }
+
private BigDecimal loadItemStandard(Long itemid, String scope) {
return loadItemStandards(itemid).get(scope);
}
--
Gitblit v1.9.3