From d5bbd17a1428811da046ec3be3c0cc943a7ae059 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期三, 17 六月 2026 15:13:20 +0800
Subject: [PATCH] ai数据自动生成
---
docs/mock_data_check.md | 22
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java | 5
src/main/java/com/ruoyi/project/system/mapper/SysUserMapper.java | 5
src/main/java/com/ruoyi/common/utils/DateUtils.java | 21
src/main/java/com/ruoyi/mock/service/impl/DataCheckServiceImpl.java | 136 ++++
src/main/java/com/ruoyi/mock/prompt/MockDataPrompt.java | 229 ++++---
src/main/resources/mapper/system/SysUserMapper.xml | 24
src/main/resources/application-dev.yml | 2
src/main/java/com/ruoyi/project/system/domain/SysUser.java | 78 +-
src/main/java/com/ruoyi/mock/service/impl/DataGenerateServiceImpl.java | 1205 +++++++++++++++++++++++++++++++++++++++-
10 files changed, 1,513 insertions(+), 214 deletions(-)
diff --git a/docs/mock_data_check.md b/docs/mock_data_check.md
index e423eb5..8c67159 100644
--- a/docs/mock_data_check.md
+++ b/docs/mock_data_check.md
@@ -14,11 +14,11 @@
| 鍙傛暟 | 绫诲瀷 | 蹇呭~ | 璇存槑 |
|------|------|------|------|
-| modules | List\<String\> | 鏄� | 瑕佹娴嬬殑妯″潡鍒楄〃锛屽彲閫夊�硷細sales锛堥攢鍞級銆乸urchase锛堥噰璐級銆乹uality锛堣川閲忥級 |
+| modules | List\<String\> | 鏄� | 瑕佹娴嬬殑妯″潡鍒楄〃锛屽彲閫夊�硷細sales锛堥攢鍞級銆乸urchase锛堥噰璐級銆乹uality锛堣川閲忥級銆乸roduction锛堢敓浜э級 |
璇锋眰浣撶ず渚嬶細
```json
-{ "modules": ["sales", "purchase", "quality"] }
+{ "modules": ["sales", "purchase", "quality", "production"] }
```
**鍝嶅簲锛�**
@@ -68,6 +68,20 @@
| 渚涘簲鍟嗘暟鎹� | 1 | 缂哄皯渚涘簲鍟嗘暟鎹紝璇峰厛鍦ㄣ�愬熀纭�鏁版嵁-渚涘簲鍟嗙鐞嗐�戜腑娣诲姞鑷冲皯1鏉′緵搴斿晢 |
| 閲囪喘瀹℃壒妯℃澘 | 1 | 缂哄皯閲囪喘瀹℃壒妯℃澘锛岃鍏堝湪銆愮郴缁熺鐞�-瀹℃壒妯℃澘銆戜腑鍒涘缓閲囪喘瀹℃壒妯℃澘 |
+### 鐢熶骇妯″潡 (production)
+| 妫�娴嬮」 | 鏈�浣庢暟閲� | 鏈�氳繃鎻愮ず |
+|--------|----------|------------|
+| 浜у搧鏁版嵁 | 1 | 缂哄皯浜у搧鏁版嵁锛岃鍏堝湪銆愬熀纭�鏁版嵁-浜у搧绠$悊銆戜腑娣诲姞鑷冲皯1鏉′骇鍝� |
+| 浜у搧瑙勬牸 | 1 | 缂哄皯浜у搧瑙勬牸锛岃鍏堝湪銆愬熀纭�鏁版嵁-浜у搧绠$悊銆戜腑涓轰骇鍝佹坊鍔犺鏍煎瀷鍙� |
+| 宸ュ簭 | 1 | 缂哄皯宸ュ簭锛岃鍏堝湪銆愬伐鑹鸿璁�-宸ュ簭绠$悊銆戜腑鍒涘缓宸ュ簭 |
+| BOM | 1 | 缂哄皯BOM锛岃鍏堝湪銆愬伐鑹鸿璁�-BOM绠$悊銆戜腑鍒涘缓BOM |
+| BOM浜у搧缁撴瀯 | 1 | 缂哄皯BOM浜у搧缁撴瀯锛岃鍏堝湪銆愬伐鑹鸿璁�-BOM绠$悊銆戜腑涓築OM娣诲姞浜у搧缁撴瀯鑺傜偣 |
+| 宸ヨ壓璺嚎 | 1 | 缂哄皯宸ヨ壓璺嚎锛岃鍏堝湪銆愬伐鑹鸿璁�-宸ヨ壓璺嚎銆戜腑鍒涘缓宸ヨ壓璺嚎 |
+| 宸ヨ壓璺嚎宸ュ簭 | 1 | 缂哄皯宸ヨ壓璺嚎宸ュ簭锛岃鍏堝湪銆愬伐鑹鸿璁�-宸ヨ壓璺嚎銆戜腑涓哄伐鑹鸿矾绾挎坊鍔犲伐搴� |
+| 浜у搧-宸ヨ壓璺嚎鍏宠仈 | 鈮�1 | 閮ㄥ垎浜у搧瑙勬牸鏈叧鑱斿伐鑹鸿矾绾匡紝璇峰厛鍦ㄣ�愬伐鑹鸿璁�-宸ヨ壓璺嚎銆戜腑涓轰骇鍝佽鏍煎垱寤哄伐鑹鸿矾绾� |
+| 宸ヨ壓璺嚎-宸ュ簭鍏宠仈 | 鈮�1 | 閮ㄥ垎宸ヨ壓璺嚎鏈坊鍔犲伐搴忥紝璇峰厛鍦ㄣ�愬伐鑹鸿璁�-宸ヨ壓璺嚎銆戜腑涓哄伐鑹鸿矾绾挎坊鍔犲伐搴� |
+| BOM-浜у搧缁撴瀯鍏宠仈 | 鈮�1 | 閮ㄥ垎BOM鏈坊鍔犱骇鍝佺粨鏋勶紝璇峰厛鍦ㄣ�愬伐鑹鸿璁�-BOM绠$悊銆戜腑涓築OM娣诲姞浜у搧缁撴瀯鑺傜偣 |
+
### 璐ㄩ噺妯″潡 (quality)
| 妫�娴嬮」 | 鏈�浣庢暟閲� | 鏈�氳繃鎻愮ず |
|--------|----------|------------|
@@ -91,6 +105,7 @@
<el-checkbox label="sales">閿�鍞ā鍧�</el-checkbox>
<el-checkbox label="purchase">閲囪喘妯″潡</el-checkbox>
<el-checkbox label="quality">璐ㄩ噺妯″潡</el-checkbox>
+ <el-checkbox label="production">鐢熶骇妯″潡</el-checkbox>
</el-checkbox-group>
<el-button type="primary" @click="handleCheck" :loading="checking">
寮�濮嬫娴�
@@ -128,7 +143,7 @@
```js
data() {
return {
- selectedModules: ['sales', 'purchase', 'quality'],
+ selectedModules: ['sales', 'purchase', 'quality', 'production'],
checking: false,
checkResult: null,
}
@@ -165,3 +180,4 @@
- 妫�娴嬩粎鍋氬彧璇绘煡璇紝涓嶅啓鍏ヤ换浣曟暟鎹�
- 妯″潡鍙傛暟涓虹┖鏁扮粍鏃惰繑鍥炵┖妫�娴嬪垪琛�
- 寤鸿鍦ㄦ暟鎹ā鎷熷紑濮嬪墠鍏堣皟鐢ㄦ鎺ュ彛纭鍩虹鏁版嵁灏辩华
+- 鐢熶骇妯″潡闄や簡妫�娴嬫暟鎹噺锛岃繕浼氭娴嬪叧鑱旀�э紙浜у搧-宸ヨ壓璺嚎銆佸伐鑹鸿矾绾�-宸ュ簭銆丅OM-浜у搧缁撴瀯锛夛紝纭繚宸ヨ壓璁捐鏁版嵁瀹屾暣
diff --git a/src/main/java/com/ruoyi/common/utils/DateUtils.java b/src/main/java/com/ruoyi/common/utils/DateUtils.java
index 0fa7e5a..f0b14f9 100644
--- a/src/main/java/com/ruoyi/common/utils/DateUtils.java
+++ b/src/main/java/com/ruoyi/common/utils/DateUtils.java
@@ -3,17 +3,13 @@
import java.lang.management.ManagementFactory;
import java.text.ParseException;
import java.text.SimpleDateFormat;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.LocalTime;
-import java.time.ZoneId;
-import java.time.ZonedDateTime;
+import java.time.*;
import java.util.Date;
import org.apache.commons.lang3.time.DateFormatUtils;
/**
* 鏃堕棿宸ュ叿绫�
- *
+ *
* @author ruoyi
*/
public class DateUtils extends org.apache.commons.lang3.time.DateUtils
@@ -29,13 +25,13 @@
public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
private static String[] parsePatterns = {
- "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
+ "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
"yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
"yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
/**
* 鑾峰彇褰撳墠Date鍨嬫棩鏈�
- *
+ *
* @return Date() 褰撳墠鏃ユ湡
*/
public static Date getNowDate()
@@ -45,16 +41,15 @@
public static LocalDate toLocalDate(Date date){
if(date == null) return LocalDate.now();
- // 2. 鎸囧畾鍥哄畾鏃跺尯杞崲锛堝涓滃叓鍖篣TC+8銆乁TC闆舵椂鍖猴級
- return date.toInstant()
- .atZone(ZoneId.of("Asia/Shanghai")) // 涓滃叓鍖猴紙鍖椾含/涓婃捣鏃跺尯锛�
- // .atZone(ZoneId.of("UTC")) // 鍙�夛細UTC闆舵椂鍖�
+ // java.sql.Date.toInstant() 浼氭姏 UnsupportedOperationException锛岄渶鍏堣浆涓� java.util.Date
+ Instant instant = new java.util.Date(date.getTime()).toInstant();
+ return instant.atZone(ZoneId.of("Asia/Shanghai"))
.toLocalDate();
}
/**
* 鑾峰彇褰撳墠鏃ユ湡, 榛樿鏍煎紡涓簓yyy-MM-dd
- *
+ *
* @return String
*/
public static String getDate()
diff --git a/src/main/java/com/ruoyi/mock/prompt/MockDataPrompt.java b/src/main/java/com/ruoyi/mock/prompt/MockDataPrompt.java
index 6e81263..2743445 100644
--- a/src/main/java/com/ruoyi/mock/prompt/MockDataPrompt.java
+++ b/src/main/java/com/ruoyi/mock/prompt/MockDataPrompt.java
@@ -1,6 +1,9 @@
package com.ruoyi.mock.prompt;
+import com.ruoyi.project.system.domain.SysUser;
+
import java.util.List;
+import java.util.Map;
import java.util.stream.Collectors;
/**
@@ -12,18 +15,17 @@
public static String buildSystemPrompt() {
return """
- 浣犳槸涓�涓紒涓欵RP绯荤粺鐨勬暟鎹ā鎷熶笓瀹躲�備綘闇�瑕佹牴鎹敤鎴锋彁渚涚殑琛屼笟銆佹暟閲忋�佹椂闂磋寖鍥寸瓑淇℃伅锛�
- 鐢熸垚绗﹀悎涓氬姟閫昏緫鐨勬ā鎷熸暟鎹��
+ 浣犳槸涓�涓紒涓欵RP绯荤粺鐨勬暟鎹ā鎷熶笓瀹躲��
- 瑕佹眰:
+ 鏍稿績瑙勫垯锛堝繀椤讳弗鏍奸伒瀹堬級锛�
1. 杈撳嚭蹇呴』鏄函JSON鏁扮粍锛屼笉瑕佺敤markdown浠g爜鍧楀寘瑁癸紝涓嶈鏈変换浣曞叾浠栨枃瀛�
2. 姣忎釜JSON瀵硅薄蹇呴』鍖呭惈 "entity" 瀛楁锛屽�间负瀹炰綋绫诲瀷鍚�
- 3. 鏁版嵁鍐呭瑕佺鍚堟寚瀹氳涓氱殑鐗瑰緛锛堝叕鍙稿悕绉般�佷骇鍝佸悕绉般�佽仈绯讳汉绛夎鍍忚琛屼笟鐨勶級
- 4. 鎵�鏈夋棩鏈熷瓧娈靛繀椤诲湪鎸囧畾鐨勬椂闂磋寖鍥村唴锛屼弗绂佷娇鐢ㄨ寖鍥翠箣澶栫殑鏃ユ湡
- 5. 閲戦銆佹暟閲忕瓑鏁板�煎瓧娈佃鍚堢悊
- 6. 鍚屼竴妯″潡鍐呯殑瀹炰綋涔嬮棿瑕佹湁寮曠敤鍏崇郴锛堝閿�鍞彴璐﹀紩鐢ㄥ鎴峰悕绉帮級
- 7. 鎵�鏈夊瓧绗︿覆瀛楁涓嶈浣跨敤emoji鎴栫壒娈妘nicode瀛楃
- 8. 鍚堝悓缂栧彿銆佹壒鍙风瓑鍖呭惈鏃ユ湡鐨勫瓧娈碉紝蹇呴』浣跨敤鏃堕棿鑼冨洿鍐呯殑鏃ユ湡锛屼笉瑕佷娇鐢ㄧず渚嬩腑鐨勫叿浣撴棩鏈�
+ 3. 鏁版嵁鍐呭瑕佺鍚堟寚瀹氳涓氱殑鐗瑰緛
+ 4. 閲戦銆佹暟閲忕瓑鏁板�煎瓧娈佃鍚堢悊
+ 5. 鍚屼竴妯″潡鍐呯殑瀹炰綋涔嬮棿瑕佹湁寮曠敤鍏崇郴
+ 6. 涓嶈浣跨敤emoji鎴栫壒娈妘nicode瀛楃
+ 7. 鏈�閲嶈锛氭棩鏈熷彧浠�"鎸囧畾鏃堕棿鑼冨洿"涓彇锛岀粷瀵逛笉瑕佺敤鍏朵粬骞翠唤锛�
+ 8. 浜哄憳瀛楁锛堝entryPerson銆乻alesman绛夛級蹇呴』浠�"绯荤粺鐢ㄦ埛鍒楄〃"涓�夊彇锛屾牴鎹鑹插拰閮ㄩ棬鍖归厤瀵瑰簲妯″潡锛屼笉瑕佺紪閫犱汉鍚嶏紒
""";
}
@@ -31,29 +33,68 @@
int countMin, int countMax,
String dateStart, String dateEnd,
String additionalInfo,
- List<Long> productIds,
- List<Long> productModelIds) {
+ Map<Long, String> productModelIdToCategory,
+ List<SysUser> systemUsers,
+ List<String> existingCustomerNames,
+ List<String> existingSupplierNames) {
StringBuilder sb = new StringBuilder();
- sb.append("璇蜂负浠ヤ笅琛屼笟鐢熸垚妯℃嫙ERP涓氬姟鏁版嵁:\n");
- sb.append("- 琛屼笟: ").append(String.join("銆�", industries)).append("\n");
- sb.append("- 鏁版嵁鏉℃暟: 姣忕瀹炰綋 ").append(countMin).append("-").append(countMax).append(" 鏉n");
- sb.append("- 鏃堕棿鑼冨洿: ").append(dateStart).append(" ~ ").append(dateEnd).append("\n");
+ sb.append("鎸囧畾琛屼笟: ").append(String.join("銆�", industries)).append("\n");
+ sb.append("姣忕瀹炰綋鐢熸垚: ").append(countMin).append("-").append(countMax).append(" 鏉n");
+ sb.append("鎸囧畾鏃堕棿鑼冨洿: ").append(dateStart).append(" 鍒� ").append(dateEnd);
+ sb.append("锛堟墍鏈夋棩鏈熷瓧娈靛繀椤诲湪杩欎釜鑼冨洿鍐咃紒绂佹浣跨敤2023銆�2024銆�2025绛変换浣曡秴鍑鸿寖鍥寸殑骞翠唤锛侊級\n");
if (additionalInfo != null && !additionalInfo.isBlank()) {
- sb.append("- 琛ュ厖淇℃伅: ").append(additionalInfo).append("\n");
+ sb.append("琛ュ厖淇℃伅: ").append(additionalInfo).append("\n");
}
sb.append("\n");
- sb.append("鍙敤鐨勪骇鍝両D鍒楄〃: ").append(productIds.stream().map(String::valueOf).collect(Collectors.joining(","))).append("\n");
- sb.append("鍙敤鐨勪骇鍝佽鏍糏D鍒楄〃: ").append(productModelIds.stream().map(String::valueOf).collect(Collectors.joining(","))).append("\n");
- sb.append("\n");
+ // 鎸夐《绾т骇鍝佸垎绫伙紙鎴愬搧/鍘熸潗鏂�/鍗婃垚鍝侊級鍒嗙粍鍒楀嚭浜у搧瑙勬牸
+ Map<String, List<Map.Entry<Long, String>>> grouped = productModelIdToCategory.entrySet().stream()
+ .collect(Collectors.groupingBy(
+ e -> categorize(e.getValue()),
+ java.util.LinkedHashMap::new,
+ Collectors.toList()));
- sb.append("闇�瑕佺敓鎴愮殑妯″潡: ").append(String.join("銆�", modules)).append("\n\n");
+ sb.append("=== 浜у搧瑙勬牸鍒楄〃 ===\n");
+ for (Map.Entry<String, List<Map.Entry<Long, String>>> entry : grouped.entrySet()) {
+ String label = entry.getKey();
+ List<Map.Entry<Long, String>> items = entry.getValue();
+ sb.append("銆�").append(label).append("銆�: ");
+ sb.append(items.stream()
+ .map(e -> e.getKey() + "(" + e.getValue() + ")")
+ .collect(Collectors.joining(", "))).append("\n");
+ }
+ sb.append("閿�鍞彴璐︾殑productData鍙兘閫夈�愭垚鍝佺被銆戣鏍硷紝閲囪喘鍙拌处鍙兘閫夈�愬師鏉愭枡绫汇�戣鏍笺�俓n\n");
+
+ // 绯荤粺鐢ㄦ埛鍒楄〃锛堝惈瑙掕壊鍜岄儴闂級
+ sb.append("=== 绯荤粺鐢ㄦ埛鍒楄〃锛堜汉鍛樺瓧娈靛繀椤讳粠涓�夊彇锛屼笉瑕佺紪閫犱汉鍚嶏級===\n");
+ for (SysUser u : systemUsers) {
+ String roleNames = u.getRoleNames() != null && !u.getRoleNames().isBlank() ? u.getRoleNames() : "鏃犺鑹�";
+ String deptNames = u.getDeptNames() != null && !u.getDeptNames().isBlank() ? u.getDeptNames() : "鏃犻儴闂�";
+ sb.append(u.getNickName()).append("锛堣鑹�: ").append(roleNames).append(", 閮ㄩ棬: ").append(deptNames).append("锛塡n");
+ }
+ sb.append("閫夋嫨瑙勫垯锛歕n");
+ sb.append("- 閿�鍞ā鍧楃殑浜哄憳(entryPerson銆乻alesman)閫夎鑹叉垨閮ㄩ棬鍚玕"閿�鍞甛"鐨勭敤鎴穃n");
+ sb.append("- 閲囪喘妯″潡鐨勪汉鍛橀�夎鑹叉垨閮ㄩ棬鍚玕"閲囪喘\"鐨勭敤鎴穃n");
+ sb.append("- 鐢熶骇妯″潡鐨勪汉鍛橀�夎鑹叉垨閮ㄩ棬鍚玕"鐢熶骇\"鐨勭敤鎴穃n");
+ sb.append("- 璐ㄩ噺妯″潡鐨勪汉鍛橀�夎鑹叉垨閮ㄩ棬鍚玕"璐ㄩ噺\"鎴朶"璐ㄦ\"鐨勭敤鎴穃n");
+ sb.append("- 浠撳簱妯″潡鐨勪汉鍛橀�夎鑹叉垨閮ㄩ棬鍚玕"浠撳簱\"鎴朶"搴撳瓨\"鐨勭敤鎴穃n\n");
+
+ if (!existingCustomerNames.isEmpty()) {
+ sb.append("=== 宸叉湁瀹㈡埛锛堝彧鑳藉紩鐢紝涓嶈鐢熸垚鏂癱ustomer瀹炰綋锛�===\n");
+ sb.append(String.join("銆�", existingCustomerNames)).append("\n\n");
+ }
+ if (!existingSupplierNames.isEmpty()) {
+ sb.append("=== 宸叉湁渚涘簲鍟嗭紙鍙兘寮曠敤锛屼笉瑕佺敓鎴愭柊supplier瀹炰綋锛�===\n");
+ sb.append(String.join("銆�", existingSupplierNames)).append("\n\n");
+ }
+
+ sb.append("鏁版嵁妯″潡: ").append(String.join("銆�", modules)).append("\n\n");
if (modules.contains("sales")) {
- sb.append(buildSalesPrompt(countMin, countMax, dateStart, dateEnd));
+ sb.append(buildSalesPrompt(countMin, countMax, dateStart, dateEnd, existingCustomerNames));
}
if (modules.contains("purchase")) {
- sb.append(buildPurchasePrompt(countMin, countMax, dateStart, dateEnd));
+ sb.append(buildPurchasePrompt(countMin, countMax, dateStart, dateEnd, existingSupplierNames));
}
if (modules.contains("quality")) {
sb.append(buildQualityPrompt(countMin, countMax, dateStart));
@@ -65,130 +106,105 @@
sb.append(buildStockPrompt(countMin, countMax, dateStart));
}
- sb.append("\n璇风洿鎺ヨ緭鍑篔SON鏁扮粍锛屼笉瑕佹湁浠讳綍鍏朵粬鍐呭:");
+ sb.append("\n璇风洿鎺ヨ緭鍑篔SON鏁扮粍:");
return sb.toString();
}
- private static String buildSalesPrompt(int min, int max, String dateStart, String dateEnd) {
+ /**
+ * 灏嗛《绾т骇鍝佸悕绉版槧灏勪负鍒嗙被鏍囩
+ */
+ private static String categorize(String rootProductName) {
+ if (rootProductName == null) return "鍏朵粬绫�";
+ if (rootProductName.contains("鎴愬搧") || rootProductName.contains("浜ф垚鍝�")) return "鎴愬搧绫�-閿�鍞紭鍏堥�夎繖浜�";
+ if (rootProductName.contains("鍘熸枡") || rootProductName.contains("鍘熸潗鏂�") || rootProductName.contains("鏉愭枡")) return "鍘熸潗鏂欑被-閲囪喘浼樺厛閫夎繖浜�";
+ if (rootProductName.contains("鍗婃垚鍝�")) return "鍗婃垚鍝佺被";
+ return "鍏朵粬绫�";
+ }
+
+ private static String buildSalesPrompt(int min, int max, String dateStart, String dateEnd,
+ List<String> existingCustomerNames) {
+ String namesHint = existingCustomerNames.isEmpty() ? ""
+ : "customerName蹇呴』浠庝互涓嬪凡鏈夊鎴蜂腑閫夋嫨: " + String.join("銆�", existingCustomerNames) + "\n";
return """
- 閿�鍞ā鍧� - 鎸変互涓嬫牸寮忕敓鎴愶紙娉ㄦ剰锛氱ず渚嬩腑鐨勬棩鏈熶粎浣滄牸寮忓弬鑰冿紝瀹為檯鏃ユ湡蹇呴』鍦� %s ~ %s 鑼冨洿鍐咃級:
- {
- "entity": "customer",
- "customerName": "XX绉戞妧鏈夐檺鍏徃",
- "customerType": "浼佷笟瀹㈡埛",
- "contactPerson": "寮犱笁",
- "contactPhone": "13800138000",
- "companyAddress": "XX鐪乆X甯俋X鍖篨X璺疿X鍙�",
- "companyPhone": "0513-XXXXXXXX",
- "taxpayerIdentificationNumber": "91110108XXXXXXXXXX",
- "maintainer": "鏉庡洓",
- "maintenanceTime": "%s",
- "bankAccount": "622202XXXXXXXXXXXX",
- "basicBankAccount": "XX閾惰XX鏀",
- "bankCode": "308100XXXXXX"
- }
+ 閿�鍞ā鍧楁牸寮忥紙鎵�鏈夋棩鏈熷繀椤诲湪 %s ~ %s 鑼冨洿鍐咃級:
+ %s娉ㄦ剰锛氫笉瑕佺敓鎴恈ustomer瀹炰綋锛屽彧鐢熸垚salesLedger锛�
+ productData涓殑productModelId蹇呴』閫夈�愭垚鍝佺被銆戣鏍糏D锛�
+ entryPerson鍜宻alesman蹇呴』浠庣郴缁熺敤鎴峰垪琛ㄤ腑瑙掕壊鎴栭儴闂ㄥ惈"閿�鍞�"鐨勭敤鎴蜂腑閫夊彇锛�
{
"entity": "salesLedger",
"customerName": "寮曠敤涓婇潰鐢熸垚鐨勫鎴峰悕绉�",
- "salesContractNo": "XS-骞存湀鏃�-搴忓彿",
+ "salesContractNo": "XS-YYYYMMDD-001",
"projectName": "XX椤圭洰",
"entryDate": "%s",
- "entryPerson": "寮犱笁",
- "salesman": "閿�鍞憳濮撳悕",
+ "entryPerson": "浠庣敤鎴峰垪琛ㄤ腑閫�",
+ "salesman": "浠庣敤鎴峰垪琛ㄤ腑閫�",
"contractAmount": 50000.00,
"paymentMethod": "鏈堢粨30澶�",
"executionDate": "%s",
"deliveryDate": "%s",
"type": 1,
- "productData": [
- {
- "productId": 1,
- "productModelId": 1,
- "quantity": 100,
- "taxInclusiveUnitPrice": 500.00,
- "taxInclusiveTotalPrice": 50000.00,
- "taxExclusiveTotalPrice": 44247.79,
- "taxRate": 13.00,
- "unit": "浠�",
- "type": 1
- }
- ]
+ "productData": [{
+ "productId": 1, "productModelId": 1, "quantity": 100,
+ "taxInclusiveUnitPrice": 500.00, "taxInclusiveTotalPrice": 50000.00,
+ "taxExclusiveTotalPrice": 44247.79, "taxRate": 13.00, "unit": "浠�", "type": 1
+ }]
}
- 瀹㈡埛鍚嶇О瑕佸儚鎸囧畾琛屼笟鐨勫叕鍙革紝鍚堝悓缂栧彿鏍煎紡XS-骞存湀鏃�-搴忓彿锛堝勾鏈堟棩鍙杄ntryDate鐨勬棩鏈燂級锛岄噾棰濆悎鐞嗐��
- 娉ㄦ剰 taxExclusiveTotalPrice 鏄笉鍚◣鎬讳环锛岄渶瑕佹牴鎹惈绋庢�讳环鍜岀◣鐜囪绠楋紙=鍚◣鎬讳环/(1+绋庣巼/100)锛夈��
- 鏃ユ湡鑼冨洿: %s ~ %s锛屾瘡绉嶅疄浣撶敓鎴�%d-%d鏉°��
- """.formatted(dateStart, dateEnd, dateStart, dateStart, dateStart, dateEnd, dateStart, dateEnd, min, max);
+ salesContractNo涓璝YYYMMDD鏇挎崲涓篹ntryDate鐨勬棩鏈熴��%d-%d鏉°��
+ """.formatted(dateStart, dateEnd, namesHint, dateStart, dateStart, dateEnd, min, max);
}
- private static String buildPurchasePrompt(int min, int max, String dateStart, String dateEnd) {
+ private static String buildPurchasePrompt(int min, int max, String dateStart, String dateEnd,
+ List<String> existingSupplierNames) {
+ String namesHint = existingSupplierNames.isEmpty() ? ""
+ : "supplierName蹇呴』浠庝互涓嬪凡鏈変緵搴斿晢涓�夋嫨: " + String.join("銆�", existingSupplierNames) + "\n";
return """
- 閲囪喘妯″潡 - 鎸変互涓嬫牸寮忕敓鎴愶紙娉ㄦ剰锛氱ず渚嬩腑鐨勬棩鏈熶粎浣滄牸寮忓弬鑰冿紝瀹為檯鏃ユ湡蹇呴』鍦� %s ~ %s 鑼冨洿鍐咃級:
- {
- "entity": "supplier",
- "supplierName": "XX鍘熸潗鏂欐湁闄愬叕鍙�",
- "supplierType": "鍘熸潗鏂欎緵搴斿晢",
- "contactUserName": "鏉庡洓",
- "contactUserPhone": "13900139000",
- "companyAddress": "XX鐪乆X甯俋X鍖篨X璺疿X鍙�",
- "companyPhone": "0513-XXXXXXXX",
- "taxpayerIdentificationNum": "91110108XXXXXXXXXX",
- "bankAccountName": "XX閾惰XX鏀",
- "bankAccountNum": "622202XXXXXXXXXXXX",
- "isWhite": 0
- }
+ 閲囪喘妯″潡鏍煎紡锛堟墍鏈夋棩鏈熷繀椤诲湪 %s ~ %s 鑼冨洿鍐咃級:
+ %s娉ㄦ剰锛氫笉瑕佺敓鎴恠upplier瀹炰綋锛屽彧鐢熸垚purchaseLedger锛�
+ productData涓殑productModelId蹇呴』閫夈�愬師鏉愭枡绫汇�戣鏍糏D锛�
+ 浜哄憳瀛楁蹇呴』浠庣郴缁熺敤鎴峰垪琛ㄤ腑瑙掕壊鎴栭儴闂ㄥ惈"閲囪喘"鐨勭敤鎴蜂腑閫夊彇锛�
{
"entity": "purchaseLedger",
- "supplierName": "寮曠敤涓婇潰鐢熸垚鐨勪緵搴斿晢鍚嶇О",
- "purchaseContractNumber": "CG-骞存湀鏃�-搴忓彿",
+ "supplierName": "浠庡凡鏈変緵搴斿晢涓�夋嫨",
+ "purchaseContractNumber": "CG-YYYYMMDD-001",
"projectName": "XX閲囪喘椤圭洰",
"entryDate": "%s",
"contractAmount": 30000.00,
"paymentMethod": "璐у埌浠樻",
"executionDate": "%s",
- "productData": [
- {
- "productId": 1,
- "productModelId": 1,
- "quantity": 50,
- "taxInclusiveUnitPrice": 600.00,
- "taxInclusiveTotalPrice": 30000.00,
- "taxExclusiveTotalPrice": 26548.67,
- "taxRate": 13.00,
- "unit": "浠�",
- "type": 2
- }
- ]
+ "productData": [{
+ "productId": 1, "productModelId": 1, "quantity": 50,
+ "taxInclusiveUnitPrice": 600.00, "taxInclusiveTotalPrice": 30000.00,
+ "taxExclusiveTotalPrice": 26548.67, "taxRate": 13.00, "unit": "浠�", "type": 2
+ }]
}
- 渚涘簲鍟嗗悕绉拌鍍忔寚瀹氳涓氱殑渚涘簲鍟嗭紝鍚堝悓缂栧彿鏍煎紡CG-骞存湀鏃�-搴忓彿锛堝勾鏈堟棩鍙杄ntryDate鐨勬棩鏈燂級銆�
- 娉ㄦ剰 taxExclusiveTotalPrice 鏄笉鍚◣鎬讳环锛岄渶瑕佹牴鎹惈绋庢�讳环鍜岀◣鐜囪绠楋紙=鍚◣鎬讳环/(1+绋庣巼/100)锛夈��
- 鏃ユ湡鑼冨洿: %s ~ %s锛屾瘡绉嶅疄浣撶敓鎴�%d-%d鏉°��
- """.formatted(dateStart, dateEnd, dateStart, dateStart, dateStart, dateEnd, min, max);
+ purchaseContractNumber涓璝YYYMMDD鏇挎崲涓篹ntryDate鐨勬棩鏈熴��%d-%d鏉°��
+ """.formatted(dateStart, dateEnd, namesHint, dateStart, dateStart, min, max);
}
private static String buildQualityPrompt(int min, int max, String dateStart) {
return """
- 璐ㄩ噺妯″潡 - 鎸変互涓嬫牸寮忕敓鎴�:
+ 璐ㄩ噺妯″潡鏍煎紡:
{
"entity": "qualityTestStandard",
- "standardNo": "QTS-骞存湀鏃�-搴忓彿",
+ "standardNo": "QTS-YYYYMMDD-001",
"standardName": "XX浜у搧妫�楠屾爣鍑�",
"inspectType": 0,
"remark": "閫傜敤浜嶺X琛屼笟鐨勮川閲忔楠屾爣鍑�"
}
inspectType: 0=鍘熸潗鏂欐楠�, 1=杩囩▼妫�楠�, 2=鍑哄巶妫�楠屻�備笁绉嶇被鍨嬮兘瑕佽鐩栥��
- standardNo涓殑骞存湀鏃ヤ娇鐢� %s 杩欎釜鏃ユ湡銆�
+ standardNo涓璝YYYMMDD鏇挎崲涓� %s銆�%d-%d鏉°��
{
"entity": "qualityTestStandardBinding",
"productId": 1,
"testStandardId": 1
}
- 姣忕瀹炰綋鐢熸垚%d-%d鏉°��
- """.formatted(dateStart, min, max);
+ %d-%d鏉°��
+ """.formatted(dateStart.replace("-", ""), min, max, min, max);
}
private static String buildProductionPrompt(int min, int max, String dateStart, String dateEnd) {
return """
- 鐢熶骇妯″潡 - 鎸変互涓嬫牸寮忕敓鎴愶紙娉ㄦ剰锛氱ず渚嬩腑鐨勬棩鏈熶粎浣滄牸寮忓弬鑰冿紝瀹為檯鏃ユ湡蹇呴』鍦� %s ~ %s 鑼冨洿鍐咃級:
+ 鐢熶骇妯″潡鏍煎紡锛堟墍鏈夋棩鏈熷繀椤诲湪 %s ~ %s 鑼冨洿鍐咃級:
{
"entity": "productionPlan",
"productModelId": 1,
@@ -205,23 +221,22 @@
"planCompleteTime": "%s",
"remark": "鏍规嵁鐢熶骇璁″垝XX鐢熸垚"
}
- productionPlan鐨剆ource鍙��"閿�鍞�"鎴�"鍐呴儴"銆�
- 鏃ユ湡鑼冨洿: %s ~ %s锛屾瘡绉嶅疄浣撶敓鎴�%d-%d鏉°��
- """.formatted(dateStart, dateEnd, dateStart, dateEnd, dateEnd, dateStart, dateEnd, min, max);
+ source鍙��"閿�鍞�"鎴�"鍐呴儴"銆�%d-%d鏉°��
+ """.formatted(dateStart, dateEnd, dateStart, dateEnd, dateEnd, min, max);
}
private static String buildStockPrompt(int min, int max, String dateStart) {
return """
- 搴撳瓨妯″潡 - 鎸変互涓嬫牸寮忕敓鎴�:
+ 搴撳瓨妯″潡鏍煎紡:
{
"entity": "stockInventory",
"productModelId": 1,
"qualitity": 500,
- "batchNo": "BATCH-骞存湀鏃�-搴忓彿",
+ "batchNo": "BATCH-YYYYMMDD-001",
"warnNum": 50,
"remark": "瀹夊叏搴撳瓨"
}
- 姣忕瀹炰綋鐢熸垚%d-%d鏉°�俠atchNo鏍煎紡BATCH-骞存湀鏃�-搴忓彿锛屽勾鏈堟棩浣跨敤 %s 杩欎釜鏃ユ湡銆�
- """.formatted(min, max, dateStart);
+ batchNo涓璝YYYMMDD鏇挎崲涓� %s銆�%d-%d鏉°��
+ """.formatted(dateStart.replace("-", ""), min, max);
}
}
diff --git a/src/main/java/com/ruoyi/mock/service/impl/DataCheckServiceImpl.java b/src/main/java/com/ruoyi/mock/service/impl/DataCheckServiceImpl.java
index 870e20b..0fc4718 100644
--- a/src/main/java/com/ruoyi/mock/service/impl/DataCheckServiceImpl.java
+++ b/src/main/java/com/ruoyi/mock/service/impl/DataCheckServiceImpl.java
@@ -5,14 +5,26 @@
import com.ruoyi.approve.mapper.ApprovalTemplateMapper;
import com.ruoyi.basic.mapper.CustomerMapper;
import com.ruoyi.basic.mapper.ProductMapper;
+import com.ruoyi.basic.mapper.ProductModelMapper;
import com.ruoyi.basic.mapper.SupplierManageMapper;
import com.ruoyi.common.enums.TypeEnums;
import com.ruoyi.mock.dto.DataCheckRequest;
import com.ruoyi.mock.service.DataCheckService;
import com.ruoyi.mock.vo.DataCheckResult;
import com.ruoyi.mock.vo.DataCheckResult.CheckItem;
+import com.ruoyi.project.system.domain.SysUser;
+import com.ruoyi.project.system.mapper.SysUserMapper;
import com.ruoyi.quality.mapper.QualityTestStandardBindingMapper;
import com.ruoyi.quality.mapper.QualityTestStandardMapper;
+import com.ruoyi.technology.mapper.TechnologyBomMapper;
+import com.ruoyi.technology.mapper.TechnologyBomStructureMapper;
+import com.ruoyi.technology.mapper.TechnologyOperationMapper;
+import com.ruoyi.technology.mapper.TechnologyRoutingMapper;
+import com.ruoyi.technology.mapper.TechnologyRoutingOperationMapper;
+import com.ruoyi.technology.pojo.TechnologyBom;
+import com.ruoyi.technology.pojo.TechnologyBomStructure;
+import com.ruoyi.technology.pojo.TechnologyRouting;
+import com.ruoyi.technology.pojo.TechnologyRoutingOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@@ -26,11 +38,18 @@
public class DataCheckServiceImpl implements DataCheckService {
private final ProductMapper productMapper;
+ private final ProductModelMapper productModelMapper;
private final CustomerMapper customerMapper;
private final SupplierManageMapper supplierManageMapper;
private final ApprovalTemplateMapper approvalTemplateMapper;
private final QualityTestStandardMapper qualityTestStandardMapper;
private final QualityTestStandardBindingMapper qualityTestStandardBindingMapper;
+ private final TechnologyRoutingMapper technologyRoutingMapper;
+ private final TechnologyRoutingOperationMapper technologyRoutingOperationMapper;
+ private final TechnologyOperationMapper technologyOperationMapper;
+ private final TechnologyBomMapper technologyBomMapper;
+ private final TechnologyBomStructureMapper technologyBomStructureMapper;
+ private final SysUserMapper sysUserMapper;
@Override
public DataCheckResult check(DataCheckRequest request) {
@@ -43,6 +62,7 @@
if (!modules.isEmpty()) {
addProductCheck(itemMap);
+ addUserChecks(itemMap);
}
for (String module : modules) {
@@ -50,6 +70,7 @@
case "sales" -> addSalesChecks(itemMap);
case "purchase" -> addPurchaseChecks(itemMap);
case "quality" -> addQualityChecks(itemMap);
+ case "production" -> addProductionChecks(itemMap);
}
}
@@ -70,6 +91,34 @@
long count = productMapper.selectCount(null);
itemMap.put(key, buildItem("common", "浜у搧鏁版嵁", 1, (int) count,
"缂哄皯浜у搧鏁版嵁锛岃鍏堝湪銆愬熀纭�鏁版嵁-浜у搧绠$悊銆戜腑娣诲姞鑷冲皯1鏉′骇鍝�"));
+ }
+
+ private void addUserChecks(Map<String, CheckItem> itemMap) {
+ // 1. 绯荤粺鐢ㄦ埛
+ String userKey = "common:绯荤粺鐢ㄦ埛";
+ if (!itemMap.containsKey(userKey)) {
+ List<SysUser> users = sysUserMapper.selectUserListWithDetail();
+ itemMap.put(userKey, buildItem("common", "绯荤粺鐢ㄦ埛", 1, (int) users.size(),
+ "缂哄皯绯荤粺鐢ㄦ埛锛岃鍏堝湪銆愮郴缁熺鐞�-鐢ㄦ埛绠$悊銆戜腑娣诲姞鐢ㄦ埛"));
+ }
+
+ // 2. 鏈夎鑹茬殑鐢ㄦ埛
+ String userWithRoleKey = "common:鐢ㄦ埛瑙掕壊閰嶇疆";
+ if (!itemMap.containsKey(userWithRoleKey)) {
+ List<SysUser> users = sysUserMapper.selectUserListWithDetail();
+ long withRole = users.stream().filter(u -> u.getRoleNames() != null && !u.getRoleNames().isBlank()).count();
+ itemMap.put(userWithRoleKey, buildItem("common", "鐢ㄦ埛瑙掕壊閰嶇疆", 1, (int) withRole,
+ "娌℃湁鐢ㄦ埛鍒嗛厤瑙掕壊锛岃鍏堝湪銆愮郴缁熺鐞�-鐢ㄦ埛绠$悊銆戜腑涓虹敤鎴峰垎閰嶈鑹�"));
+ }
+
+ // 3. 鏈夐儴闂ㄧ殑鐢ㄦ埛
+ String userWithDeptKey = "common:鐢ㄦ埛閮ㄩ棬閰嶇疆";
+ if (!itemMap.containsKey(userWithDeptKey)) {
+ List<SysUser> users = sysUserMapper.selectUserListWithDetail();
+ long withDept = users.stream().filter(u -> u.getDeptNames() != null && !u.getDeptNames().isBlank()).count();
+ itemMap.put(userWithDeptKey, buildItem("common", "鐢ㄦ埛閮ㄩ棬閰嶇疆", 1, (int) withDept,
+ "娌℃湁鐢ㄦ埛鍒嗛厤閮ㄩ棬锛岃鍏堝湪銆愮郴缁熺鐞�-鐢ㄦ埛绠$悊銆戜腑涓虹敤鎴峰垎閰嶉儴闂�"));
+ }
}
private void addSalesChecks(Map<String, CheckItem> itemMap) {
@@ -133,6 +182,93 @@
}
}
+ private void addProductionChecks(Map<String, CheckItem> itemMap) {
+ // 1. 浜у搧瑙勬牸
+ String modelKey = "production:浜у搧瑙勬牸";
+ if (!itemMap.containsKey(modelKey)) {
+ long count = productModelMapper.selectCount(null);
+ itemMap.put(modelKey, buildItem("production", "浜у搧瑙勬牸", 1, (int) count,
+ "缂哄皯浜у搧瑙勬牸锛岃鍏堝湪銆愬熀纭�鏁版嵁-浜у搧绠$悊銆戜腑涓轰骇鍝佹坊鍔犺鏍煎瀷鍙�"));
+ }
+
+ // 2. 宸ュ簭
+ String operationKey = "production:宸ュ簭";
+ if (!itemMap.containsKey(operationKey)) {
+ long count = technologyOperationMapper.selectCount(null);
+ itemMap.put(operationKey, buildItem("production", "宸ュ簭", 1, (int) count,
+ "缂哄皯宸ュ簭锛岃鍏堝湪銆愬伐鑹鸿璁�-宸ュ簭绠$悊銆戜腑鍒涘缓宸ュ簭"));
+ }
+
+ // 3. BOM
+ String bomKey = "production:BOM";
+ if (!itemMap.containsKey(bomKey)) {
+ long count = technologyBomMapper.selectCount(null);
+ itemMap.put(bomKey, buildItem("production", "BOM", 1, (int) count,
+ "缂哄皯BOM锛岃鍏堝湪銆愬伐鑹鸿璁�-BOM绠$悊銆戜腑鍒涘缓BOM"));
+ }
+
+ // 4. BOM浜у搧缁撴瀯
+ String bomStructureKey = "production:BOM浜у搧缁撴瀯";
+ if (!itemMap.containsKey(bomStructureKey)) {
+ long count = technologyBomStructureMapper.selectCount(null);
+ itemMap.put(bomStructureKey, buildItem("production", "BOM浜у搧缁撴瀯", 1, (int) count,
+ "缂哄皯BOM浜у搧缁撴瀯锛岃鍏堝湪銆愬伐鑹鸿璁�-BOM绠$悊銆戜腑涓築OM娣诲姞浜у搧缁撴瀯鑺傜偣"));
+ }
+
+ // 5. 宸ヨ壓璺嚎
+ String routingKey = "production:宸ヨ壓璺嚎";
+ if (!itemMap.containsKey(routingKey)) {
+ long count = technologyRoutingMapper.selectCount(null);
+ itemMap.put(routingKey, buildItem("production", "宸ヨ壓璺嚎", 1, (int) count,
+ "缂哄皯宸ヨ壓璺嚎锛岃鍏堝湪銆愬伐鑹鸿璁�-宸ヨ壓璺嚎銆戜腑鍒涘缓宸ヨ壓璺嚎"));
+ }
+
+ // 6. 宸ヨ壓璺嚎宸ュ簭
+ String routingOpKey = "production:宸ヨ壓璺嚎宸ュ簭";
+ if (!itemMap.containsKey(routingOpKey)) {
+ long count = technologyRoutingOperationMapper.selectCount(null);
+ itemMap.put(routingOpKey, buildItem("production", "宸ヨ壓璺嚎宸ュ簭", 1, (int) count,
+ "缂哄皯宸ヨ壓璺嚎宸ュ簭锛岃鍏堝湪銆愬伐鑹鸿璁�-宸ヨ壓璺嚎銆戜腑涓哄伐鑹鸿矾绾挎坊鍔犲伐搴�"));
+ }
+
+ // 7. 鍏宠仈鎬ф娴嬶細鏈変骇鍝佽鏍间絾鏃犲伐鑹鸿矾绾跨殑
+ String linkageKey = "production:浜у搧-宸ヨ壓璺嚎鍏宠仈";
+ if (!itemMap.containsKey(linkageKey)) {
+ long modelCount = productModelMapper.selectCount(null);
+ long routedCount = technologyRoutingMapper.selectCount(
+ new LambdaQueryWrapper<TechnologyRouting>()
+ .isNotNull(TechnologyRouting::getProductModelId)
+ .gt(TechnologyRouting::getProductModelId, 0));
+ itemMap.put(linkageKey, buildItem("production", "浜у搧-宸ヨ壓璺嚎鍏宠仈",
+ (int) Math.min(modelCount, 1), (int) routedCount,
+ "閮ㄥ垎浜у搧瑙勬牸鏈叧鑱斿伐鑹鸿矾绾匡紝璇峰厛鍦ㄣ�愬伐鑹鸿璁�-宸ヨ壓璺嚎銆戜腑涓轰骇鍝佽鏍煎垱寤哄伐鑹鸿矾绾�"));
+ }
+
+ // 8. 鍏宠仈鎬ф娴嬶細鏈夊伐鑹鸿矾绾夸絾鏃犲伐搴忕殑
+ String routingOpLinkKey = "production:宸ヨ壓璺嚎-宸ュ簭鍏宠仈";
+ if (!itemMap.containsKey(routingOpLinkKey)) {
+ long routingCount = technologyRoutingMapper.selectCount(null);
+ long routedOpCount = technologyRoutingOperationMapper.selectCount(
+ new LambdaQueryWrapper<TechnologyRoutingOperation>()
+ .gt(TechnologyRoutingOperation::getTechnologyRoutingId, 0));
+ itemMap.put(routingOpLinkKey, buildItem("production", "宸ヨ壓璺嚎-宸ュ簭鍏宠仈",
+ (int) Math.min(routingCount, 1), (int) routedOpCount,
+ "閮ㄥ垎宸ヨ壓璺嚎鏈坊鍔犲伐搴忥紝璇峰厛鍦ㄣ�愬伐鑹鸿璁�-宸ヨ壓璺嚎銆戜腑涓哄伐鑹鸿矾绾挎坊鍔犲伐搴�"));
+ }
+
+ // 9. 鍏宠仈鎬ф娴嬶細鏈塀OM浣嗘棤浜у搧缁撴瀯鐨�
+ String bomStructureLinkKey = "production:BOM-浜у搧缁撴瀯鍏宠仈";
+ if (!itemMap.containsKey(bomStructureLinkKey)) {
+ long bomCount = technologyBomMapper.selectCount(null);
+ long structureCount = technologyBomStructureMapper.selectCount(
+ new LambdaQueryWrapper<TechnologyBomStructure>()
+ .gt(TechnologyBomStructure::getBomId, 0));
+ itemMap.put(bomStructureLinkKey, buildItem("production", "BOM-浜у搧缁撴瀯鍏宠仈",
+ (int) Math.min(bomCount, 1), (int) structureCount,
+ "閮ㄥ垎BOM鏈坊鍔犱骇鍝佺粨鏋勶紝璇峰厛鍦ㄣ�愬伐鑹鸿璁�-BOM绠$悊銆戜腑涓築OM娣诲姞浜у搧缁撴瀯鑺傜偣"));
+ }
+ }
+
private CheckItem buildItem(String module, String itemName, int minRequired, int currentCount, String failMessage) {
CheckItem item = new CheckItem();
item.setModule(module);
diff --git a/src/main/java/com/ruoyi/mock/service/impl/DataGenerateServiceImpl.java b/src/main/java/com/ruoyi/mock/service/impl/DataGenerateServiceImpl.java
index 046633d..92b7cb8 100644
--- a/src/main/java/com/ruoyi/mock/service/impl/DataGenerateServiceImpl.java
+++ b/src/main/java/com/ruoyi/mock/service/impl/DataGenerateServiceImpl.java
@@ -5,27 +5,51 @@
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.ai.assistant.Assistant;
import com.ruoyi.approve.mapper.ApprovalInstanceMapper;
+import com.ruoyi.approve.mapper.ApprovalInstanceNodeMapper;
+import com.ruoyi.approve.mapper.ApprovalRecordMapper;
+import com.ruoyi.approve.mapper.ApprovalTaskMapper;
import com.ruoyi.approve.pojo.ApprovalInstance;
+import com.ruoyi.approve.pojo.ApprovalInstanceNode;
+import com.ruoyi.approve.pojo.ApprovalRecord;
+import com.ruoyi.approve.pojo.ApprovalTask;
import com.ruoyi.approve.service.ApprovalInstanceService;
import com.ruoyi.basic.mapper.ProductMapper;
import com.ruoyi.basic.mapper.ProductModelMapper;
import com.ruoyi.basic.pojo.Customer;
+import com.ruoyi.basic.pojo.Product;
+import com.ruoyi.basic.pojo.ProductModel;
import com.ruoyi.basic.pojo.SupplierManage;
import com.ruoyi.basic.service.ICustomerService;
import com.ruoyi.basic.service.ISupplierService;
import com.ruoyi.common.enums.ReviewStatusEnum;
+import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
+import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
+import com.ruoyi.common.utils.OrderUtils;
import com.ruoyi.mock.dto.DataGenerateRequest;
import com.ruoyi.mock.prompt.MockDataPrompt;
import com.ruoyi.mock.service.DataGenerateService;
import com.ruoyi.mock.vo.DataGenerateResult;
import com.ruoyi.mock.vo.DataGenerateResult.ModuleSummary;
-import com.ruoyi.production.pojo.ProductionOrder;
-import com.ruoyi.production.pojo.ProductionPlan;
+import com.ruoyi.procurementrecord.utils.StockUtils;
+import com.ruoyi.production.bean.dto.ProductionOrderPickDto;
+import com.ruoyi.production.bean.dto.ProductionPlanDto;
+import com.ruoyi.production.bean.dto.ProductionProductMainDto;
+import com.ruoyi.production.bean.vo.ProductionBomStructureVo;
+import com.ruoyi.production.mapper.*;
+import com.ruoyi.production.pojo.*;
+import com.ruoyi.production.service.ProductionOrderPickService;
import com.ruoyi.production.service.ProductionOrderService;
import com.ruoyi.production.service.ProductionPlanService;
+import com.ruoyi.production.service.ProductionProductMainService;
import com.ruoyi.purchase.dto.PurchaseLedgerDto;
import com.ruoyi.purchase.pojo.PurchaseLedger;
import com.ruoyi.purchase.service.IPurchaseLedgerService;
+import com.ruoyi.project.system.domain.SysDept;
+import com.ruoyi.project.system.domain.SysUser;
+import com.ruoyi.project.system.mapper.SysDeptMapper;
+import com.ruoyi.project.system.mapper.SysUserDeptMapper;
+import com.ruoyi.project.system.mapper.SysUserMapper;
+import com.ruoyi.quality.mapper.QualityInspectMapper;
import com.ruoyi.quality.pojo.QualityInspect;
import com.ruoyi.quality.pojo.QualityTestStandard;
import com.ruoyi.quality.pojo.QualityTestStandardBinding;
@@ -33,11 +57,29 @@
import com.ruoyi.quality.service.IQualityTestStandardService;
import com.ruoyi.quality.service.QualityTestStandardBindingService;
import com.ruoyi.sales.dto.SalesLedgerDto;
+import com.ruoyi.sales.dto.ShippingInfoDto;
+import com.ruoyi.sales.mapper.SalesLedgerMapper;
+import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
+import com.ruoyi.sales.mapper.ShippingInfoMapper;
+import com.ruoyi.sales.mapper.ShippingProductDetailMapper;
+import com.ruoyi.sales.pojo.SalesLedger;
import com.ruoyi.sales.pojo.SalesLedgerProduct;
+import com.ruoyi.sales.pojo.ShippingInfo;
+import com.ruoyi.sales.pojo.ShippingProductDetail;
import com.ruoyi.sales.service.ISalesLedgerService;
+import com.ruoyi.sales.service.ShippingInfoService;
+import com.ruoyi.stock.mapper.StockInRecordMapper;
+import com.ruoyi.stock.mapper.StockInventoryMapper;
+import com.ruoyi.stock.mapper.StockOutRecordMapper;
+import com.ruoyi.stock.pojo.StockInventory;
+import com.ruoyi.stock.pojo.StockOutRecord;
import com.ruoyi.stock.dto.StockInventoryDto;
import com.ruoyi.stock.service.StockInRecordService;
+import com.ruoyi.stock.service.StockOutRecordService;
import com.ruoyi.stock.service.StockInventoryService;
+import com.ruoyi.technology.mapper.TechnologyBomStructureMapper;
+import com.ruoyi.technology.mapper.TechnologyRoutingMapper;
+import com.ruoyi.technology.mapper.TechnologyRoutingOperationMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@@ -46,11 +88,15 @@
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
@@ -76,8 +122,43 @@
// 閲囪喘瀹屾暣娴佺▼闇�瑕佺殑service
private final ApprovalInstanceService approvalInstanceService;
private final ApprovalInstanceMapper approvalInstanceMapper;
+ private final ApprovalInstanceNodeMapper approvalInstanceNodeMapper;
+ private final ApprovalTaskMapper approvalTaskMapper;
+ private final ApprovalRecordMapper approvalRecordMapper;
private final IQualityInspectService qualityInspectService;
+ private final QualityInspectMapper qualityInspectMapper;
private final StockInRecordService stockInRecordService;
+ private final StockInRecordMapper stockInRecordMapper;
+
+ // 閿�鍞畬鏁存祦绋嬮渶瑕佺殑service/mapper
+ private final SalesLedgerMapper salesLedgerMapper;
+ private final SalesLedgerProductMapper salesLedgerProductMapper;
+ private final ProductionPlanMapper productionPlanMapper;
+ private final ProductionOrderMapper productionOrderMapper;
+ private final ProductionOperationTaskMapper productionOperationTaskMapper;
+ private final ProductionProductMainService productionProductMainService;
+ private final ShippingInfoService shippingInfoService;
+ private final ShippingInfoMapper shippingInfoMapper;
+ private final ShippingProductDetailMapper shippingProductDetailMapper;
+ private final StockUtils stockUtils;
+ private final StockOutRecordMapper stockOutRecordMapper;
+ private final StockOutRecordService stockOutRecordService;
+ private final StockInventoryMapper stockInventoryMapper;
+
+ // 宸ヨ壓鏁版嵁妫�娴�
+ private final TechnologyRoutingMapper technologyRoutingMapper;
+ private final TechnologyRoutingOperationMapper technologyRoutingOperationMapper;
+ private final TechnologyBomStructureMapper technologyBomStructureMapper;
+
+ // 棰嗘枡
+ private final ProductionOrderPickService productionOrderPickService;
+ private final ProductionOrderBomMapper productionOrderBomMapper;
+ private final ProductionBomStructureMapper productionBomStructureMapper;
+
+ // 鐢ㄦ埛/瑙掕壊鏌ヨ
+ private final SysUserMapper sysUserMapper;
+ private final SysDeptMapper sysDeptMapper;
+ private final SysUserDeptMapper sysUserDeptMapper;
@Override
public DataGenerateResult generate(DataGenerateRequest request) {
@@ -87,10 +168,18 @@
int totalGenerated = 0;
try {
- List<Long> productIds = productMapper.selectList(null).stream()
- .map(p -> p.getId()).collect(Collectors.toList());
- List<Long> productModelIds = productModelMapper.selectList(null).stream()
- .map(m -> m.getId()).collect(Collectors.toList());
+ // 鏋勫缓浜у搧瑙勬牸鍒嗙被锛氶�氳繃Product鏍戞牴鑺傜偣鍒ゆ柇鎴愬搧/鍘熸潗鏂�
+ Map<Long, String> productModelIdToCategory = buildProductModelCategoryMap();
+ List<Long> productModelIds = new ArrayList<>(productModelIdToCategory.keySet());
+
+ // 鍔犺浇宸叉湁瀹㈡埛/渚涘簲鍟嗭紙涓嶆柊澧烇紝浣跨敤宸叉湁鏁版嵁锛�
+ Map<String, Long> customerNameToId = loadExistingCustomers();
+ Map<String, Long> supplierNameToId = loadExistingSuppliers();
+ List<String> existingCustomerNames = new ArrayList<>(customerNameToId.keySet());
+ List<String> existingSupplierNames = new ArrayList<>(supplierNameToId.keySet());
+
+ // 鍔犺浇绯荤粺鐢ㄦ埛淇℃伅锛堟樀绉般�佽鑹层�侀儴闂級
+ List<SysUser> systemUsers = loadSystemUsersWithDetail();
String systemPrompt = MockDataPrompt.buildSystemPrompt();
String userMessage = MockDataPrompt.buildUserMessage(
@@ -98,7 +187,9 @@
request.getCountMin(), request.getCountMax(),
request.getDateStart(), request.getDateEnd(),
request.getAdditionalInfo(),
- productIds, productModelIds);
+ productModelIdToCategory,
+ systemUsers,
+ existingCustomerNames, existingSupplierNames);
String fullPrompt = systemPrompt + "\n\n" + userMessage;
log.info("璋冪敤AI鐢熸垚妯℃嫙鏁版嵁, modules={}, industries={}", request.getModules(), request.getIndustries());
@@ -120,24 +211,17 @@
return result;
}
+ // 淇AI鐢熸垚鐨勬棩鏈熷埌鎸囧畾鏃堕棿鑼冨洿鍐�
+ String dateStart = request.getDateStart();
+ String dateEnd = request.getDateEnd();
+ if (dateStart != null && dateEnd != null) {
+ fixDatesInRange(entities, dateStart, dateEnd);
+ }
+
Map<String, List<JSONObject>> grouped = entities.stream()
.collect(Collectors.groupingBy(e -> e.getString("entity")));
- // 鍚嶇О鈫扞D 鏄犲皠琛紝鐢ㄤ簬鍒涘缓涓氬姟鍗曟嵁鏃跺洖濉閿�
- Map<String, Long> customerNameToId = new HashMap<>();
- Map<String, Long> supplierNameToId = new HashMap<>();
-
- // Tier 0: 鍩虹鏁版嵁
- if (grouped.containsKey("customer")) {
- ModuleSummary s = createCustomers(grouped.get("customer"), customerNameToId);
- summaries.add(s);
- totalGenerated += s.getSuccessCount();
- }
- if (grouped.containsKey("supplier")) {
- ModuleSummary s = createSuppliers(grouped.get("supplier"), supplierNameToId);
- summaries.add(s);
- totalGenerated += s.getSuccessCount();
- }
+ // Tier 0: 鍩虹鏁版嵁锛堝鎴峰拰渚涘簲鍟嗕笉鑷姩鐢熸垚锛屼娇鐢ㄥ凡鏈夋暟鎹級
if (grouped.containsKey("qualityTestStandard")) {
ModuleSummary s = createQualityStandards(grouped.get("qualityTestStandard"));
summaries.add(s);
@@ -146,13 +230,13 @@
// Tier 1: 涓氬姟鍗曟嵁
if (grouped.containsKey("salesLedger")) {
- ModuleSummary s = createSalesLedgers(grouped.get("salesLedger"), customerNameToId);
+ ModuleSummary s = createSalesLedgers(grouped.get("salesLedger"), customerNameToId, request.getDateStart());
summaries.add(s);
totalGenerated += s.getSuccessCount();
}
if (grouped.containsKey("purchaseLedger")) {
ModuleSummary s = createPurchaseLedgers(grouped.get("purchaseLedger"), supplierNameToId,
- request.getAdditionalInfo(), request.getDateEnd());
+ request.getAdditionalInfo(), request.getDateStart(), request.getDateEnd());
summaries.add(s);
totalGenerated += s.getSuccessCount();
}
@@ -216,7 +300,154 @@
}
}
+ /**
+ * 淇AI鐢熸垚鐨勬棩鏈熷埌鎸囧畾鏃堕棿鑼冨洿鍐呫��
+ * 閬嶅巻鎵�鏈夊疄浣撶殑鎵�鏈夊瓧娈碉紝濡傛灉鍙戠幇鏃ユ湡瀛楃涓诧紙yyyy-MM-dd鏍煎紡锛夎秴鍑鸿寖鍥达紝鏇挎崲涓鸿寖鍥村唴鐨勯殢鏈烘棩鏈熴��
+ */
+ private void fixDatesInRange(List<JSONObject> entities, String dateStart, String dateEnd) {
+ LocalDate start;
+ LocalDate end;
+ try {
+ start = LocalDate.parse(dateStart);
+ end = LocalDate.parse(dateEnd);
+ } catch (Exception e) {
+ log.warn("鏃ユ湡鑼冨洿瑙f瀽澶辫触: {} ~ {}", dateStart, dateEnd);
+ return;
+ }
+ long daysBetween = ChronoUnit.DAYS.between(start, end);
+ if (daysBetween <= 0) {
+ daysBetween = 1;
+ }
+
+ // 鎵�鏈夊凡鐭ョ殑鏃ユ湡瀛楁鍚�
+ java.util.Set<String> dateFields = java.util.Set.of(
+ "entryDate", "executionDate", "deliveryDate", "requiredDate",
+ "promisedDeliveryDate", "planCompleteTime", "maintenanceTime",
+ "checkTime", "registerDate"
+ );
+
+ for (JSONObject entity : entities) {
+ for (String key : dateFields) {
+ String val = entity.getString(key);
+ if (val != null && val.matches("\\d{4}-\\d{2}-\\d{2}")) {
+ try {
+ LocalDate d = LocalDate.parse(val);
+ if (d.isBefore(start) || d.isAfter(end)) {
+ LocalDate fixed = start.plusDays(ThreadLocalRandom.current().nextLong(daysBetween + 1));
+ entity.put(key, fixed.toString());
+ log.debug("淇鏃ユ湡 {}: {} -> {}", key, val, fixed);
+ }
+ } catch (Exception ignored) {
+ }
+ } else if (val != null && !val.matches("\\d{4}-\\d{2}-\\d{2}")) {
+ // AI杩斿洖浜嗘棤鏁堟棩鏈熸牸寮忥紝鐩存帴鏇挎崲涓鸿寖鍥村唴鐨勯殢鏈烘棩鏈�
+ LocalDate fixed = start.plusDays(ThreadLocalRandom.current().nextLong(daysBetween + 1));
+ entity.put(key, fixed.toString());
+ log.debug("淇鏃犳晥鏃ユ湡 {}: {} -> {}", key, val, fixed);
+ }
+ }
+ // 淇鍚堝悓缂栧彿涓殑鏃ユ湡: CG-20230601-001 -> CG-YYYYMMDD-001
+ for (String key : java.util.Set.of("purchaseContractNumber", "salesContractNo", "standardNo", "batchNo")) {
+ String val = entity.getString(key);
+ if (val != null && val.matches(".*\\d{8}.*")) {
+ String datePart = val.replaceAll(".*?(\\d{8}).*", "$1");
+ try {
+ // 楠岃瘉鎻愬彇鍒扮殑鏄湁鏁堟棩鏈�
+ String dateStr = datePart.substring(0, 4) + "-" + datePart.substring(4, 6) + "-" + datePart.substring(6, 8);
+ LocalDate d = LocalDate.parse(dateStr);
+ if (d.isBefore(start) || d.isAfter(end)) {
+ LocalDate fixed = start.plusDays(ThreadLocalRandom.current().nextLong(daysBetween + 1));
+ String newDatePart = fixed.format(java.time.format.DateTimeFormatter.BASIC_ISO_DATE);
+ String newVal = val.replace(datePart, newDatePart);
+ entity.put(key, newVal);
+ log.debug("淇缂栧彿 {}: {} -> {}", key, val, newVal);
+ }
+ } catch (Exception ignored) {
+ }
+ }
+ }
+ }
+ }
+
// ---- Tier 0: 鍩虹鏁版嵁 ----
+
+ /**
+ * 浠庢暟鎹簱鍔犺浇宸叉湁瀹㈡埛鍚嶇О鈫扞D鏄犲皠
+ */
+ private Map<String, Long> loadExistingCustomers() {
+ Map<String, Long> map = new HashMap<>();
+ List<Customer> customers = customerService.list();
+ for (Customer c : customers) {
+ if (c.getCustomerName() != null) {
+ map.put(c.getCustomerName(), c.getId());
+ }
+ }
+ return map;
+ }
+
+ /**
+ * 浠庢暟鎹簱鍔犺浇宸叉湁渚涘簲鍟嗗悕绉扳啋ID鏄犲皠
+ */
+ private Map<String, Long> loadExistingSuppliers() {
+ Map<String, Long> map = new HashMap<>();
+ List<SupplierManage> suppliers = supplierService.list();
+ for (SupplierManage s : suppliers) {
+ if (s.getSupplierName() != null) {
+ map.put(s.getSupplierName(), s.getId());
+ }
+ }
+ return map;
+ }
+
+ /**
+ * 鍔犺浇绯荤粺鐢ㄦ埛淇℃伅锛堝惈瑙掕壊鍜岄儴闂ㄥ悕绉帮級
+ */
+ private List<SysUser> loadSystemUsersWithDetail() {
+ return sysUserMapper.selectUserListWithDetail();
+ }
+
+ /**
+ * 鏋勫缓浜у搧瑙勬牸ID鈫掗《绾т骇鍝佸垎绫诲悕绉扮殑鏄犲皠
+ * 閫氳繃Product鏍戝悜涓婃壘鍒版牴鑺傜偣锛屽垽鏂�"鎴愬搧"/"鍘熸潗鏂�"/"鍗婃垚鍝�"
+ */
+ private Map<Long, String> buildProductModelCategoryMap() {
+ // 鍔犺浇鎵�鏈塒roduct鑺傜偣
+ List<Product> allProducts = productMapper.selectList(null);
+ Map<Long, Product> productMap = allProducts.stream()
+ .collect(Collectors.toMap(Product::getId, p -> p, (a, b) -> a));
+
+ // 瀵规瘡涓狿roduct锛屾部parentId鍚戜笂鎵惧埌鏍硅妭鐐瑰悕绉�
+ Map<Long, String> productIdToRootName = new HashMap<>();
+ for (Product p : allProducts) {
+ if (productIdToRootName.containsKey(p.getId())) continue;
+ // 鍚戜笂閬嶅巻鎵炬牴
+ List<Long> chain = new ArrayList<>();
+ Long currentId = p.getId();
+ while (currentId != null) {
+ chain.add(currentId);
+ Product current = productMap.get(currentId);
+ if (current == null || current.getParentId() == null) break;
+ currentId = current.getParentId();
+ }
+ // 鏍硅妭鐐圭殑productName灏辨槸鍒嗙被鍚�
+ Product root = productMap.get(chain.get(chain.size() - 1));
+ String rootName = root != null ? root.getProductName() : "鍏朵粬";
+ for (Long id : chain) {
+ productIdToRootName.put(id, rootName);
+ }
+ }
+
+ // 瀵规瘡涓狿roductModel锛岄�氳繃productId鎵惧埌鍏舵墍灞炲垎绫�
+ List<ProductModel> allModels = productModelMapper.selectList(null);
+ Map<Long, String> result = new HashMap<>();
+ for (ProductModel m : allModels) {
+ String category = m.getProductId() != null
+ ? productIdToRootName.getOrDefault(m.getProductId(), "鍏朵粬")
+ : "鍏朵粬";
+ result.put(m.getId(), category);
+ }
+ return result;
+ }
private ModuleSummary createCustomers(List<JSONObject> items, Map<String, Long> nameToId) {
int success = 0, fail = 0;
@@ -232,7 +463,10 @@
c.setTaxpayerIdentificationNumber(item.getString("taxpayerIdentificationNumber"));
c.setMaintainer(item.getString("maintainer"));
if (item.containsKey("maintenanceTime")) {
- c.setMaintenanceTime(java.sql.Date.valueOf(item.getString("maintenanceTime")));
+ String mtStr = item.getString("maintenanceTime");
+ if (mtStr != null && mtStr.matches("\\d{4}-\\d{2}-\\d{2}")) {
+ c.setMaintenanceTime(java.sql.Date.valueOf(mtStr));
+ }
} else {
c.setMaintenanceTime(new java.sql.Date(System.currentTimeMillis()));
}
@@ -309,7 +543,7 @@
// ---- Tier 1: 涓氬姟鍗曟嵁 ----
- private ModuleSummary createSalesLedgers(List<JSONObject> items, Map<String, Long> customerNameToId) {
+ private ModuleSummary createSalesLedgers(List<JSONObject> items, Map<String, Long> customerNameToId, String dateStart) {
int success = 0, fail = 0;
for (JSONObject item : items) {
try {
@@ -323,20 +557,56 @@
dto.setSalesman(item.getString("salesman"));
dto.setPaymentMethod(item.getString("paymentMethod"));
dto.setType(item.getInteger("type"));
- // 褰曞叆浜猴細浼樺厛浣跨敤AI鎻愪緵鐨勬暟鎹紝鍚﹀垯鐢ㄥ綋鍓嶇櫥褰曠敤鎴�
- if (item.containsKey("entryPerson")) {
- dto.setEntryPerson(item.getString("entryPerson"));
+
+ // 褰曞叆浜猴細浼樺厛鐢ˋI杩斿洖鐨勶紝鍚﹀垯浠�"閿�鍞�"瑙掕壊/閮ㄩ棬闅忔満閫�
+ String entryPerson = item.getString("entryPerson");
+ if (entryPerson == null || entryPerson.isBlank()) {
+ SysUser salesUser = randomUserByKeyword("閿�鍞�");
+ entryPerson = salesUser != null ? salesUser.getNickName() : "绯荤粺";
}
+ dto.setEntryPerson(entryPerson);
+
+ // 涓氬姟鍛橈細浼樺厛鐢ˋI杩斿洖鐨勶紝鍚﹀垯浠�"閿�鍞�"瑙掕壊/閮ㄩ棬闅忔満閫�
+ String salesman = dto.getSalesman();
+ if (salesman == null || salesman.isBlank()) {
+ SysUser salesUser = randomUserByKeyword("閿�鍞�");
+ salesman = salesUser != null ? salesUser.getNickName() : "绯荤粺";
+ dto.setSalesman(salesman);
+ }
+ // customerId涓簄ull浼氬鑷�"瀹㈡埛涓嶅瓨鍦�"寮傚父锛岃烦杩�
+ if (customerId == null) {
+ log.warn("璺宠繃閿�鍞彴璐︼紝瀹㈡埛[{}]涓嶅瓨鍦�", customerName);
+ fail++;
+ continue;
+ }
+ LocalDate entryDate = null;
if (item.containsKey("entryDate")) {
- dto.setEntryDate(java.sql.Date.valueOf(item.getString("entryDate")));
+ String entryDateStr = item.getString("entryDate");
+ if (entryDateStr != null && entryDateStr.matches("\\d{4}-\\d{2}-\\d{2}")) {
+ entryDate = LocalDate.parse(entryDateStr);
+ dto.setEntryDate(java.sql.Date.valueOf(entryDateStr));
+ } else {
+ dto.setEntryDate(java.sql.Date.valueOf(dateStart));
+ }
}
if (item.containsKey("executionDate")) {
- dto.setExecutionDate(LocalDate.parse(item.getString("executionDate")));
+ String execDateStr = item.getString("executionDate");
+ if (execDateStr != null && execDateStr.matches("\\d{4}-\\d{2}-\\d{2}")) {
+ dto.setExecutionDate(LocalDate.parse(execDateStr));
+ } else {
+ dto.setExecutionDate(LocalDate.parse(dateStart));
+ }
}
if (item.containsKey("deliveryDate")) {
- dto.setDeliveryDate(LocalDate.parse(item.getString("deliveryDate")));
+ String delDateStr = item.getString("deliveryDate");
+ if (delDateStr != null && delDateStr.matches("\\d{4}-\\d{2}-\\d{2}")) {
+ dto.setDeliveryDate(LocalDate.parse(delDateStr));
+ } else {
+ dto.setDeliveryDate(LocalDate.parse(dateStart));
+ }
}
JSONArray productData = item.getJSONArray("productData");
+ boolean hasProduction = false;
if (productData != null) {
List<SalesLedgerProduct> products = new ArrayList<>();
for (int i = 0; i < productData.size(); i++) {
@@ -353,7 +623,6 @@
if (pd.containsKey("taxExclusiveTotalPrice")) {
slp.setTaxExclusiveTotalPrice(pd.getBigDecimal("taxExclusiveTotalPrice"));
} else if (pd.getBigDecimal("taxInclusiveTotalPrice") != null && pd.getBigDecimal("taxRate") != null) {
- // 涓嶅惈绋庢�讳环 = 鍚◣鎬讳环 / (1 + 绋庣巼/100)
slp.setTaxExclusiveTotalPrice(
pd.getBigDecimal("taxInclusiveTotalPrice").divide(
BigDecimal.ONE.add(pd.getBigDecimal("taxRate").divide(new BigDecimal("100"), 4, RoundingMode.HALF_UP)),
@@ -361,22 +630,603 @@
} else {
slp.setTaxExclusiveTotalPrice(BigDecimal.ZERO);
}
+ slp.setIsProduction(true);
products.add(slp);
+ hasProduction = true;
}
dto.setProductData(products);
}
salesLedgerService.addOrUpdateSalesLedger(dto);
+ // addOrUpdateSalesLedger鍐呴儴浼氳嚜鍔ㄧ敓鎴愬悎鍚屽彿骞秈nsert锛屼絾dto涓婃病鏈夊洖鍐�
+ // 鐩存帴鐢╠to鐨別ntryDate鍜宑ustomerId鏌ユ渶鏂板垱寤虹殑璁板綍
+ SalesLedger savedLedger = salesLedgerMapper.selectOne(
+ new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<SalesLedger>()
+ .eq(SalesLedger::getCustomerId, dto.getCustomerId())
+ .orderByDesc(SalesLedger::getId)
+ .last("limit 1"));
+ if (savedLedger != null && hasProduction) {
+ processSalesFullFlow(savedLedger, entryDate);
+ }
success++;
} catch (Exception e) {
- log.warn("鍒涘缓閿�鍞彴璐﹀け璐�: {}", e.getMessage());
+ log.warn("鍒涘缓閿�鍞彴璐﹀け璐�: {}", e.getMessage(), e);
fail++;
}
}
return summary("sales", "閿�鍞彴璐�", items.size(), success, fail);
}
+ // ==================== 閿�鍞畬鏁存祦绋� ====================
+
+ /**
+ * 閿�鍞畬鏁存祦绋�: 鐢熶骇璁″垝鍚堝苟涓嬪彂 鈫� 棰嗘枡 鈫� 鎶ュ伐 鈫� 璐ㄦ(鍙��) 鈫� 鍏ュ簱 鈫� 鍙戣揣 鈫� 鍑哄簱
+ * 鏃堕棿浠ラ攢鍞綍鍏ユ棩鏈熶负鍩哄噯锛屽悇鐜妭閫掓帹0-3澶�
+ */
+ private void processSalesFullFlow(SalesLedger salesLedger, LocalDate entryDate) {
+ try {
+ LocalDate baseDate = entryDate != null ? entryDate : LocalDate.now();
+
+ // 1. 鏌ヨ閿�鍞彴璐︿骇鍝侊紙鍚敓浜ц鍒掞級
+ List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(
+ new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<SalesLedgerProduct>()
+ .eq(SalesLedgerProduct::getSalesLedgerId, salesLedger.getId())
+ .eq(SalesLedgerProduct::getIsProduction, true));
+ if (products.isEmpty()) {
+ log.info("閿�鍞彴璐{}]鏃犻渶鐢熶骇锛岃烦杩囩敓浜ф祦绋�", salesLedger.getSalesContractNo());
+ return;
+ }
+
+ // 妫�鏌ヤ骇鍝佹槸鍚﹀叿澶囧畬鏁寸殑宸ヨ壓鏁版嵁锛堝伐鑹鸿矾绾裤�佸伐搴忋�丅OM锛�
+ List<Long> missingTechProductIds = checkTechnologyDataReadiness(products);
+ if (!missingTechProductIds.isEmpty()) {
+ log.warn("閿�鍞彴璐{}]浠ヤ笅浜у搧缂哄皯宸ヨ壓鏁版嵁锛堝伐鑹鸿矾绾�/宸ュ簭/BOM锛夛紝璺宠繃鐢熶骇娴佺▼: {}",
+ salesLedger.getSalesContractNo(), missingTechProductIds);
+ return;
+ }
+
+ // 2. 鐢熶骇璁″垝鍚堝苟涓嬪彂 鈫� 鐢熶骇璁㈠崟
+ LocalDate planDate = baseDate.plusDays(ThreadLocalRandom.current().nextInt(0, 4));
+ processProductionCombine(salesLedger, planDate);
+
+ // 3. 棰嗘枡锛堢墿鏂欎笉瓒宠嚜鍔ㄥ叆搴撳悗鍐嶉锛�
+ LocalDate pickDate = planDate.plusDays(ThreadLocalRandom.current().nextInt(0, 3));
+ processMaterialPick(salesLedger, pickDate);
+
+ // 4. 鐢熶骇鎶ュ伐
+ LocalDate reportDate = pickDate.plusDays(ThreadLocalRandom.current().nextInt(1, 4));
+ processProductionReport(salesLedger, reportDate);
+
+ // 5. 璐ㄦ鎻愪氦 + 鍏ュ簱瀹℃壒
+ LocalDate qualityDate = reportDate.plusDays(ThreadLocalRandom.current().nextInt(0, 4));
+ processSalesQualityAndStockIn(salesLedger, qualityDate);
+
+ // 6. 鍙戣揣 + 鍙戣揣瀹℃壒 + 鍑哄簱瀹℃壒
+ LocalDate shipDate = qualityDate.plusDays(ThreadLocalRandom.current().nextInt(0, 4));
+ processSalesShipping(salesLedger, shipDate);
+
+ log.info("閿�鍞彴璐{}]瀹屾暣娴佺▼澶勭悊瀹屾瘯", salesLedger.getSalesContractNo());
+ } catch (Exception e) {
+ log.warn("閿�鍞畬鏁存祦绋嬪鐞嗗け璐{}]: {}", salesLedger.getSalesContractNo(), e.getMessage());
+ }
+ }
+
+ /**
+ * 鏌ヨ瑙掕壊鎴栭儴闂ㄥ惈鎸囧畾鍏抽敭瀛楃殑鐢ㄦ埛锛岄殢鏈鸿繑鍥炰竴涓�
+ */
+ private SysUser randomUserByKeyword(String keyword) {
+ try {
+ List<Long> userIds = new ArrayList<>(sysUserMapper.getUserByRole(keyword));
+
+ List<SysDept> depts = sysDeptMapper.selectList(
+ new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<SysDept>()
+ .like(SysDept::getDeptName, keyword)
+ .eq(SysDept::getDelFlag, "0")
+ .eq(SysDept::getStatus, "0"));
+ if (!depts.isEmpty()) {
+ List<Long> deptIds = depts.stream().map(SysDept::getDeptId).collect(Collectors.toList());
+ List<Long> deptUserIds = sysUserDeptMapper.selectDistinctUserIdsByDeptIds(deptIds);
+ userIds.addAll(deptUserIds);
+ }
+
+ if (userIds.isEmpty()) {
+ return null;
+ }
+ List<Long> distinctIds = userIds.stream().distinct().collect(Collectors.toList());
+ Long randomId = distinctIds.get(ThreadLocalRandom.current().nextInt(distinctIds.size()));
+ return sysUserMapper.selectUserById(randomId);
+ } catch (Exception e) {
+ log.warn("鏌ヨ[{}]瑙掕壊/閮ㄩ棬鐢ㄦ埛澶辫触: {}", keyword, e.getMessage());
+ return null;
+ }
+ }
+
+ /**
+ * 鏌ヨ瑙掕壊鎴栭儴闂ㄥ惈"鐢熶骇"鐨勭敤鎴凤紝闅忔満杩斿洖涓�涓�
+ */
+ private SysUser randomProductionUser() {
+ return randomUserByKeyword("鐢熶骇");
+ }
+
+ /**
+ * 妫�鏌ヤ骇鍝佹槸鍚﹀叿澶囧畬鏁寸殑宸ヨ壓鏁版嵁锛堝伐鑹鸿矾绾裤�佸伐搴忋�丅OM锛�
+ * @return 缂哄皯宸ヨ壓鏁版嵁鐨勪骇鍝佽鏍糏D鍒楄〃锛堢┖鍒楄〃琛ㄧず鍏ㄩ儴灏辩华锛�
+ */
+ private List<Long> checkTechnologyDataReadiness(List<SalesLedgerProduct> products) {
+ List<Long> missingIds = new ArrayList<>();
+ for (SalesLedgerProduct slp : products) {
+ Long productModelId = slp.getProductModelId();
+ if (productModelId == null) continue;
+
+ // 1. 妫�鏌ュ伐鑹鸿矾绾�
+ List<com.ruoyi.technology.pojo.TechnologyRouting> routings =
+ technologyRoutingMapper.selectList(
+ new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<com.ruoyi.technology.pojo.TechnologyRouting>()
+ .eq(com.ruoyi.technology.pojo.TechnologyRouting::getProductModelId, productModelId));
+ if (routings.isEmpty()) {
+ log.warn("浜у搧瑙勬牸[{}]缂哄皯宸ヨ壓璺嚎", productModelId);
+ missingIds.add(productModelId);
+ continue;
+ }
+ Long routingId = routings.get(0).getId();
+
+ // 2. 妫�鏌ュ伐鑹鸿矾绾挎槸鍚︽湁鍏宠仈宸ュ簭
+ List<com.ruoyi.technology.pojo.TechnologyRoutingOperation> routingOps =
+ technologyRoutingOperationMapper.selectList(
+ new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<com.ruoyi.technology.pojo.TechnologyRoutingOperation>()
+ .eq(com.ruoyi.technology.pojo.TechnologyRoutingOperation::getTechnologyRoutingId, routingId));
+ if (routingOps.isEmpty()) {
+ log.warn("浜у搧瑙勬牸[{}]宸ヨ壓璺嚎[{}]缂哄皯宸ュ簭", productModelId, routingId);
+ missingIds.add(productModelId);
+ continue;
+ }
+
+ // 3. 妫�鏌OM锛堝彲閫変絾鏈夋洿濂斤級
+ com.ruoyi.technology.pojo.TechnologyRouting routing = routings.get(0);
+ if (routing.getBomId() != null) {
+ List<com.ruoyi.technology.pojo.TechnologyBomStructure> bomStructures =
+ technologyBomStructureMapper.selectList(
+ new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<com.ruoyi.technology.pojo.TechnologyBomStructure>()
+ .eq(com.ruoyi.technology.pojo.TechnologyBomStructure::getBomId, routing.getBomId()));
+ if (bomStructures.isEmpty()) {
+ log.warn("浜у搧瑙勬牸[{}]BOM[{}]缂哄皯浜у搧缁撴瀯", productModelId, routing.getBomId());
+ missingIds.add(productModelId);
+ }
+ }
+ }
+ return missingIds;
+ }
+
+ /**
+ * 鐢熶骇璁″垝鍚堝苟涓嬪彂 鈫� 鐢熶骇璁㈠崟锛堟寜productModelId鍒嗙粍锛屽悓鍨嬪彿鍚堝苟涓嬪彂锛�
+ */
+ private void processProductionCombine(SalesLedger salesLedger, LocalDate planDate) {
+ try {
+ List<ProductionPlan> plans = productionPlanMapper.selectList(
+ new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<ProductionPlan>()
+ .eq(ProductionPlan::getSalesLedgerId, salesLedger.getId())
+ .and(w -> w.eq(ProductionPlan::getStatus, 0).or().isNull(ProductionPlan::getStatus)));
+ if (plans.isEmpty()) {
+ log.info("閿�鍞彴璐{}]鏃犲緟涓嬪彂鐢熶骇璁″垝", salesLedger.getSalesContractNo());
+ return;
+ }
+
+ // 鎸塸roductModelId鍒嗙粍锛屽悓鍨嬪彿鎵嶈兘鍚堝苟涓嬪彂锛沺roductModelId涓簄ull鐨勫崟鐙�愪釜涓嬪彂
+ Map<Long, List<ProductionPlan>> grouped = plans.stream()
+ .filter(p -> p.getProductModelId() != null)
+ .collect(Collectors.groupingBy(ProductionPlan::getProductModelId));
+
+ for (Map.Entry<Long, List<ProductionPlan>> entry : grouped.entrySet()) {
+ try {
+ List<ProductionPlan> sameModelPlans = entry.getValue();
+ BigDecimal totalQty = sameModelPlans.stream()
+ .map(p -> Optional.ofNullable(p.getQtyRequired()).orElse(BigDecimal.ZERO))
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
+ ProductionPlanDto combineDto = new ProductionPlanDto();
+ combineDto.setIds(sameModelPlans.stream().map(ProductionPlan::getId).collect(Collectors.toList()));
+ combineDto.setTotalAssignedQuantity(totalQty);
+ combineDto.setPlanCompleteTime(planDate.plusDays(ThreadLocalRandom.current().nextInt(3, 7)));
+ productionPlanService.combine(combineDto);
+
+ // 淇鐢熶骇璁㈠崟鐨刾lanCompleteTime
+ List<ProductionOrder> orders = productionOrderMapper.selectList(
+ new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<ProductionOrder>()
+ .like(ProductionOrder::getProductionPlanIds, String.valueOf(sameModelPlans.get(0).getId())));
+ for (ProductionOrder order : orders) {
+ order.setPlanCompleteTime(planDate.plusDays(ThreadLocalRandom.current().nextInt(3, 7)));
+ order.setStartTime(planDate.atStartOfDay());
+ productionOrderMapper.updateById(order);
+ }
+ log.info("閿�鍞彴璐{}]鐢熶骇璁″垝涓嬪彂鎴愬姛, productModelId={}, 璁″垝鏁�: {}",
+ salesLedger.getSalesContractNo(), entry.getKey(), sameModelPlans.size());
+ } catch (Exception e) {
+ log.warn("閿�鍞彴璐{}]鐢熶骇璁″垝涓嬪彂澶辫触, productModelId={}: {}",
+ salesLedger.getSalesContractNo(), entry.getKey(), e.getMessage());
+ }
+ }
+ } catch (Exception e) {
+ log.warn("鐢熶骇璁″垝涓嬪彂澶辫触[{}]: {}", salesLedger.getSalesContractNo(), e.getMessage());
+ }
+ }
+
+ /**
+ * 棰嗘枡: 鏌ヨ鐢熶骇璁㈠崟鐨凚OM棰嗘枡娓呭崟锛屾鏌ュ簱瀛橈紝涓嶈冻鍒欏厛鑷姩鍏ュ簱瀹℃壒鍚庡啀棰嗘枡
+ */
+ private void processMaterialPick(SalesLedger salesLedger, LocalDate pickDate) {
+ try {
+ List<ProductionOrder> orders = findOrdersForSalesLedger(salesLedger);
+ if (orders.isEmpty()) {
+ log.info("閿�鍞彴璐{}]鏃犵敓浜ц鍗曪紝璺宠繃棰嗘枡", salesLedger.getSalesContractNo());
+ return;
+ }
+
+ for (ProductionOrder order : orders) {
+ try {
+ // 鏌ヨ璁㈠崟BOM棰嗘枡娓呭崟
+ List<com.ruoyi.production.bean.vo.ProductionOrderPickVo> pickList = productionOrderService.pick(order.getId());
+ if (pickList == null || pickList.isEmpty()) {
+ log.info("鐢熶骇璁㈠崟[{}]鏃犻鏂欐竻鍗�", order.getId());
+ continue;
+ }
+
+ // 妫�鏌ュ簱瀛樹笉瓒崇殑鐗╂枡锛屽厛鑷姩鍏ュ簱
+ ensureMaterialStock(pickList, pickDate);
+
+ // 閲嶆柊鑾峰彇棰嗘枡娓呭崟锛堝叆搴撳悗鎵瑰彿鍜屽簱瀛橀噺宸叉洿鏂帮級
+ pickList = productionOrderService.pick(order.getId());
+ if (pickList == null || pickList.isEmpty()) {
+ log.info("鐢熶骇璁㈠崟[{}]閲嶆柊鑾峰彇棰嗘枡娓呭崟涓虹┖", order.getId());
+ continue;
+ }
+
+ // 鎵ц棰嗘枡
+ List<ProductionOrderPickDto> pickDtoList = new ArrayList<>();
+ for (com.ruoyi.production.bean.vo.ProductionOrderPickVo pickVo : pickList) {
+ ProductionOrderPickDto pickDto = new ProductionOrderPickDto();
+ pickDto.setProductionOrderId(order.getId());
+ pickDto.setProductModelId(pickVo.getProductModelId());
+ pickDto.setPickQuantity(pickVo.getDemandedQuantity());
+ pickDto.setPickType((byte) 1);
+ pickDto.setOperationName(pickVo.getOperationName());
+ pickDto.setTechnologyOperationId(pickVo.getTechnologyOperationId());
+ pickDto.setDemandedQuantity(pickVo.getDemandedQuantity());
+ pickDto.setBom(pickVo.getBom());
+ // 璁剧疆鎵瑰彿锛堢敤鏇存柊鍚庣殑鎵瑰彿鍒楄〃锛�
+ if (pickVo.getBatchNoList() != null && !pickVo.getBatchNoList().isEmpty()) {
+ pickDto.setBatchNoList(pickVo.getBatchNoList());
+ pickDto.setBatchNo(pickVo.getBatchNoList().get(0));
+ }
+ pickDtoList.add(pickDto);
+ }
+
+ if (!pickDtoList.isEmpty()) {
+ ProductionOrderPickDto batchDto = new ProductionOrderPickDto();
+ batchDto.setPickList(pickDtoList);
+ productionOrderPickService.savePick(batchDto);
+ log.info("鐢熶骇璁㈠崟[{}]棰嗘枡鎴愬姛, 棰嗘枡椤规暟: {}", order.getId(), pickDtoList.size());
+ }
+ } catch (Exception e) {
+ log.warn("鐢熶骇璁㈠崟[{}]棰嗘枡澶辫触: {}", order.getId(), e.getMessage());
+ }
+ }
+ } catch (Exception e) {
+ log.warn("棰嗘枡娴佺▼澶辫触[{}]: {}", salesLedger.getSalesContractNo(), e.getMessage());
+ }
+ }
+
+ /**
+ * 纭繚鐗╂枡搴撳瓨鍏呰冻锛屼笉瓒冲垯鍏堣嚜鍔ㄥ叆搴撳鎵�
+ */
+ private void ensureMaterialStock(List<com.ruoyi.production.bean.vo.ProductionOrderPickVo> pickList, LocalDate pickDate) {
+ LocalDateTime pickDateTime = pickDate.atTime(9, 0, 0).plusMinutes(ThreadLocalRandom.current().nextInt(0, 480));
+ String pickDateStr = pickDate.format(DateTimeFormatter.BASIC_ISO_DATE);
+
+ for (com.ruoyi.production.bean.vo.ProductionOrderPickVo pickVo : pickList) {
+ BigDecimal demanded = pickVo.getDemandedQuantity() != null ? pickVo.getDemandedQuantity() : BigDecimal.ZERO;
+ BigDecimal stockQty = pickVo.getStockQuantity() != null ? pickVo.getStockQuantity() : BigDecimal.ZERO;
+ BigDecimal shortage = demanded.subtract(stockQty);
+
+ if (shortage.compareTo(BigDecimal.ZERO) <= 0) {
+ continue; // 搴撳瓨鍏呰冻
+ }
+
+ // 搴撳瓨涓嶈冻锛岃嚜鍔ㄥ叆搴撹ˉ鍏�
+ try {
+ StockInventoryDto dto = new StockInventoryDto();
+ dto.setProductModelId(pickVo.getProductModelId());
+ dto.setQualitity(shortage);
+ dto.setRecordType(StockInQualifiedRecordTypeEnum.CUSTOMIZATION_STOCK_IN.getCode());
+ dto.setRecordId(0L);
+ stockInventoryService.addStockInRecordOnly(dto);
+
+ // 鏌ユ壘鍒氬垱寤虹殑鍏ュ簱璁板綍
+ List<com.ruoyi.stock.pojo.StockInRecord> records = stockInRecordService.list(
+ new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<com.ruoyi.stock.pojo.StockInRecord>()
+ .eq(com.ruoyi.stock.pojo.StockInRecord::getProductModelId, pickVo.getProductModelId())
+ .eq(com.ruoyi.stock.pojo.StockInRecord::getApprovalStatus, 0)
+ .orderByDesc(com.ruoyi.stock.pojo.StockInRecord::getId)
+ .last("limit 1"));
+ if (!records.isEmpty()) {
+ com.ruoyi.stock.pojo.StockInRecord record = records.get(0);
+ record.setCreateTime(pickDateTime);
+ record.setBatchNo(fixBatchNoDate(record.getBatchNo(), pickDateStr));
+ record.setInboundBatches(fixBatchNoDate(record.getInboundBatches(), pickDateStr));
+ stockInRecordMapper.updateById(record);
+ // 瀹℃壒閫氳繃
+ stockInRecordService.batchApprove(List.of(record.getId()), ReviewStatusEnum.APPROVED.getCode());
+ log.info("鐗╂枡[{}]鑷姩鍏ュ簱瀹℃壒瀹屾垚, 鍏ュ簱鏁伴噺: {}", pickVo.getProductModelId(), shortage);
+ }
+ } catch (Exception e) {
+ log.warn("鐗╂枡[{}]鑷姩鍏ュ簱澶辫触: {}", pickVo.getProductModelId(), e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * 鐢熶骇鎶ュ伐: 閬嶅巻宸ュ崟閫愪釜鎶ュ伐锛屼粠鐢熶骇瑙掕壊鐢ㄦ埛涓殢鏈洪�夊彇鎶ュ伐浜�
+ */
+ private void processProductionReport(SalesLedger salesLedger, LocalDate reportDate) {
+ try {
+ List<ProductionOrder> orders = findOrdersForSalesLedger(salesLedger);
+ if (orders.isEmpty()) {
+ log.info("閿�鍞彴璐{}]鏃犵敓浜ц鍗�", salesLedger.getSalesContractNo());
+ return;
+ }
+
+ for (ProductionOrder order : orders) {
+ List<ProductionOperationTask> tasks = productionOperationTaskMapper.selectList(
+ new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<ProductionOperationTask>()
+ .eq(ProductionOperationTask::getProductionOrderId, order.getId())
+ .orderByAsc(ProductionOperationTask::getId));
+ for (ProductionOperationTask task : tasks) {
+ if (task.getStatus() != null && task.getStatus() >= 3) continue;
+
+ // 姣忔鎶ュ伐闅忔満閫変竴涓敓浜х敤鎴�
+ SysUser productionUser = randomProductionUser();
+ Long userId = productionUser != null ? productionUser.getUserId() : 1L;
+ String userName = productionUser != null ? productionUser.getNickName() : "绯荤粺";
+
+ // 鎶ュ伐
+ ProductionProductMainDto reportDto = new ProductionProductMainDto();
+ reportDto.setProductionOperationTaskId(task.getId());
+ reportDto.setQuantity(task.getPlanQuantity());
+ reportDto.setScrapQty(BigDecimal.ZERO);
+ reportDto.setUserId(userId);
+ reportDto.setUserName(userName);
+ productionProductMainService.addProductMain(reportDto);
+
+ // 淇鎶ュ伐鏃堕棿锛堥噸鏂颁粠DB璇诲彇锛岄伩鍏嶈鐩朼ddProductMain鏇存柊鐨刢ompleteQuantity锛�
+ fixProductionReportTimes(task.getId(), reportDate);
+ }
+ // 淇鐢熶骇璁㈠崟鏃堕棿锛堥噸鏂颁粠DB璇诲彇锛岄伩鍏嶈鐩朼ddProductMain鏇存柊鐨刢ompleteQuantity锛�
+ fixProductionOrderTimes(order.getId(), reportDate);
+ }
+ log.info("閿�鍞彴璐{}]鐢熶骇鎶ュ伐瀹屾垚, 璁㈠崟鏁�: {}", salesLedger.getSalesContractNo(), orders.size());
+ } catch (Exception e) {
+ log.warn("鐢熶骇鎶ュ伐澶辫触[{}]: {}", salesLedger.getSalesContractNo(), e.getMessage());
+ }
+ }
+
+ /**
+ * 鏌ユ壘閿�鍞彴璐﹀叧鑱旂殑鐢熶骇璁㈠崟
+ */
+ private List<ProductionOrder> findOrdersForSalesLedger(SalesLedger salesLedger) {
+ List<ProductionOrder> orders = new ArrayList<>();
+ List<ProductionPlan> plans = productionPlanMapper.selectList(
+ new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<ProductionPlan>()
+ .eq(ProductionPlan::getSalesLedgerId, salesLedger.getId()));
+ for (ProductionPlan plan : plans) {
+ List<ProductionOrder> po = productionOrderMapper.selectList(
+ new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<ProductionOrder>()
+ .like(ProductionOrder::getProductionPlanIds, String.valueOf(plan.getId())));
+ orders.addAll(po);
+ }
+ // 鍘婚噸
+ return orders.stream()
+ .collect(Collectors.toMap(ProductionOrder::getId, o -> o, (a, b) -> a))
+ .values().stream().collect(Collectors.toList());
+ }
+
+ /**
+ * 淇鐢熶骇鎶ュ伐鐩稿叧鏃堕棿锛堥噸鏂颁粠DB璇诲彇task锛岄伩鍏嶈鐩朼ddProductMain宸叉洿鏂扮殑completeQuantity锛�
+ */
+ private void fixProductionReportTimes(Long taskId, LocalDate reportDate) {
+ try {
+ ProductionOperationTask freshTask = productionOperationTaskMapper.selectById(taskId);
+ if (freshTask != null) {
+ freshTask.setActualStartTime(reportDate);
+ freshTask.setActualEndTime(reportDate);
+ freshTask.setStatus(4);
+ productionOperationTaskMapper.updateById(freshTask);
+ }
+ } catch (Exception e) {
+ log.warn("淇鐢熶骇鎶ュ伐鏃堕棿澶辫触: {}", e.getMessage());
+ }
+ }
+
+ /**
+ * 淇鐢熶骇璁㈠崟鏃堕棿锛堥噸鏂颁粠DB璇诲彇order锛岄伩鍏嶈鐩朼ddProductMain宸叉洿鏂扮殑completeQuantity锛�
+ */
+ private void fixProductionOrderTimes(Long orderId, LocalDate reportDate) {
+ try {
+ ProductionOrder freshOrder = productionOrderMapper.selectById(orderId);
+ if (freshOrder != null) {
+ freshOrder.setStartTime(reportDate.minusDays(1).atStartOfDay());
+ freshOrder.setEndTime(reportDate.plusDays(1).atStartOfDay());
+ freshOrder.setStatus(3);
+ productionOrderMapper.updateById(freshOrder);
+ }
+ } catch (Exception e) {
+ log.warn("淇鐢熶骇璁㈠崟鏃堕棿澶辫触: {}", e.getMessage());
+ }
+ }
+
+ /**
+ * 閿�鍞川妫�鎻愪氦 + 鍏ュ簱瀹℃壒
+ */
+ private void processSalesQualityAndStockIn(SalesLedger salesLedger, LocalDate qualityDate) {
+ try {
+ LocalDateTime qualityDateTime = qualityDate.atTime(9, 0, 0)
+ .plusMinutes(ThreadLocalRandom.current().nextInt(0, 480));
+
+ // 鏌ユ墍鏈夋湭鎻愪氦鐨勮川妫�鍗曪紙inspectType=1杩囩▼妫�楠�, 2=鍑哄巶妫�楠岋紝鐢辩敓浜ф姤宸ョ敓鎴愶級
+ List<QualityInspect> allUnsubmitted = qualityInspectService.list(
+ new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<QualityInspect>()
+ .eq(QualityInspect::getInspectState, 0)
+ .in(QualityInspect::getInspectType, java.util.Arrays.asList(1, 2)));
+ for (QualityInspect qi : allUnsubmitted) {
+ qualityInspectService.autoSubmit(qi.getId());
+ qi.setCreateTime(qualityDateTime);
+ qualityInspectMapper.updateById(qi);
+ }
+ log.info("閿�鍞彴璐{}]璐ㄦ鎻愪氦瀹屾垚, 璐ㄦ鍗曟暟: {}", salesLedger.getSalesContractNo(), allUnsubmitted.size());
+
+ // 鍏ュ簱瀹℃壒锛氬鎵规墍鏈夊緟瀹℃壒鐨勫叆搴撹褰�
+ LocalDate stockDate = qualityDate.plusDays(ThreadLocalRandom.current().nextInt(0, 3));
+ LocalDateTime stockDateTime = stockDate.atTime(9, 0, 0)
+ .plusMinutes(ThreadLocalRandom.current().nextInt(0, 480));
+ String stockDateStr = stockDate.format(DateTimeFormatter.BASIC_ISO_DATE);
+ List<com.ruoyi.stock.pojo.StockInRecord> stockRecords = stockInRecordService.list(
+ new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<com.ruoyi.stock.pojo.StockInRecord>()
+ .eq(com.ruoyi.stock.pojo.StockInRecord::getApprovalStatus, 0));
+ List<Long> recordIds = stockRecords.stream()
+ .map(com.ruoyi.stock.pojo.StockInRecord::getId)
+ .collect(Collectors.toList());
+ if (!recordIds.isEmpty()) {
+ for (com.ruoyi.stock.pojo.StockInRecord sr : stockRecords) {
+ sr.setCreateTime(stockDateTime);
+ sr.setBatchNo(fixBatchNoDate(sr.getBatchNo(), stockDateStr));
+ sr.setInboundBatches(fixBatchNoDate(sr.getInboundBatches(), stockDateStr));
+ stockInRecordMapper.updateById(sr);
+ }
+ stockInRecordService.batchApprove(recordIds, ReviewStatusEnum.APPROVED.getCode());
+ for (com.ruoyi.stock.pojo.StockInRecord sr : stockRecords) {
+ StockInventory si = stockInventoryMapper.selectOne(
+ new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<StockInventory>()
+ .eq(StockInventory::getProductModelId, sr.getProductModelId())
+ .eq(StockInventory::getBatchNo, sr.getBatchNo()));
+ if (si != null) {
+ si.setBatchNo(fixBatchNoDate(si.getBatchNo(), stockDateStr));
+ stockInventoryMapper.updateById(si);
+ }
+ }
+ log.info("閿�鍞彴璐{}]鍏ュ簱瀹℃壒瀹屾垚, 鍏ュ簱璁板綍鏁�: {}", salesLedger.getSalesContractNo(), recordIds.size());
+ }
+ } catch (Exception e) {
+ log.warn("閿�鍞川妫�鍏ュ簱澶辫触[{}]: {}", salesLedger.getSalesContractNo(), e.getMessage());
+ }
+ }
+
+ /**
+ * 鍙戣揣 + 鍙戣揣瀹℃壒閫氳繃 + 鍑哄簱瀹℃壒
+ */
+ private void processSalesShipping(SalesLedger salesLedger, LocalDate shipDate) {
+ try {
+ LocalDateTime shipDateTime = shipDate.atTime(9, 0, 0)
+ .plusMinutes(ThreadLocalRandom.current().nextInt(0, 480));
+ String shipDateStr = shipDate.format(DateTimeFormatter.BASIC_ISO_DATE);
+
+ // 鏌ユ壘鏈夊簱瀛樼殑浜у搧瑙勬牸
+ List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(
+ new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<SalesLedgerProduct>()
+ .eq(SalesLedgerProduct::getSalesLedgerId, salesLedger.getId()));
+
+ List<ShippingProductDetail> details = new ArrayList<>();
+ for (SalesLedgerProduct slp : products) {
+ StockInventory si = stockInventoryMapper.selectOne(
+ new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<StockInventory>()
+ .eq(StockInventory::getProductModelId, slp.getProductModelId())
+ .gt(StockInventory::getQualitity, BigDecimal.ZERO)
+ .orderByDesc(StockInventory::getId)
+ .last("limit 1"));
+ if (si != null) {
+ ShippingProductDetail detail = new ShippingProductDetail();
+ detail.setStockInventoryId(si.getId());
+ detail.setProductModelId(slp.getProductModelId());
+ detail.setBatchNo(si.getBatchNo());
+ detail.setQuantity(slp.getQuantity());
+ details.add(detail);
+ }
+ }
+ if (details.isEmpty()) {
+ log.info("閿�鍞彴璐{}]鏃犲彲鐢ㄥ簱瀛橈紝璺宠繃鍙戣揣", salesLedger.getSalesContractNo());
+ return;
+ }
+
+ // 鍒涘缓鍙戣揣鍗�
+ ShippingInfoDto shipDto = new ShippingInfoDto();
+ shipDto.setSalesLedgerId(salesLedger.getId());
+ shipDto.setSalesLedgerProductId(products.get(0).getId());
+ shipDto.setCreateTime(shipDateTime);
+ shipDto.setBatchNoDetailList(details);
+ shippingInfoService.addReq(shipDto);
+
+ // 鎵惧埌鍙戣揣鍗曞拰瀹℃壒瀹炰緥
+ ShippingInfo shippingInfo = shippingInfoMapper.selectOne(
+ new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<ShippingInfo>()
+ .eq(ShippingInfo::getShippingNo, shipDto.getShippingNo())
+ .last("limit 1"));
+ if (shippingInfo != null) {
+ shippingInfo.setCreateTime(shipDateTime);
+ shippingInfo.setShippingDate(java.sql.Date.valueOf(shipDate));
+ // 鏍规嵁瀹㈡埛鍦板潃鐢熸垚鍙戣揣杞︾墝鍙�
+ shippingInfo.setShippingCarNumber(generateCarNumber(salesLedger.getCustomerName()));
+ shippingInfoMapper.updateById(shippingInfo);
+
+ // 鍙戣揣瀹℃壒鑷姩閫氳繃
+ ApprovalInstance shipApproval = approvalInstanceMapper.selectOne(
+ new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<ApprovalInstance>()
+ .eq(ApprovalInstance::getBusinessId, shippingInfo.getId())
+ .eq(ApprovalInstance::getBusinessType, 7L)
+ .eq(ApprovalInstance::getDeleted, 0)
+ .orderByDesc(ApprovalInstance::getId)
+ .last("limit 1"));
+ if (shipApproval != null) {
+ LocalDate shipApproveDate = shipDate.plusDays(ThreadLocalRandom.current().nextInt(0, 3));
+ LocalDateTime shipApproveDateTime = shipApproveDate.atTime(9, 0, 0)
+ .plusMinutes(ThreadLocalRandom.current().nextInt(0, 480));
+ approvalInstanceService.autoApprove(shipApproval.getId());
+ fixApprovalTimes(shipApproval.getId(), shipApproveDateTime);
+
+ shippingInfo.setStatus("宸插彂璐�");
+ shippingInfo.setShippingDate(java.sql.Date.valueOf(shipApproveDate));
+ shippingInfoMapper.updateById(shippingInfo);
+ }
+
+ // 鍑哄簱瀹℃壒
+ LocalDate outDate = shipDate.plusDays(ThreadLocalRandom.current().nextInt(0, 3));
+ LocalDateTime outDateTime = outDate.atTime(9, 0, 0)
+ .plusMinutes(ThreadLocalRandom.current().nextInt(0, 480));
+ String outDateStr = outDate.format(DateTimeFormatter.BASIC_ISO_DATE);
+ List<StockOutRecord> outRecords = stockOutRecordMapper.selectList(
+ new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<StockOutRecord>()
+ .eq(StockOutRecord::getRecordId, shippingInfo.getId())
+ .eq(StockOutRecord::getRecordType,
+ String.valueOf(StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode())));
+ List<Long> outIds = new ArrayList<>();
+ for (StockOutRecord sr : outRecords) {
+ if (sr.getApprovalStatus() == null || sr.getApprovalStatus() == 0 || sr.getApprovalStatus() == 3) {
+ sr.setCreateTime(outDateTime);
+ sr.setOutboundBatches(fixBatchNoDate(sr.getOutboundBatches(), outDateStr));
+ sr.setBatchNo(fixBatchNoDate(sr.getBatchNo(), outDateStr));
+ stockOutRecordMapper.updateById(sr);
+ outIds.add(sr.getId());
+ }
+ }
+ if (!outIds.isEmpty()) {
+ // 鍑哄簱瀹℃壒閫氳繃锛堣蛋姝e紡瀹℃壒娴佺▼锛屽唴閮ㄤ細鎵e噺搴撳瓨锛�
+ stockOutRecordService.batchApprove(outIds, ReviewStatusEnum.APPROVED.getCode());
+ log.info("閿�鍞彴璐{}]鍑哄簱瀹℃壒瀹屾垚, 鍑哄簱璁板綍鏁�: {}",
+ salesLedger.getSalesContractNo(), outIds.size());
+ }
+ }
+ log.info("閿�鍞彴璐{}]鍙戣揣娴佺▼瀹屾垚", salesLedger.getSalesContractNo());
+ } catch (Exception e) {
+ log.warn("閿�鍞彂璐ф祦绋嬪け璐{}]: {}", salesLedger.getSalesContractNo(), e.getMessage());
+ }
+ }
+
private ModuleSummary createPurchaseLedgers(List<JSONObject> items, Map<String, Long> supplierNameToId,
- String additionalInfo, String dateEnd) {
+ String additionalInfo, String dateStart, String dateEnd) {
// 鏄惁闇�瑕佽川妫�锛屼粠琛ュ厖淇℃伅鍒ゆ柇锛岄粯璁や笉闇�瑕�
boolean needQualityInspect = additionalInfo != null
&& (additionalInfo.contains("璐ㄦ") || additionalInfo.contains("闇�瑕佹楠�"));
@@ -396,12 +1246,19 @@
String entryDateStr = item.getString("entryDate");
LocalDate entryDate = null;
- if (item.containsKey("entryDate")) {
+ if (item.containsKey("entryDate") && entryDateStr != null && entryDateStr.matches("\\d{4}-\\d{2}-\\d{2}")) {
entryDate = LocalDate.parse(entryDateStr);
dto.setEntryDate(java.sql.Date.valueOf(entryDateStr));
+ } else {
+ dto.setEntryDate(java.sql.Date.valueOf(dateStart));
}
if (item.containsKey("executionDate")) {
- dto.setExecutionDate(java.sql.Date.valueOf(item.getString("executionDate")));
+ String execDateStr = item.getString("executionDate");
+ if (execDateStr != null && execDateStr.matches("\\d{4}-\\d{2}-\\d{2}")) {
+ dto.setExecutionDate(java.sql.Date.valueOf(execDateStr));
+ } else {
+ dto.setExecutionDate(java.sql.Date.valueOf(dateStart));
+ }
}
JSONArray productData = item.getJSONArray("productData");
if (productData != null) {
@@ -445,7 +1302,7 @@
}
success++;
} catch (Exception e) {
- log.warn("鍒涘缓閲囪喘鍙拌处澶辫触: {}", e.getMessage());
+ log.warn("鍒涘缓閲囪喘鍙拌处澶辫触: {}", e.getMessage(), e);
fail++;
}
}
@@ -454,10 +1311,18 @@
/**
* 閲囪喘瀹屾暣娴佺▼: 瀹℃牳閫氳繃 鈫� 璐ㄦ(鍙��) 鈫� 鍏ュ簱瀹℃牳閫氳繃
+ * 鍚勭幆鑺傛椂闂翠互閲囪喘褰曞叆鏃ユ湡涓哄熀鍑嗭紝鍋跺皵鎺ㄨ繜1-3澶�
*/
private void processPurchaseFullFlow(PurchaseLedger purchaseLedger, boolean needQualityInspect,
LocalDate entryDate, String dateEnd) {
try {
+ // 鍩哄噯鏃ユ湡锛氶噰璐綍鍏ユ棩鏈燂紝涓虹┖鍒欑敤褰撳ぉ
+ LocalDate baseDate = entryDate != null ? entryDate : LocalDate.now();
+ // 瀹℃壒鏃堕棿锛氬熀浜庡綍鍏ユ棩鏈燂紝闅忔満鎺�0-3澶�
+ LocalDate approveDate = baseDate.plusDays(ThreadLocalRandom.current().nextInt(0, 4));
+ LocalDateTime approveDateTime = approveDate.atTime(9, 0, 0)
+ .plusMinutes(ThreadLocalRandom.current().nextInt(0, 480));
+
// 1. 瀹℃壒鑷姩閫氳繃
ApprovalInstance approvalInstance = approvalInstanceMapper.selectOne(
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<ApprovalInstance>()
@@ -467,21 +1332,25 @@
.orderByDesc(ApprovalInstance::getId)
.last("limit 1"));
if (approvalInstance != null) {
- // 缁撶畻瀹℃壒寮�濮嬫椂闂达細鍩轰簬褰曞叆鏃ユ湡锛岄殢鏈烘帹0-3澶�
- LocalDate baseDate = entryDate != null ? entryDate : LocalDate.now();
- LocalDate approveDate = baseDate.plusDays(ThreadLocalRandom.current().nextInt(0, 4));
- // 浣跨敤autoApprove瀹屾垚瀹℃壒
approvalInstanceService.autoApprove(approvalInstance.getId());
+ // 淇瀹℃壒鐩稿叧鏃堕棿涓洪噰璐綍鍏ユ棩鏈熻寖鍥�
+ fixApprovalTimes(approvalInstance.getId(), approveDateTime);
log.info("閲囪喘鍙拌处[{}]瀹℃壒閫氳繃, 瀹℃壒鏃ユ湡: {}", purchaseLedger.getPurchaseContractNumber(), approveDate);
}
// 2. 璐ㄦ娴佺▼锛堝鏋滈渶瑕佽川妫�锛�
if (needQualityInspect) {
- processQualityInspect(purchaseLedger, entryDate, dateEnd);
+ // 璐ㄦ鏃堕棿锛氬鎵逛箣鍚庡啀鎺�0-3澶�
+ LocalDate inspectDate = approveDate.plusDays(ThreadLocalRandom.current().nextInt(0, 4));
+ processQualityInspect(purchaseLedger, inspectDate);
}
// 3. 鍏ュ簱瀹℃壒閫氳繃
- processStockInApprove(purchaseLedger, dateEnd);
+ // 鍏ュ簱鏃堕棿锛氳川妫�鏃堕棿锛堟湁璐ㄦ锛夋垨瀹℃壒鏃堕棿涔嬪悗鍐嶆帹0-3澶�
+ LocalDate stockBaseDate = needQualityInspect
+ ? approveDate.plusDays(ThreadLocalRandom.current().nextInt(1, 4))
+ : approveDate.plusDays(ThreadLocalRandom.current().nextInt(0, 4));
+ processStockInApprove(purchaseLedger, stockBaseDate);
} catch (Exception e) {
log.warn("閲囪喘瀹屾暣娴佺▼澶勭悊澶辫触[{}]: {}", purchaseLedger.getPurchaseContractNumber(), e.getMessage());
@@ -489,17 +1358,68 @@
}
/**
+ * 淇瀹℃壒瀹炰緥鍙婂叧鑱旇妭鐐广�佷换鍔°�佽褰曠殑鏃堕棿
+ */
+ private void fixApprovalTimes(Long instanceId, LocalDateTime dateTime) {
+ try {
+ // 鏇存柊瀹℃壒瀹炰緥鐨刦inishTime鍜宑reateTime
+ ApprovalInstance instance = approvalInstanceMapper.selectById(instanceId);
+ if (instance != null) {
+ instance.setFinishTime(dateTime);
+ instance.setCreateTime(dateTime.minusHours(1));
+ approvalInstanceMapper.updateById(instance);
+ }
+
+ // 鏇存柊瀹℃壒瀹炰緥鑺傜偣鐨刦inishTime
+ List<ApprovalInstanceNode> nodes = approvalInstanceNodeMapper.selectList(
+ new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<ApprovalInstanceNode>()
+ .eq(ApprovalInstanceNode::getInstanceId, instanceId));
+ for (ApprovalInstanceNode node : nodes) {
+ node.setFinishTime(dateTime);
+ node.setCreateTime(dateTime.minusHours(1));
+ approvalInstanceNodeMapper.updateById(node);
+ }
+
+ // 鏇存柊瀹℃壒浠诲姟鐨刢reateTime
+ List<ApprovalTask> tasks = approvalTaskMapper.selectList(
+ new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<ApprovalTask>()
+ .eq(ApprovalTask::getInstanceId, instanceId));
+ for (ApprovalTask task : tasks) {
+ task.setCreateTime(dateTime.minusMinutes(30));
+ approvalTaskMapper.updateById(task);
+ }
+
+ // 鏇存柊瀹℃壒璁板綍鐨刢reateTime
+ List<ApprovalRecord> records = approvalRecordMapper.selectList(
+ new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<ApprovalRecord>()
+ .eq(ApprovalRecord::getInstanceId, instanceId));
+ for (ApprovalRecord record : records) {
+ record.setCreateTime(dateTime.minusMinutes(10));
+ approvalRecordMapper.updateById(record);
+ }
+ } catch (Exception e) {
+ log.warn("淇瀹℃壒鏃堕棿澶辫触: {}", e.getMessage());
+ }
+ }
+
+ /**
* 璐ㄦ: 鎵惧埌閲囪喘鍏宠仈鐨勮川妫�鍗曪紝鑷姩鎻愪氦涓哄悎鏍�
*/
- private void processQualityInspect(PurchaseLedger purchaseLedger, LocalDate entryDate, String dateEnd) {
+ private void processQualityInspect(PurchaseLedger purchaseLedger, LocalDate inspectDate) {
try {
+ LocalDateTime inspectDateTime = inspectDate.atTime(9, 0, 0)
+ .plusMinutes(ThreadLocalRandom.current().nextInt(0, 480));
List<QualityInspect> inspectList = qualityInspectService.list(
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<QualityInspect>()
.eq(QualityInspect::getPurchaseLedgerId, purchaseLedger.getId()));
for (QualityInspect qi : inspectList) {
if (qi.getInspectState() == null || qi.getInspectState() == 0) {
qualityInspectService.autoSubmit(qi.getId());
- log.info("閲囪喘鍙拌处[{}]璐ㄦ鍗昜{}]鑷姩鎻愪氦鍚堟牸", purchaseLedger.getPurchaseContractNumber(), qi.getId());
+ // 淇璐ㄦ鏃堕棿
+ qi.setCreateTime(inspectDateTime);
+ qualityInspectMapper.updateById(qi);
+ log.info("閲囪喘鍙拌处[{}]璐ㄦ鍗昜{}]鑷姩鎻愪氦鍚堟牸, 璐ㄦ鏃ユ湡: {}",
+ purchaseLedger.getPurchaseContractNumber(), qi.getId(), inspectDate);
}
}
} catch (Exception e) {
@@ -508,16 +1428,19 @@
}
/**
- * 鍏ュ簱瀹℃牳: 鎵惧埌鍏ュ簱璁板綍骞跺鎵归�氳繃
+ * 鍏ュ簱瀹℃牳: 鎵惧埌鍏ュ簱璁板綍骞跺鎵归�氳繃锛屽苟淇鏃堕棿涓庢壒鍙锋棩鏈�
*/
- private void processStockInApprove(PurchaseLedger purchaseLedger, String dateEnd) {
+ private void processStockInApprove(PurchaseLedger purchaseLedger, LocalDate stockDate) {
try {
+ LocalDateTime stockDateTime = stockDate.atTime(9, 0, 0)
+ .plusMinutes(ThreadLocalRandom.current().nextInt(0, 480));
+ String stockDateStr = stockDate.format(java.time.format.DateTimeFormatter.BASIC_ISO_DATE);
+
List<com.ruoyi.stock.pojo.StockInRecord> stockRecords = stockInRecordService.list(
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<com.ruoyi.stock.pojo.StockInRecord>()
.eq(com.ruoyi.stock.pojo.StockInRecord::getRecordId, purchaseLedger.getId())
.eq(com.ruoyi.stock.pojo.StockInRecord::getRecordType,
String.valueOf(com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum.PURCHASE_STOCK_IN.getCode())));
- // 濡傛灉鎸塒URCHASE_STOCK_IN鎵句笉鍒帮紝灏濊瘯CUSTOMIZATION_UNSTOCK_OUT(璐ㄦ鍚堟牸鍏ュ簱)
if (stockRecords.isEmpty()) {
stockRecords = stockInRecordService.list(
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<com.ruoyi.stock.pojo.StockInRecord>()
@@ -525,7 +1448,6 @@
.eq(com.ruoyi.stock.pojo.StockInRecord::getRecordType,
String.valueOf(com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum.CUSTOMIZATION_UNSTOCK_OUT.getCode())));
}
- // 涔熷皾璇曟寜璐ㄦ鍗旾D鏌ユ壘(璐ㄦ鍗曠殑recordId鏄川妫�鍗旾D)
for (QualityInspect qi : qualityInspectService.list(
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<QualityInspect>()
.eq(QualityInspect::getPurchaseLedgerId, purchaseLedger.getId()))) {
@@ -534,7 +1456,6 @@
.eq(com.ruoyi.stock.pojo.StockInRecord::getRecordId, qi.getId()));
stockRecords.addAll(qiRecords);
}
- // 鍘婚噸
stockRecords = stockRecords.stream()
.collect(Collectors.toMap(com.ruoyi.stock.pojo.StockInRecord::getId, r -> r, (a, b) -> a))
.values().stream().collect(Collectors.toList());
@@ -545,8 +1466,20 @@
.map(com.ruoyi.stock.pojo.StockInRecord::getId)
.collect(Collectors.toList());
if (!recordIds.isEmpty()) {
+ // 鍏堜慨姝e叆搴撹褰曠殑createTime鍜屾壒鍙锋棩鏈燂紙batchApprove鍐呴儴浼氱敤batchNo鍒涘缓StockInventory锛�
+ for (Long recordId : recordIds) {
+ com.ruoyi.stock.pojo.StockInRecord sr = stockInRecordMapper.selectById(recordId);
+ if (sr != null) {
+ sr.setCreateTime(stockDateTime);
+ sr.setBatchNo(fixBatchNoDate(sr.getBatchNo(), stockDateStr));
+ String s = OrderUtils.countTodayByCreateTime(stockInRecordMapper, "RK", "inbound_batches", stockDateTime);
+ sr.setInboundBatches(s);
+ stockInRecordMapper.updateById(sr);
+ }
+ }
stockInRecordService.batchApprove(recordIds, ReviewStatusEnum.APPROVED.getCode());
- log.info("閲囪喘鍙拌处[{}]鍏ュ簱瀹℃壒閫氳繃, 鍏ュ簱璁板綍鏁�: {}", purchaseLedger.getPurchaseContractNumber(), recordIds.size());
+ log.info("閲囪喘鍙拌处[{}]鍏ュ簱瀹℃壒閫氳繃, 鍏ュ簱鏃ユ湡: {}, 鍏ュ簱璁板綍鏁�: {}",
+ purchaseLedger.getPurchaseContractNumber(), stockDate, recordIds.size());
}
}
} catch (Exception e) {
@@ -554,8 +1487,137 @@
}
}
+ /**
+ * 鏇挎崲鎵瑰彿涓殑鏃ユ湡閮ㄥ垎锛坹yyyMMdd 鈫� 鎸囧畾鏃ユ湡锛�
+ */
+ /**
+ * 鏍规嵁瀹㈡埛鍚嶇О鏌ュ湴鍧�锛屾帹鏂渷浠界畝绉扮敓鎴愯溅鐗屽彿
+ * 鏍煎紡: 鐪佷唤绠�绉� + 瀛楁瘝 + 5浣嶉殢鏈烘暟瀛楀瓧姣�, 濡� 鑻廇12345
+ */
+ private String generateCarNumber(String customerName) {
+ // 鐪佷唤绠�绉板埌鍩庡競瀛楁瘝鐨勫父瑙佹槧灏�
+ Map<String, String[]> provinceCityMap = new HashMap<>();
+ provinceCityMap.put("浜�", new String[]{"A", "B", "C", "E", "F", "G"});
+ provinceCityMap.put("娌�", new String[]{"A", "B", "D", "E", "F"});
+ provinceCityMap.put("绮�", new String[]{"A", "B", "E", "F", "G", "H", "J", "K"});
+ provinceCityMap.put("鑻�", new String[]{"A", "B", "E", "F", "G", "H", "J", "K", "L", "M"});
+ provinceCityMap.put("娴�", new String[]{"A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L"});
+ provinceCityMap.put("椴�", new String[]{"A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "U", "V", "W", "Y"});
+ provinceCityMap.put("璞�", new String[]{"A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "U"});
+ provinceCityMap.put("宸�", new String[]{"A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"});
+ provinceCityMap.put("娓�", new String[]{"A", "B", "C", "D"});
+ provinceCityMap.put("閯�", new String[]{"A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "Q", "R", "S"});
+ provinceCityMap.put("婀�", new String[]{"A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "S"});
+ provinceCityMap.put("闂�", new String[]{"A", "B", "C", "D", "E", "F", "G", "H", "J", "K"});
+ provinceCityMap.put("璧�", new String[]{"A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M"});
+ provinceCityMap.put("鐨�", new String[]{"A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "R", "S"});
+ provinceCityMap.put("鍐�", new String[]{"A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "R", "T"});
+ provinceCityMap.put("杈�", new String[]{"A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P"});
+ provinceCityMap.put("鍚�", new String[]{"A", "B", "C", "D", "E", "F", "G", "H", "J", "K"});
+ provinceCityMap.put("榛�", new String[]{"A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "R"});
+ provinceCityMap.put("鏅�", new String[]{"A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M"});
+ provinceCityMap.put("闄�", new String[]{"A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "V"});
+ provinceCityMap.put("妗�", new String[]{"A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "R"});
+ provinceCityMap.put("浜�", new String[]{"A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "Q", "R", "S"});
+ provinceCityMap.put("璐�", new String[]{"A", "B", "C", "D", "E", "F", "G", "H", "J"});
+ provinceCityMap.put("鐢�", new String[]{"A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P"});
+ provinceCityMap.put("鐞�", new String[]{"A", "B", "C", "D", "E", "F"});
+ provinceCityMap.put("瀹�", new String[]{"A", "B", "C", "D", "E"});
+ provinceCityMap.put("闈�", new String[]{"A", "B", "C", "D", "E", "F", "G", "H"});
+ provinceCityMap.put("钘�", new String[]{"A", "B", "C", "D", "E", "F", "G", "H", "J"});
+ provinceCityMap.put("钂�", new String[]{"A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M"});
+ provinceCityMap.put("鏂�", new String[]{"A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "Q", "R"});
+ provinceCityMap.put("娲�", new String[]{"A", "B", "C", "E", "F", "G", "H", "J", "K", "L", "M", "N", "Q", "R"});
+
+ // 鍦板潃鍏抽敭璇嶅埌鐪佷唤绠�绉扮殑鏄犲皠
+ Map<String, String> addressToProvince = new HashMap<>();
+ addressToProvince.put("鍖椾含", "浜�"); addressToProvince.put("涓婃捣", "娌�");
+ addressToProvince.put("骞垮窞", "绮�"); addressToProvince.put("娣卞湷", "绮�");
+ addressToProvince.put("涓滆帪", "绮�"); addressToProvince.put("浣涘北", "绮�");
+ addressToProvince.put("鍗椾含", "鑻�"); addressToProvince.put("鑻忓窞", "鑻�");
+ addressToProvince.put("鏃犻敗", "鑻�"); addressToProvince.put("鍗楅��", "鑻�");
+ addressToProvince.put("甯稿窞", "鑻�"); addressToProvince.put("寰愬窞", "鑻�");
+ addressToProvince.put("鏉窞", "娴�"); addressToProvince.put("瀹佹尝", "娴�");
+ addressToProvince.put("娓╁窞", "娴�"); addressToProvince.put("鍢夊叴", "娴�");
+ addressToProvince.put("娴庡崡", "椴�"); addressToProvince.put("闈掑矝", "椴�");
+ addressToProvince.put("閮戝窞", "璞�"); addressToProvince.put("鎴愰兘", "宸�");
+ addressToProvince.put("閲嶅簡", "娓�"); addressToProvince.put("姝︽眽", "閯�");
+ addressToProvince.put("闀挎矙", "婀�"); addressToProvince.put("绂忓窞", "闂�");
+ addressToProvince.put("鍘﹂棬", "闂�"); addressToProvince.put("鍗楁槍", "璧�");
+ addressToProvince.put("鍚堣偉", "鐨�"); addressToProvince.put("鐭冲搴�", "鍐�");
+ addressToProvince.put("娌堥槼", "杈�"); addressToProvince.put("澶ц繛", "杈�");
+ addressToProvince.put("闀挎槬", "鍚�"); addressToProvince.put("鍝堝皵婊�", "榛�");
+ addressToProvince.put("澶師", "鏅�"); addressToProvince.put("瑗垮畨", "闄�");
+ addressToProvince.put("鍗楀畞", "妗�"); addressToProvince.put("鏄嗘槑", "浜�");
+ addressToProvince.put("璐甸槼", "璐�"); addressToProvince.put("鍏板窞", "鐢�");
+ addressToProvince.put("娴峰彛", "鐞�"); addressToProvince.put("閾跺窛", "瀹�");
+ addressToProvince.put("瑗垮畞", "闈�"); addressToProvince.put("鎷夎惃", "钘�");
+ addressToProvince.put("鍛煎拰娴╃壒", "钂�"); addressToProvince.put("涔岄瞾鏈ㄩ綈", "鏂�");
+ addressToProvince.put("澶╂触", "娲�");
+ // 鐪佸悕鏄犲皠
+ addressToProvince.put("姹熻嫃", "鑻�"); addressToProvince.put("娴欐睙", "娴�");
+ addressToProvince.put("灞变笢", "椴�"); addressToProvince.put("娌冲崡", "璞�");
+ addressToProvince.put("鍥涘窛", "宸�"); addressToProvince.put("婀栧寳", "閯�");
+ addressToProvince.put("婀栧崡", "婀�"); addressToProvince.put("绂忓缓", "闂�");
+ addressToProvince.put("姹熻タ", "璧�"); addressToProvince.put("瀹夊窘", "鐨�");
+ addressToProvince.put("娌冲寳", "鍐�"); addressToProvince.put("杈藉畞", "杈�");
+ addressToProvince.put("鍚夋灄", "鍚�"); addressToProvince.put("榛戦緳姹�", "榛�");
+ addressToProvince.put("灞辫タ", "鏅�"); addressToProvince.put("闄曡タ", "闄�");
+ addressToProvince.put("骞夸笢", "绮�"); addressToProvince.put("骞胯タ", "妗�");
+ addressToProvince.put("浜戝崡", "浜�"); addressToProvince.put("璐靛窞", "璐�");
+ addressToProvince.put("鐢樿們", "鐢�"); addressToProvince.put("娴峰崡", "鐞�");
+ addressToProvince.put("瀹佸", "瀹�"); addressToProvince.put("闈掓捣", "闈�");
+ addressToProvince.put("瑗胯棌", "钘�"); addressToProvince.put("鍐呰挋鍙�", "钂�");
+ addressToProvince.put("鏂扮枂", "鏂�");
+
+ String province = "鑻�"; // 榛樿姹熻嫃
+ // 灏濊瘯浠庡鎴峰湴鍧�鎺ㄦ柇鐪佷唤
+ if (customerName != null) {
+ try {
+ Customer customer = customerService.getOne(
+ new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<Customer>()
+ .eq(Customer::getCustomerName, customerName)
+ .last("limit 1"));
+ if (customer != null && customer.getCompanyAddress() != null) {
+ String addr = customer.getCompanyAddress();
+ for (Map.Entry<String, String> e : addressToProvince.entrySet()) {
+ if (addr.contains(e.getKey())) {
+ province = e.getValue();
+ break;
+ }
+ }
+ }
+ } catch (Exception e) {
+ log.debug("鏌ュ鎴峰湴鍧�澶辫触: {}", e.getMessage());
+ }
+ }
+
+ // 鐢熸垚杞︾墝鍙�: 鐪佷唤绠�绉� + 鍩庡競瀛楁瘝 + 5浣嶉殢鏈哄瓧绗�(鏁板瓧+澶у啓瀛楁瘝)
+ String[] cities = provinceCityMap.getOrDefault(province, new String[]{"A", "B", "C"});
+ String city = cities[ThreadLocalRandom.current().nextInt(cities.length)];
+ String chars = "ABCDEFGHJKLMNPQRSTUVWXYZ0123456789";
+ StringBuilder suffix = new StringBuilder();
+ for (int i = 0; i < 5; i++) {
+ suffix.append(chars.charAt(ThreadLocalRandom.current().nextInt(chars.length())));
+ }
+ return province + city + suffix;
+ }
+
+ private String fixBatchNoDate(String batchNo, String newDate) {
+ if (batchNo == null || batchNo.length() < 8) {
+ return batchNo;
+ }
+ // 鎵瑰彿鏍煎紡: yyyyMMdd-浜у搧缂栫爜-NNN
+ String prefix = batchNo.substring(0, 8);
+ if (prefix.matches("\\d{8}")) {
+ return newDate + batchNo.substring(8);
+ }
+ return batchNo;
+ }
+
private ModuleSummary createProductionPlans(List<JSONObject> items) {
int success = 0, fail = 0;
+ List<ProductionPlan> createdPlans = new ArrayList<>();
for (JSONObject item : items) {
try {
ProductionPlan plan = new ProductionPlan();
@@ -564,18 +1626,48 @@
plan.setSource(item.getString("source"));
plan.setRemark(item.getString("remark"));
if (item.containsKey("requiredDate")) {
- plan.setRequiredDate(LocalDate.parse(item.getString("requiredDate")));
+ String dateStr = item.getString("requiredDate");
+ if (dateStr != null && dateStr.matches("\\d{4}-\\d{2}-\\d{2}")) {
+ plan.setRequiredDate(LocalDate.parse(dateStr));
+ }
}
if (item.containsKey("promisedDeliveryDate")) {
- plan.setPromisedDeliveryDate(LocalDate.parse(item.getString("promisedDeliveryDate")));
+ String dateStr = item.getString("promisedDeliveryDate");
+ if (dateStr != null && dateStr.matches("\\d{4}-\\d{2}-\\d{2}")) {
+ plan.setPromisedDeliveryDate(LocalDate.parse(dateStr));
+ }
}
productionPlanService.save(plan);
+ createdPlans.add(plan);
success++;
} catch (Exception e) {
log.warn("鍒涘缓鐢熶骇璁″垝澶辫触: {}", e.getMessage());
fail++;
}
}
+
+ // 鎸塸roductModelId鍒嗙粍锛岃嚜鍔ㄥ悎骞朵笅鍙�
+ Map<Long, List<ProductionPlan>> grouped = createdPlans.stream()
+ .filter(p -> p.getProductModelId() != null)
+ .collect(Collectors.groupingBy(ProductionPlan::getProductModelId));
+ for (Map.Entry<Long, List<ProductionPlan>> entry : grouped.entrySet()) {
+ try {
+ List<Long> planIds = entry.getValue().stream().map(ProductionPlan::getId).collect(Collectors.toList());
+ BigDecimal totalQty = entry.getValue().stream()
+ .map(ProductionPlan::getQtyRequired)
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
+ ProductionPlanDto combineDto = new ProductionPlanDto();
+ combineDto.setIds(planIds);
+ combineDto.setTotalAssignedQuantity(totalQty);
+ combineDto.setPlanCompleteTime(LocalDate.now().plusDays(ThreadLocalRandom.current().nextInt(3, 10)));
+ productionPlanService.combine(combineDto);
+ log.info("鐢熶骇璁″垝鑷姩涓嬪彂鎴愬姛, productModelId={}, 璁″垝鏁�: {}, 涓嬪彂鏁伴噺: {}",
+ entry.getKey(), planIds.size(), totalQty);
+ } catch (Exception e) {
+ log.warn("鐢熶骇璁″垝鑷姩涓嬪彂澶辫触, productModelId={}: {}", entry.getKey(), e.getMessage());
+ }
+ }
+
return summary("production", "鐢熶骇璁″垝", items.size(), success, fail);
}
@@ -589,7 +1681,10 @@
order.setProductModelId(item.getLong("productModelId"));
order.setQuantity(item.getBigDecimal("quantity"));
if (item.containsKey("planCompleteTime")) {
- order.setPlanCompleteTime(LocalDate.parse(item.getString("planCompleteTime")));
+ String dateStr = item.getString("planCompleteTime");
+ if (dateStr != null && dateStr.matches("\\d{4}-\\d{2}-\\d{2}")) {
+ order.setPlanCompleteTime(LocalDate.parse(dateStr));
+ }
}
productionOrderService.saveProductionOrder(order);
success++;
diff --git a/src/main/java/com/ruoyi/project/system/domain/SysUser.java b/src/main/java/com/ruoyi/project/system/domain/SysUser.java
index 515210e..39050e5 100644
--- a/src/main/java/com/ruoyi/project/system/domain/SysUser.java
+++ b/src/main/java/com/ruoyi/project/system/domain/SysUser.java
@@ -1,8 +1,8 @@
package com.ruoyi.project.system.domain;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.ruoyi.common.xss.Xss;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.ruoyi.common.xss.Xss;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
import com.ruoyi.framework.aspectj.lang.annotation.Excel.ColumnType;
import com.ruoyi.framework.aspectj.lang.annotation.Excel.Type;
@@ -60,13 +60,13 @@
@Excel(name = "璐﹀彿鐘舵��", readConverterExp = "0=姝e父,1=鍋滅敤")
private String status;
- /** 鍒犻櫎鏍囧織锛�0浠h〃瀛樺湪 2浠h〃鍒犻櫎锛� */
- private String delFlag;
-
- /** 鏄惁寮�閫欰I鍔熻兘锛�0鍚� 1鏄級 */
- @JsonIgnore
- private Integer aiEnabled;
-
+ /** 鍒犻櫎鏍囧織锛�0浠h〃瀛樺湪 2浠h〃鍒犻櫎锛� */
+ private String delFlag;
+
+ /** 鏄惁寮�閫欰I鍔熻兘锛�0鍚� 1鏄級 */
+ @JsonIgnore
+ private Integer aiEnabled;
+
/** 鏈�鍚庣櫥褰旾P */
@Excel(name = "鏈�鍚庣櫥褰旾P", type = Type.EXPORT)
private String loginIp;
@@ -128,6 +128,12 @@
*/
@TableField(exist = false)
private String deptNames;
+
+ /**
+ * 瑙掕壊鍚嶇О
+ */
+ @TableField(exist = false)
+ private String roleNames;
public Long getCurrentDeptId() {
return currentDeptId;
@@ -255,25 +261,25 @@
this.status = status;
}
- public String getDelFlag()
- {
- return delFlag;
- }
+ public String getDelFlag()
+ {
+ return delFlag;
+ }
- public void setDelFlag(String delFlag)
- {
- this.delFlag = delFlag;
- }
-
- public Integer getAiEnabled()
- {
- return aiEnabled;
- }
-
- public void setAiEnabled(Integer aiEnabled)
- {
- this.aiEnabled = aiEnabled;
- }
+ public void setDelFlag(String delFlag)
+ {
+ this.delFlag = delFlag;
+ }
+
+ public Integer getAiEnabled()
+ {
+ return aiEnabled;
+ }
+
+ public void setAiEnabled(Integer aiEnabled)
+ {
+ this.aiEnabled = aiEnabled;
+ }
public String getLoginIp()
{
@@ -369,6 +375,14 @@
this.deptNames = deptNames;
}
+ public String getRoleNames() {
+ return roleNames;
+ }
+
+ public void setRoleNames(String roleNames) {
+ this.roleNames = roleNames;
+ }
+
public Long getDeptId() {
return deptId;
}
@@ -388,10 +402,10 @@
.append("sex", getSex())
.append("avatar", getAvatar())
.append("password", getPassword())
- .append("status", getStatus())
- .append("delFlag", getDelFlag())
- .append("aiEnabled", getAiEnabled())
- .append("loginIp", getLoginIp())
+ .append("status", getStatus())
+ .append("delFlag", getDelFlag())
+ .append("aiEnabled", getAiEnabled())
+ .append("loginIp", getLoginIp())
.append("loginDate", getLoginDate())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
diff --git a/src/main/java/com/ruoyi/project/system/mapper/SysUserMapper.java b/src/main/java/com/ruoyi/project/system/mapper/SysUserMapper.java
index 5507b3f..ccabf71 100644
--- a/src/main/java/com/ruoyi/project/system/mapper/SysUserMapper.java
+++ b/src/main/java/com/ruoyi/project/system/mapper/SysUserMapper.java
@@ -155,5 +155,10 @@
List<Long> getUserByRole(@Param("role") String role);
+ /**
+ * 鏌ヨ鎵�鏈夋椿璺冪敤鎴凤紙鍚儴闂ㄥ悕绉板拰瑙掕壊鍚嶇О锛�
+ */
+ List<SysUser> selectUserListWithDetail();
+
List<Long> getUserByPerms(@Param("perms") List<String> perms);
}
diff --git a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java
index 9f6e004..b8042d8 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java
@@ -223,9 +223,8 @@
ProductionPlan productionPlan = new ProductionPlan();
productionPlan.setSalesLedgerId(salesLedgerProduct.getSalesLedgerId());
productionPlan.setSalesLedgerProductId(salesLedgerProduct.getId());
- productionPlan.setMpsNo(generateNextPlanNo(salesLedger.getEntryDate().toInstant()
- .atZone(ZoneId.systemDefault())
- .toLocalDate().format(DateTimeFormatter.ofPattern("yyyyMMdd"))));
+ productionPlan.setMpsNo(generateNextPlanNo(com.ruoyi.common.utils.DateUtils.toLocalDate(salesLedger.getEntryDate())
+ .format(DateTimeFormatter.ofPattern("yyyyMMdd"))));
productionPlan.setProductModelId(salesLedgerProduct.getProductModelId());
productionPlan.setQtyRequired(salesLedgerProduct.getQuantity());
productionPlan.setSource("閿�鍞�");
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
index f1a5bf9..e5e2f9a 100644
--- a/src/main/resources/application-dev.yml
+++ b/src/main/resources/application-dev.yml
@@ -74,7 +74,7 @@
druid:
# 涓诲簱鏁版嵁婧�
master:
- url: jdbc:mysql://localhost:3306/product-inventory-management-new-pro?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+ url: jdbc:mysql://localhost:3306/product-inventory-management-bdpro?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: 123456
# 浠庡簱鏁版嵁婧�
diff --git a/src/main/resources/mapper/system/SysUserMapper.xml b/src/main/resources/mapper/system/SysUserMapper.xml
index ea68745..b12ee0f 100644
--- a/src/main/resources/mapper/system/SysUserMapper.xml
+++ b/src/main/resources/mapper/system/SysUserMapper.xml
@@ -25,6 +25,7 @@
<result property="remark" column="remark" />
<result property="deptNames" column="dept_names" />
<result property="tenantId" column="tenant_id" />
+ <result property="roleNames" column="role_names" />
<association property="dept" javaType="com.ruoyi.project.system.domain.SysDept" resultMap="deptResult" />
<collection property="roles" javaType="java.util.List" resultMap="RoleResult" />
</resultMap>
@@ -290,6 +291,29 @@
and su.del_flag = '0'
ORDER BY su.create_time DESC
</select>
+
+ <select id="selectUserListWithDetail" resultMap="SysUserResult">
+ select u.user_id, u.nick_name, u.user_name, u.status, u.del_flag,
+ dept_agg.dept_names,
+ role_agg.role_names
+ from sys_user u
+ left join (
+ SELECT ud.user_id, GROUP_CONCAT(d.dept_name SEPARATOR ', ') AS dept_names
+ FROM sys_user_dept ud
+ LEFT JOIN sys_dept d ON ud.dept_id = d.dept_id
+ WHERE d.del_flag = '0' AND d.status = '0'
+ GROUP BY ud.user_id
+ ) dept_agg on dept_agg.user_id = u.user_id
+ left join (
+ SELECT ur.user_id, GROUP_CONCAT(r.role_name SEPARATOR ', ') AS role_names
+ FROM sys_user_role ur
+ LEFT JOIN sys_role r ON ur.role_id = r.role_id
+ WHERE r.del_flag = '0' AND r.status = '0'
+ GROUP BY ur.user_id
+ ) role_agg on role_agg.user_id = u.user_id
+ where u.del_flag = '0' AND u.status = '0'
+ </select>
+
<select id="getUserByPerms" resultType="java.lang.Long">
select distinct t5.user_id
from sys_role_menu t1
--
Gitblit v1.9.3