fix:产品库存数据展示调整

dev_1.0.2
jiangpeng 2026-07-09 18:45:23 +08:00
parent 3883b75b3b
commit 2913740e36
9 changed files with 55 additions and 46 deletions

View File

@ -287,7 +287,7 @@
<dict-tag :options="dict.type.purchase_status" :value="String(scope.row.status)"/> <dict-tag :options="dict.type.purchase_status" :value="String(scope.row.status)"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="制造" align="center" prop="vendorAddress" /> <el-table-column label="制造" align="center" prop="vendorAddress" />
<el-table-column label="单价" align="center" prop="price" width="130"> <el-table-column label="单价" align="center" prop="price" width="130">
<template slot-scope="scope"> <template slot-scope="scope">
<span style="color: #f05a00;"> {{ formatCurrency(scope.row.price) }}</span> <span style="color: #f05a00;"> {{ formatCurrency(scope.row.price) }}</span>

View File

@ -21,11 +21,6 @@
<el-option v-for="vendor in vendorOptions" :key="vendor.vendorCode" :label="vendor.vendorName" :value="vendor.vendorCode" /> <el-option v-for="vendor in vendorOptions" :key="vendor.vendorCode" :label="vendor.vendorName" :value="vendor.vendorCode" />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="仓库" prop="warehouseId">
<el-select v-model="queryParams.warehouseId" placeholder="请选择仓库" clearable size="small">
<el-option v-for="warehouse in warehouseOptions" :key="warehouse.id" :label="warehouse.warehouseName" :value="warehouse.id" />
</el-select>
</el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery"></el-button> <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery"></el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery"></el-button> <el-button icon="el-icon-refresh" size="mini" @click="resetQuery"></el-button>
@ -56,7 +51,6 @@
<el-table-column label="产品编码" align="center" prop="productCode" show-overflow-tooltip /> <el-table-column label="产品编码" align="center" prop="productCode" show-overflow-tooltip />
<el-table-column label="产品型号" align="center" prop="model" show-overflow-tooltip /> <el-table-column label="产品型号" align="center" prop="model" show-overflow-tooltip />
<el-table-column label="产品名称" align="center" prop="productName" show-overflow-tooltip /> <el-table-column label="产品名称" align="center" prop="productName" show-overflow-tooltip />
<el-table-column label="仓库" align="center" prop="warehouseName" />
<el-table-column label="在库现存" align="center" prop="inventoryNum"> <el-table-column label="在库现存" align="center" prop="inventoryNum">
<template slot-scope="scope"> <template slot-scope="scope">
<el-link v-if="scope.row.inventoryNum" class="inventory-num inventory-num--stock" :underline="false" @click="handleInventoryInner(scope.row)">{{ scope.row.inventoryNum }}</el-link> <el-link v-if="scope.row.inventoryNum" class="inventory-num inventory-num--stock" :underline="false" @click="handleInventoryInner(scope.row)">{{ scope.row.inventoryNum }}</el-link>
@ -448,7 +442,6 @@ export default {
productName: null, productName: null,
type: null, type: null,
vendorCode: null, vendorCode: null,
warehouseId: null,
orderByColumn:'outer_num desc, usable_num desc, inventory_num desc, purchase_num desc, bind_num', orderByColumn:'outer_num desc, usable_num desc, inventory_num desc, purchase_num desc, bind_num',
isAsc: 'desc' isAsc: 'desc'
}, },
@ -652,13 +645,9 @@ export default {
}, },
/** 处理在库现存 */ /** 处理在库现存 */
handleInventoryInner(row) { handleInventoryInner(row) {
if (!row.warehouseId) {
this.$modal.msgError("仓库信息不存在,无法查看在库现存");
return;
}
this.inventoryInnerQuery.pageNum = 1; this.inventoryInnerQuery.pageNum = 1;
this.inventoryInnerQuery.productCode = row.productCode; this.inventoryInnerQuery.productCode = row.productCode;
this.inventoryInnerQuery.warehouseId = row.warehouseId; this.inventoryInnerQuery.warehouseId = null;
this.currentInventoryInnerProductName = row.productName; this.currentInventoryInnerProductName = row.productName;
this.currentInventoryInnerTotal = row.inventoryNum; this.currentInventoryInnerTotal = row.inventoryNum;
this.inventoryInnerVisible = true; this.inventoryInnerVisible = true;
@ -697,13 +686,9 @@ export default {
}, },
/** 处理在途库存 */ /** 处理在途库存 */
handlePurchaseStock(row) { handlePurchaseStock(row) {
if (!row.warehouseId) {
this.$modal.msgError("仓库信息不存在,无法查看在途库存");
return;
}
this.purchaseStockQuery.pageNum = 1; this.purchaseStockQuery.pageNum = 1;
this.purchaseStockQuery.productCode = row.productCode; this.purchaseStockQuery.productCode = row.productCode;
this.purchaseStockQuery.warehouseId = row.warehouseId; this.purchaseStockQuery.warehouseId = null;
this.currentPurchaseStockProductName = row.productName; this.currentPurchaseStockProductName = row.productName;
this.currentPurchaseStockTotal = row.purchaseNum; this.currentPurchaseStockTotal = row.purchaseNum;
this.purchaseStockVisible = true; this.purchaseStockVisible = true;
@ -723,13 +708,9 @@ export default {
}, },
/** 处理锁单量 */ /** 处理锁单量 */
handleBindOrder(row) { handleBindOrder(row) {
if (!row.warehouseId) {
this.$modal.msgError("仓库信息不存在,无法查看锁单量");
return;
}
this.bindOrderQuery.pageNum = 1; this.bindOrderQuery.pageNum = 1;
this.bindOrderQuery.productCode = row.productCode; this.bindOrderQuery.productCode = row.productCode;
this.bindOrderQuery.warehouseId = row.warehouseId; this.bindOrderQuery.warehouseId = null;
this.currentBindOrderProductName = row.productName; this.currentBindOrderProductName = row.productName;
this.currentBindOrderTotal = row.bindNum; this.currentBindOrderTotal = row.bindNum;
this.bindOrderVisible = true; this.bindOrderVisible = true;

View File

@ -25,6 +25,8 @@ import java.io.InputStream;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/** /**
* Controller (Vue) * Controller (Vue)
@ -124,6 +126,18 @@ public class VueInventoryOuterController extends BaseController
if (inventoryInfoExcelDtoList.size()!=quantity.intValue()){ if (inventoryInfoExcelDtoList.size()!=quantity.intValue()){
return AjaxResult.error("导入数据应等于发货数量"); return AjaxResult.error("导入数据应等于发货数量");
} }
List<String> repeatSnList = inventoryInfoExcelDtoList.stream()
.map(InventoryInfoExcelDto::getProductSn)
.filter(sn -> sn != null && !sn.trim().isEmpty())
.collect(Collectors.groupingBy(String::trim, Collectors.counting()))
.entrySet()
.stream()
.filter(entry -> entry.getValue() > 1)
.map(Map.Entry::getKey)
.collect(Collectors.toList());
if (!repeatSnList.isEmpty()) {
throw new ServiceException("文件中存在重复SN码" + repeatSnList);
}
return AjaxResult.success(innerService.getInventoryInfoList(inventoryInfoExcelDtoList, productCode,orderType)); return AjaxResult.success(innerService.getInventoryInfoList(inventoryInfoExcelDtoList, productCode,orderType));
} catch (IOException e) { } catch (IOException e) {
@ -150,6 +164,18 @@ public class VueInventoryOuterController extends BaseController
if (CollUtil.isEmpty(inventoryInfoExcelDtoList)) { if (CollUtil.isEmpty(inventoryInfoExcelDtoList)) {
return AjaxResult.error("导入数据为空"); return AjaxResult.error("导入数据为空");
} }
List<String> repeatSnList = inventoryInfoExcelDtoList.stream()
.map(InventoryInfoExcelDto::getProductSn)
.filter(sn -> sn != null && !sn.trim().isEmpty())
.collect(Collectors.groupingBy(String::trim, Collectors.counting()))
.entrySet()
.stream()
.filter(entry -> entry.getValue() > 1)
.map(Map.Entry::getKey)
.collect(Collectors.toList());
if (!repeatSnList.isEmpty()) {
throw new ServiceException("文件中存在重复SN码" + repeatSnList);
}
return AjaxResult.success(innerService.validateAndGetAssignDeliveryList( return AjaxResult.success(innerService.validateAndGetAssignDeliveryList(
inventoryInfoExcelDtoList, productCode, orderType, purchaseNo)); inventoryInfoExcelDtoList, productCode, orderType, purchaseNo));

View File

@ -19,6 +19,8 @@ import org.springframework.web.multipart.MultipartFile;
import java.io.IOException; import java.io.IOException;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/** /**
* (Vue) Controller * (Vue) Controller
@ -125,6 +127,18 @@ public class VueOmsInventoryInnerController extends BaseController {
ExcelUtil<WarehouseInnerExcelDto> util = new ExcelUtil<>(WarehouseInnerExcelDto.class); ExcelUtil<WarehouseInnerExcelDto> util = new ExcelUtil<>(WarehouseInnerExcelDto.class);
try { try {
List<WarehouseInnerExcelDto> excelList = util.importExcel(file.getInputStream()); List<WarehouseInnerExcelDto> excelList = util.importExcel(file.getInputStream());
List<String> repeatSnList = excelList.stream()
.map(WarehouseInnerExcelDto::getProductSn)
.filter(sn -> sn != null && !sn.trim().isEmpty())
.collect(Collectors.groupingBy(String::trim, Collectors.counting()))
.entrySet()
.stream()
.filter(entry -> entry.getValue() > 1)
.map(Map.Entry::getKey)
.collect(Collectors.toList());
if (!repeatSnList.isEmpty()) {
throw new ServiceException("文件中存在重复SN码" + repeatSnList);
}
return AjaxResult.success(inventoryInfoService.fillBaseInfo(excelList)); return AjaxResult.success(inventoryInfoService.fillBaseInfo(excelList));
} catch (ServiceException e) { } catch (ServiceException e) {
return AjaxResult.error(e.getMessage()); return AjaxResult.error(e.getMessage());

View File

@ -10,6 +10,4 @@ public class ProductInventoryQueryDTO {
/** 产品编码 */ /** 产品编码 */
private String productCode; private String productCode;
/** 仓库ID */
private Long warehouseId;
} }

View File

@ -177,6 +177,7 @@ public class ProjectOrderInfoToolProvider extends AbstractMcpToolProvider {
item.put("requiredDeliveryDate", formatDate(orderInfo.getDeliveryTime())); item.put("requiredDeliveryDate", formatDate(orderInfo.getDeliveryTime()));
item.put("contractCode", orderInfo.getOrderCode()); item.put("contractCode", orderInfo.getOrderCode());
item.put("projectName", orderInfo.getProjectName()); item.put("projectName", orderInfo.getProjectName());
item.put("h3cSales", projectInfo == null ? "" : projectInfo.getH3cPerson());
item.put("agentName", orderInfo.getAgentName()); item.put("agentName", orderInfo.getAgentName());
item.put("orderStatus", DictUtils.getDictLabel("order_status", orderInfo.getOrderStatus())); item.put("orderStatus", DictUtils.getDictLabel("order_status", orderInfo.getOrderStatus()));
item.put("orderStockingStatus", resolveOrderStockingStatus(orderInfo)); item.put("orderStockingStatus", resolveOrderStockingStatus(orderInfo));

View File

@ -105,7 +105,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
inner join oms_inventory_info as t2 on t1.inner_code = t2.inner_code inner join oms_inventory_info as t2 on t1.inner_code = t2.inner_code
<where> <where>
<if test="productCode != null and productCode != ''">and t2.product_code = #{productCode}</if> <if test="productCode != null and productCode != ''">and t2.product_code = #{productCode}</if>
<if test="warehouseId != null">and t2.warehouse_id = #{warehouseId}</if>
</where> </where>
group by t1.id group by t1.id
having inventory_num > 0 having inventory_num > 0

View File

@ -261,7 +261,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
inner join oms_purchase_order_item as t2 on t1.id = t2.purchase_id inner join oms_purchase_order_item as t2 on t1.id = t2.purchase_id
<where> <where>
<if test="productCode != null and productCode != ''">and t2.product_code = #{productCode}</if> <if test="productCode != null and productCode != ''">and t2.product_code = #{productCode}</if>
<if test="warehouseId != null">and t1.warehouse_id = #{warehouseId}</if>
and t2.quantity - t2.inner_quantity &gt; 0 and t2.quantity - t2.inner_quantity &gt; 0
</where> </where>
order by t1.create_time desc order by t1.create_time desc
@ -285,13 +284,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
from oms_inventory_info from oms_inventory_info
<where> <where>
<if test="productCode != null and productCode != ''">and product_code = #{productCode}</if> <if test="productCode != null and productCode != ''">and product_code = #{productCode}</if>
<if test="warehouseId != null">and warehouse_id = #{warehouseId}</if>
</where> </where>
group by order_code group by order_code
) as t6 on t1.order_code = t6.order_code ) as t6 on t1.order_code = t6.order_code
<where> <where>
<if test="productCode != null and productCode != ''">and t2.product_code = #{productCode}</if> <if test="productCode != null and productCode != ''">and t2.product_code = #{productCode}</if>
<if test="warehouseId != null">and t3.warehouse_id = #{warehouseId}</if>
</where> </where>
group by t1.id group by t1.id
having bind_num != 0 having bind_num != 0

View File

@ -131,37 +131,33 @@
</select> </select>
<select id="listInventory" resultType="com.ruoyi.sip.domain.ProductInfo"> <select id="listInventory" resultType="com.ruoyi.sip.domain.ProductInfo">
SELECT SELECT
t4.warehouse_name,
ifnull(t2.warehouse_id, t3.warehouse_id) as warehouse_id,
t3.vendor_name, t3.vendor_name,
t1.*, t1.*,
t2.inventory_num, t2.inventory_num,
t2.outer_num, t2.outer_num,
t2.purchase_num, t4.purchase_num,
ifnull(t2.bind_num,0) - ifnull(t2.outer_num,0) as bind_num, ifnull(t2.bind_num,0) - ifnull(t2.outer_num,0) as bind_num,
ifnull(t2.inventory_num,0) + ifnull(t2.purchase_num,0) - (ifnull(t2.bind_num,0) - ifnull(t2.outer_num,0)) as usable_num ifnull(t2.inventory_num,0) + ifnull(t4.purchase_num,0) - (ifnull(t2.bind_num,0) - ifnull(t2.outer_num,0)) as usable_num
FROM product_info t1 FROM product_info t1
LEFT JOIN ( LEFT JOIN (
SELECT product_code, warehouse_id, SELECT product_code,
sum((case when inventory_status = 0 then 1 else 0 end)) as inventory_num, sum((case when inventory_status = 0 then 1 else 0 end)) as inventory_num,
sum((case when inventory_status = 1 then 1 else 0 end)) as outer_num, sum((case when inventory_status = 1 then 1 else 0 end)) as outer_num,
(
select sum(tt2.quantity) - sum(tt2.inner_quantity)
from oms_purchase_order_item as tt2
inner join oms_purchase_order as tt3 on tt2.purchase_id = tt3.id
where tt1.product_code = tt2.product_code and tt3.warehouse_id = tt1.warehouse_id
) as purchase_num,
( (
select sum(bind_num) from oms_purchase_order as tt2 select sum(bind_num) from oms_purchase_order as tt2
inner join oms_purchase_order_map as tt3 on tt2.id = tt3.purchase_id inner join oms_purchase_order_map as tt3 on tt2.id = tt3.purchase_id
where tt1.product_code = tt3.product_code where tt1.product_code = tt3.product_code
and tt1.warehouse_id = tt2.warehouse_id
) as bind_num ) as bind_num
FROM oms_inventory_info as tt1 FROM oms_inventory_info as tt1
GROUP BY product_code, warehouse_id GROUP BY product_code
) t2 ON t1.product_code = t2.product_code ) t2 ON t1.product_code = t2.product_code
left join oms_vendor_info t3 on t1.vendor_code = t3.vendor_code left join oms_vendor_info t3 on t1.vendor_code = t3.vendor_code
left join oms_warehouse_info t4 on t4.id = ifnull(t2.warehouse_id, t3.warehouse_id) left join (
select tt1.product_code, sum(tt1.quantity) - sum(tt1.inner_quantity) as purchase_num
from oms_purchase_order_item as tt1
inner join oms_purchase_order as tt2 on tt1.purchase_id = tt2.id
group by product_code
) as t4 on t1.product_code = t4.product_code
<where> <where>
<if test="productCode != null and productCode != ''">and t1.product_code like concat('%', #{productCode}, <if test="productCode != null and productCode != ''">and t1.product_code like concat('%', #{productCode},
'%') '%')
@ -180,9 +176,6 @@
'%') '%')
</if> </if>
<if test="vendorCode != null and vendorCode != ''">and t1.vendor_code = #{vendorCode}</if> <if test="vendorCode != null and vendorCode != ''">and t1.vendor_code = #{vendorCode}</if>
<if test="warehouseId != null">
and ifnull(t2.warehouse_id, t3.warehouse_id) = #{warehouseId}
</if>
</where> </where>
</select> </select>