From b22ebe8fad1691b35adcf321fe2e136795b3f81d Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期一, 29 六月 2026 17:58:00 +0800
Subject: [PATCH] 库位
---
src/main/java/com/ruoyi/device/controller/DeviceLedgerController.java | 9 ++
docs/purchase_product_location.md | 151 +++++++++++++++++++++++++++++++++++++
src/main/resources/mapper/sales/SalesLedgerProductMapper.xml | 4 +
src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java | 22 +++++
src/main/resources/mapper/stock/StockInventoryMapper.xml | 3
docs/purchase_product_location.sql | 19 ++++
src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java | 10 ++
src/main/java/com/ruoyi/approve/service/impl/ApproveBusinessStatusService.java | 5 +
src/main/java/com/ruoyi/quality/pojo/QualityInspect.java | 3
src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java | 2
10 files changed, 224 insertions(+), 4 deletions(-)
diff --git a/docs/purchase_product_location.md b/docs/purchase_product_location.md
new file mode 100644
index 0000000..15cdfea
--- /dev/null
+++ b/docs/purchase_product_location.md
@@ -0,0 +1,151 @@
+# 閲囪喘鍙拌处搴撲綅瀛楁锛堣澶囬�夋嫨锛�
+
+## 娑夊強椤甸潰
+
+- 閲囪喘鍙拌处绠$悊椤甸潰 (`views/procurementManagement/procurementLedger/index.vue`)
+- 閲囪喘鍙拌处鏂板/缂栬緫寮圭獥
+- 搴撳瓨绠$悊椤甸潰 (`views/inventoryManagement/stockManagement/index.vue`)
+- 鍏ュ簱璁板綍椤甸潰 (`views/inventoryManagement/stockManagement/Record.vue`)
+
+## 瀛楁鏄犲皠鍏崇郴
+
+| 琛�/瀹炰綋 | 瀛楁鍚� | 璇存槑 |
+|---------|--------|------|
+| device_ledger | storage_location | 璁惧鐨勫瓨鏀句綅缃紙搴撲綅锛� |
+| sales_ledger_product | storage_location | 閲囪喘鍙拌处浜у搧鏄庣粏鐨勫簱浣嶏紙鏉ユ簮浜庤澶囷級 |
+| sales_ledger_product | device_id | 鍏宠仈鐨勮澶嘔D |
+| stock_in_record | warehouse | 鍏ュ簱璁板綍鐨勫簱浣嶏紙鏉ユ簮浜巗torageLocation锛� |
+| stock_inventory | warehouse | 搴撳瓨鐨勫簱浣嶏紙鏉ユ簮浜巗torageLocation锛� |
+
+**鏁版嵁娴佸悜锛�**
+```
+璁惧鍙拌处(storage_location) 鈫� 閲囪喘浜у搧鏄庣粏(storage_location) 鈫� 鍏ュ簱璁板綍(warehouse) 鈫� 搴撳瓨(warehouse)
+```
+
+## API
+
+| 鏂规硶 | 璺緞 | 璇存槑 |
+|------|------|------|
+| GET | /device/ledger/iotDeviceList | 鑾峰彇IoT璁惧鍒楄〃锛坕s_iot_device=1锛� |
+| POST | /purchase/purchaseLedger/addOrEditPurchase | 鏂板/缂栬緫閲囪喘鍙拌处 |
+| GET | /purchase/purchaseLedger/getPurchaseById | 鏌ヨ閲囪喘鍙拌处璇︽儏 |
+| GET | /stock/stockInventory/pagestockInventory | 搴撳瓨鍒嗛〉鏌ヨ |
+| GET | /stock/stockInventory/pageListCombinedStockInventory | 搴撳瓨鍚堝苟鏌ヨ |
+| GET | /stock/stockInRecord/listPage | 鍏ュ簱璁板綍鍒嗛〉鏌ヨ |
+
+**IoT璁惧鍒楄〃鍝嶅簲锛�**
+
+```json
+[
+ {
+ "id": 1,
+ "deviceName": "鍌ㄧ綈A",
+ "storageLocation": "浠撳簱1-A鍖�"
+ }
+]
+```
+
+**璇锋眰鍙傛暟锛堜骇鍝佹槑缁嗘柊澧炲瓧娈碉級锛�**
+
+| 鍙傛暟 | 绫诲瀷 | 蹇呭~ | 璇存槑 |
+|------|------|------|------|
+| deviceId | Long | 鍚� | 璁惧ID锛堥�夋嫨IoT璁惧鍚庤嚜鍔ㄨ幏鍙栵級 |
+| storageLocation | String | 鍚� | 搴撲綅锛堥�夋嫨璁惧鍚庤嚜鍔ㄥ~鍏呰澶囩殑storageLocation锛� |
+
+**鍝嶅簲瀛楁锛堜骇鍝佹槑缁嗗洖鏄撅級锛�**
+
+| 鍙傛暟 | 绫诲瀷 | 璇存槑 |
+|------|------|------|
+| deviceId | Long | 璁惧ID |
+| deviceName | String | 璁惧鍚嶇О |
+| storageLocation | String | 搴撲綅 |
+
+**鍝嶅簲瀛楁锛堝簱瀛�/鍏ュ簱璁板綍鍥炴樉锛夛細**
+
+| 鍙傛暟 | 绫诲瀷 | 璇存槑 |
+|------|------|------|
+| warehouse | String | 搴撲綅锛堟潵婧愪簬閲囪喘鍙拌处浜у搧鏄庣粏鐨剆torageLocation锛� |
+
+## 鍓嶇淇敼鐐�
+
+### 1. 閲囪喘鍙拌处浜у搧琛ㄦ牸鏂板璁惧閫夋嫨鍒�
+
+```html
+<el-table-column label="閫夋嫨璁惧" prop="deviceId" min-width="150">
+ <template slot-scope="scope">
+ <el-select
+ v-model="scope.row.deviceId"
+ placeholder="璇烽�夋嫨璁惧"
+ filterable
+ @change="handleDeviceChange(scope.row, scope.$index)">
+ <el-option
+ v-for="device in iotDeviceList"
+ :key="device.id"
+ :label="device.deviceName"
+ :value="device.id">
+ </el-option>
+ </el-select>
+ </template>
+</el-table-column>
+
+<el-table-column label="搴撲綅" prop="storageLocation" min-width="120">
+ <template slot-scope="scope">
+ <el-input v-model="scope.row.storageLocation" placeholder="鑷姩鑾峰彇" disabled />
+ </template>
+</el-table-column>
+```
+
+### 2. 搴撳瓨/鍏ュ簱璁板綍琛ㄦ牸鏂板搴撲綅鍒�
+
+```html
+<el-table-column label="搴撲綅" prop="warehouse" min-width="120" />
+```
+
+### 3. data 鏁版嵁
+
+```js
+data() {
+ return {
+ iotDeviceList: [], // IoT璁惧鍒楄〃
+ productData: [], // 浜у搧鏄庣粏
+ }
+}
+```
+
+### 4. methods 鏂规硶
+
+```js
+// 鑾峰彇IoT璁惧鍒楄〃
+async getIotDeviceList() {
+ const res = await this.$axios.get('/device/ledger/iotDeviceList');
+ this.iotDeviceList = res.data;
+},
+
+// 璁惧閫夋嫨鍙樻洿鏃讹紝鑷姩濉厖搴撲綅
+handleDeviceChange(row, index) {
+ const device = this.iotDeviceList.find(d => d.id === row.deviceId);
+ if (device) {
+ row.storageLocation = device.storageLocation;
+ } else {
+ row.storageLocation = '';
+ }
+},
+
+// 缂栬緫鍥炴樉鏃讹紝鏍规嵁deviceId鍥炴樉璁惧鍚嶇О
+// 娉ㄦ剰锛氬悗绔煡璇㈠凡鍏宠仈杩斿洖deviceName锛屾棤闇�棰濆澶勭悊
+
+// 椤甸潰鍔犺浇鏃惰幏鍙栬澶囧垪琛�
+mounted() {
+ this.getIotDeviceList();
+}
+```
+
+## 娉ㄦ剰浜嬮」
+
+- 璁惧閫夋嫨鎺ュ彛鍙繑鍥� `is_iot_device=1` 鐨勮澶囷紙鐗╄仈璁惧锛�
+- 閫夋嫨璁惧鍚庯紝搴撲綅鑷姩浠庤澶囩殑 `storageLocation` 瀛楁鑾峰彇锛屾棤闇�鎵嬪姩杈撳叆
+- 缂栬緫閲囪喘鍙拌处鏃讹紝鍚庣浼氳嚜鍔ㄥ洖鏄� `deviceId`銆乣deviceName`銆乣storageLocation` 瀛楁
+- 搴撲綅瀛楁浠呯敤浜庨噰璐彴璐︾殑鍘熸潗鏂欎骇鍝侊紝閿�鍞彴璐︾殑鎴愬搧涓嶉渶瑕佹瀛楁
+- 搴撲綅淇℃伅浼氬湪閲囪喘鍏ュ簱娴佺▼瀹℃壒閫氳繃鍚庤嚜鍔ㄥ甫鍏ュ埌搴撳瓨璁板綍鐨� `warehouse` 瀛楁
+- 搴撳瓨绠$悊椤甸潰鍜屽叆搴撹褰曢〉闈㈢殑 `warehouse` 瀛楁宸茶嚜鍔ㄥ洖鏄惧簱浣嶄俊鎭�
+- 娉ㄦ剰瀛楁鍛藉悕宸紓锛氶噰璐彴璐︾敤 `storageLocation`锛屽簱瀛樼敤 `warehouse`锛屽疄闄呭瓨鍌ㄧ殑鏄悓涓�涓簱浣嶅��
\ No newline at end of file
diff --git a/docs/purchase_product_location.sql b/docs/purchase_product_location.sql
new file mode 100644
index 0000000..4aff517
--- /dev/null
+++ b/docs/purchase_product_location.sql
@@ -0,0 +1,19 @@
+-- 閲囪喘鍙拌处浜у搧娣诲姞搴撲綅瀛楁锛堣澶囬�夋嫨锛�
+-- 鏃ユ湡: 2026-06-29
+-- 璇存槑: 鍘熸潗鏂欓噰璐叆搴撻渶瑕佷粠IoT璁惧鍙拌处閫夋嫨搴撲綅锛岄�氳繃娴佺▼甯﹀叆鍒板簱瀛樿褰�
+
+-- 涓洪噰璐彴璐︿骇鍝佽〃娣诲姞璁惧ID鍜屽簱浣嶅瓧娈�
+ALTER TABLE sales_ledger_product ADD COLUMN device_id BIGINT DEFAULT NULL COMMENT '璁惧ID锛堝叧鑱旇澶囧彴璐︼紝绛涢�塱s_iot_device=1锛�';
+ALTER TABLE sales_ledger_product ADD COLUMN storage_location VARCHAR(100) DEFAULT NULL COMMENT '搴撲綅锛堟潵婧愪簬璁惧鐨剆torage_location锛�';
+
+-- 涓鸿川妫�鍗曡〃娣诲姞搴撲綅瀛楁锛堥噰璐川妫�鍏ュ簱鏃朵娇鐢級
+ALTER TABLE quality_inspect ADD COLUMN warehouse VARCHAR(100) DEFAULT NULL COMMENT '搴撲綅锛堟潵婧愪簬閲囪喘浜у搧鏄庣粏鐨剆torage_location锛�';
+
+-- 娉ㄦ剰浜嬮」:
+-- 1. 姝ゅ瓧娈典粎鐢ㄤ簬閲囪喘鍙拌处(type=2)鐨勫師鏉愭枡浜у搧
+-- 2. 閿�鍞彴璐︾殑鎴愬搧搴撳瓨涓嶉渶瑕佹瀛楁
+-- 3. 鍓嶇閫夋嫨璁惧鏃讹紝闇�璋冪敤 GET /device/ledger/iotDeviceList 鎺ュ彛鑾峰彇 is_iot_device=1 鐨勮澶囧垪琛�
+-- 4. 閫夋嫨璁惧鍚庯紝鑷姩鑾峰彇璁惧鐨� storage_location 瀛楁鍊�
+-- 5. 搴撲綅淇℃伅娴佽浆璺緞锛�
+-- 璁惧(storage_location) 鈫� 閲囪喘浜у搧鏄庣粏(storage_location) 鈫� 璐ㄦ鍗�(warehouse) 鈫� 鍏ュ簱璁板綍(warehouse) 鈫� 搴撳瓨(warehouse)
+-- 鎴栵細璁惧(storage_location) 鈫� 閲囪喘浜у搧鏄庣粏(storage_location) 鈫� 鍏ュ簱璁板綍(warehouse) 鈫� 搴撳瓨(warehouse)锛堢洿鎺ュ叆搴擄級
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/approve/service/impl/ApproveBusinessStatusService.java b/src/main/java/com/ruoyi/approve/service/impl/ApproveBusinessStatusService.java
index 8484aa0..88601e8 100644
--- a/src/main/java/com/ruoyi/approve/service/impl/ApproveBusinessStatusService.java
+++ b/src/main/java/com/ruoyi/approve/service/impl/ApproveBusinessStatusService.java
@@ -87,7 +87,9 @@
salesLedgerProduct.getQuantity(),
StockInQualifiedRecordTypeEnum.PURCHASE_STOCK_IN.getCode(),
purchaseLedger.getId(),
- purchaseLedger.getPurchaseContractNumber() + "-" + salesLedgerProduct.getId());
+ purchaseLedger.getPurchaseContractNumber() + "-" + salesLedgerProduct.getId(),
+ null,
+ salesLedgerProduct.getStorageLocation());
}
}
} else if (status.equals(3)) {
@@ -156,6 +158,7 @@
qualityInspect.setProductModelId(saleProduct.getProductModelId());
qualityInspect.setUnit(saleProduct.getUnit());
qualityInspect.setQuantity(saleProduct.getQuantity());
+ qualityInspect.setWarehouse(saleProduct.getStorageLocation());
qualityInspectMapper.insert(qualityInspect);
List<QualityTestStandard> qualityTestStandard = qualityTestStandardMapper.getQualityTestStandardByProductId(saleProduct.getProductId(), 0, null);
if (qualityTestStandard.size() > 0) {
diff --git a/src/main/java/com/ruoyi/device/controller/DeviceLedgerController.java b/src/main/java/com/ruoyi/device/controller/DeviceLedgerController.java
index 298980e..4992cd4 100644
--- a/src/main/java/com/ruoyi/device/controller/DeviceLedgerController.java
+++ b/src/main/java/com/ruoyi/device/controller/DeviceLedgerController.java
@@ -113,4 +113,13 @@
deviceLedger.setCreateTime(deviceLedger.getUpdateTime().plusMonths(1));//涓嬫缁存姢鏃堕棿
return AjaxResult.success(deviceLedger);
}
+
+ @GetMapping("iotDeviceList")
+ @Operation(summary = "鑾峰彇IoT璁惧鍒楄〃锛坕s_iot_device=1锛�")
+ public AjaxResult iotDeviceList() {
+ return AjaxResult.success(deviceLedgerMapper.selectList(
+ new QueryWrapper<DeviceLedger>().lambda()
+ .eq(DeviceLedger::getIsIotDevice, 1)
+ .select(DeviceLedger::getId, DeviceLedger::getDeviceName, DeviceLedger::getStorageLocation)));
+ }
}
diff --git a/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java b/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
index 96be8cf..49bd0a5 100644
--- a/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java
@@ -64,6 +64,8 @@
import com.ruoyi.sales.service.impl.CommonFileServiceImpl;
import com.ruoyi.stock.pojo.StockInRecord;
import com.ruoyi.stock.service.StockInRecordService;
+import com.ruoyi.device.mapper.DeviceLedgerMapper;
+import com.ruoyi.device.pojo.DeviceLedger;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
@@ -119,6 +121,7 @@
private final StockUtils stockUtils;
private final ApprovalTemplateMapper approvalTemplateMapper;
private final SparePartsMapper sparePartsMapper;
+ private final DeviceLedgerMapper deviceLedgerMapper;
@Override
public List<PurchaseLedger> selectPurchaseLedgerList(PurchaseLedger purchaseLedger) {
@@ -421,6 +424,7 @@
qualityInspect.setProductModelId(saleProduct.getProductModelId());
qualityInspect.setUnit(saleProduct.getUnit());
qualityInspect.setQuantity(saleProduct.getQuantity());
+ qualityInspect.setWarehouse(saleProduct.getStorageLocation());
qualityInspectMapper.insert(qualityInspect);
List<QualityTestStandard> qualityTestStandard = qualityTestStandardMapper.getQualityTestStandardByProductId(saleProduct.getProductId(), 0,null);
if (qualityTestStandard.size()>0){
@@ -495,13 +499,18 @@
if (CollectionUtils.isEmpty(stockRecords)
&& qualityInspect.getQualifiedQuantity() != null
&& qualityInspect.getQualifiedQuantity().compareTo(BigDecimal.ZERO) > 0) {
+ // 浼樺厛浣跨敤璐ㄦ鍗曚腑鐨勫簱浣嶏紝濡傛灉娌℃湁鍒欎娇鐢ㄤ骇鍝佹槑缁嗕腑鐨勫簱浣�
+ String warehouse = StringUtils.hasText(qualityInspect.getWarehouse())
+ ? qualityInspect.getWarehouse()
+ : product.getStorageLocation();
stockUtils.addStockWithBatchNo(
product.getProductModelId(),
qualityInspect.getQualifiedQuantity(),
StockInQualifiedRecordTypeEnum.CUSTOMIZATION_UNSTOCK_OUT.getCode(),
qualityInspect.getId(),
null,
- purchaseInspectTime == null ? null : purchaseInspectTime.plusDays(1)
+ purchaseInspectTime == null ? null : purchaseInspectTime.plusDays(1),
+ warehouse
);
stockRecords = findQualityStockRecords(qualityInspect.getId(), product.getProductModelId());
}
@@ -548,7 +557,8 @@
StockInQualifiedRecordTypeEnum.PURCHASE_STOCK_IN.getCode(),
purchaseLedger.getId(),
purchaseLedger.getPurchaseContractNumber() + "-" + product.getId(),
- stockCreateTime
+ stockCreateTime,
+ product.getStorageLocation()
);
stockRecords = findDirectStockRecords(purchaseLedger.getId(), purchaseLedger.getPurchaseContractNumber(), product.getProductModelId(), product.getId());
}
@@ -735,6 +745,14 @@
product.setProductCategory(spareParts.getName());
}
}
+
+ // 濡傛灉鏈夎澶嘔D浣嗘病鏈夊簱浣嶏紝浠庤澶囪〃鑷姩濉厖搴撲綅
+ if (product.getDeviceId() != null && StringUtils.isEmpty(product.getStorageLocation())) {
+ DeviceLedger device = deviceLedgerMapper.selectById(product.getDeviceId());
+ if (device != null && StringUtils.isNotEmpty(device.getStorageLocation())) {
+ product.setStorageLocation(device.getStorageLocation());
+ }
+ }
}
// 鍒嗙粍澶勭悊
diff --git a/src/main/java/com/ruoyi/quality/pojo/QualityInspect.java b/src/main/java/com/ruoyi/quality/pojo/QualityInspect.java
index cb17247..49b2d98 100644
--- a/src/main/java/com/ruoyi/quality/pojo/QualityInspect.java
+++ b/src/main/java/com/ruoyi/quality/pojo/QualityInspect.java
@@ -191,6 +191,9 @@
@Excel(name = "鑷姩鍒ゆ柇缁撴灉")
private String autoJudgeResult;
+ @Schema(description = "搴撲綅锛堟潵婧愪簬閲囪喘浜у搧鏄庣粏锛�")
+ private String warehouse;
+
@TableField(fill = FieldFill.INSERT)
private Long deptId;
}
diff --git a/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java b/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java
index d6766e3..3b778a3 100644
--- a/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java
+++ b/src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java
@@ -188,4 +188,14 @@
@TableField(exist = false)
@Schema(description = "寰呭彂璐ф暟閲�")
private BigDecimal noQuantity;
+
+ @Schema(description = "璁惧ID锛堝叧鑱旇澶囧彴璐︼紝绛涢�塱s_iot_device=1锛�")
+ private Long deviceId;
+
+ @TableField(exist = false)
+ @Schema(description = "璁惧鍚嶇О")
+ private String deviceName;
+
+ @Schema(description = "搴撲綅锛堟潵婧愪簬璁惧鐨剆torage_location锛�")
+ private String storageLocation;
}
diff --git a/src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java b/src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java
index b717f9d..e18515c 100644
--- a/src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java
+++ b/src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java
@@ -242,6 +242,7 @@
stockInventoryDto.setBatchNo(stockInRecord.getBatchNo());
stockInventoryDto.setQualitity(stockInRecord.getStockInNum());
stockInventoryDto.setRemark(stockInRecord.getRemark());
+ stockInventoryDto.setWarehouse(stockInRecord.getWarehouse());
if (stockInventory == null) {
stockInventoryMapper.insert(new StockInventory() {{
setProductModelId(stockInRecord.getProductModelId());
@@ -263,6 +264,7 @@
stockUninventoryDto.setBatchNo(stockInRecord.getBatchNo());
stockUninventoryDto.setQualitity(stockInRecord.getStockInNum());
stockUninventoryDto.setRemark(stockInRecord.getRemark());
+ stockUninventoryDto.setWarehouse(stockInRecord.getWarehouse());
if (stockUninventory == null) {
stockUninventoryMapper.insert(new StockUninventory() {{
setProductModelId(stockInRecord.getProductModelId());
diff --git a/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml b/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
index 5316727..91aac3e 100644
--- a/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
+++ b/src/main/resources/mapper/sales/SalesLedgerProductMapper.xml
@@ -26,9 +26,12 @@
T1.is_production,
T1.create_user,
T1.dept_id,
+ T1.device_id,
+ T1.storage_location,
p.product_name as product_category,
pm.model as specification_model,
pm.unit as unit,
+ dl.device_name,
CASE
WHEN (IFNULL(t2.qualitity, 0) - IFNULL(t2.locked_quantity, 0)) >0 THEN 1
ELSE 0
@@ -101,6 +104,7 @@
) t4 ON t4.sales_ledger_product_id = T1.id
left join product_model pm ON T1.product_model_id = pm.id
left join product p ON pm.product_id = p.id
+ left join device_ledger dl ON T1.device_id = dl.id
<where>
<if test="salesLedgerProduct.salesLedgerId != null">
AND T1.sales_ledger_id = #{salesLedgerProduct.salesLedgerId}
diff --git a/src/main/resources/mapper/stock/StockInventoryMapper.xml b/src/main/resources/mapper/stock/StockInventoryMapper.xml
index cb70db6..63cc1d6 100644
--- a/src/main/resources/mapper/stock/StockInventoryMapper.xml
+++ b/src/main/resources/mapper/stock/StockInventoryMapper.xml
@@ -231,7 +231,8 @@
model,
unit,
product_name,
- product_id
+ product_id,
+ warehouse
order by create_time desc
</select>
--
Gitblit v1.9.3