feat(sip): 增强采购订单与库存管理功能

- 修改采购订单状态判断逻辑,优化供应商确认按钮显示条件
- 库存导入接口新增订单类型参数,支持不同类型订单处理
- 完善库存信息校验逻辑,增加产品编码一致性检查
- 采购订单查询增加权限控制,支持按供应商编码过滤
- 优化采购订单详情计算逻辑,增强金额计算准确性
- 调整侧边栏字体大小,改善界面显示效果
- 修复Vue组件中价格设置相关逻辑问题
- 移除无用的控制台日志输出和冗余代码引用
master
chenhao 2025-12-08 17:01:23 +08:00
parent da0a5c8014
commit 675c1f3b95
17 changed files with 99 additions and 47 deletions

View File

@ -99,7 +99,7 @@ export default {
</script>
<style lang="scss" scoped>
::v-deep .el-submenu__title {
font-size: 15px;
font-size: 14px;
font-weight: bold;
}
</style>

View File

@ -164,7 +164,8 @@
</style>
<script>
import { getOrder, addOrder, updateOrder, delContractFile, uploadContractFile, getProject } from "@/api/project/order";
import { getOrder, addOrder, updateOrder, delContractFile, uploadContractFile } from "@/api/project/order";
import { getProject } from "@/api/project/info";
import ProductConfig from '@/views/project/info/ProductConfig.vue';
import SelectCommitType from "./SelectCommitType.vue";
import OrderInfo from '@/views/project/order/components/OrderInfo.vue';
@ -399,6 +400,8 @@ export default {
]
});
this.activeContractVersionTab = currentVersion;
console.log('11111')
console.log(this.projectId)
if (this.projectId) {
getProject(this.projectId).then(response => {
this.handleProjectSelected(response.data.project);

View File

@ -82,7 +82,7 @@
</el-col>
<el-col :span="(localOrderData.processTemplate=='1' ||(localOrderData.processTemplate!='1' &&( localOrderData.orderStatus=='1'||localOrderData.orderStatus=='2')))?8:16">
<el-form-item label="总代出货金额" prop="shipmentAmount">
<el-input v-model="localOrderData.shipmentAmount" placeholder="请输入金额" :disabled="isReadonly"/>
<el-input v-model="localOrderData.shipmentAmount" placeholder="请输入金额" readonly :disabled="isReadonly"/>
</el-form-item>
</el-col>
<el-col :span="8">

View File

@ -286,9 +286,9 @@ export default {
},
totalAmountWithoutTax() {
const total = this.form.omsPurchaseOrderItemList?.reduce((acc, cur) => {
const amount = this.$calc.mul(cur.quantity, cur.price) || 0;
const amount = this.$calc.mul(cur.quantity||0, cur.price||0) || 0;
const taxRate = cur.taxRate || 0;
console.log(taxRate)
return acc + this.$calc.div(amount , (1 + taxRate));
}, 0);
return (this.$calc.toFixed(total)) || 0;
@ -369,7 +369,7 @@ export default {
this.$set(item, 'productCode', product.productCode);
this.$set(item, 'productModel', product.model);
this.$set(item, 'productDescription', product.description);
this.$set(item, 'price', product.cataloguePrice);
// this.$set(item, 'price', product.cataloguePrice);
this.calculateRowTotal(item)
}
this.productSelectOpen = false;
@ -402,13 +402,10 @@ export default {
},
/** 计算含税小计 */
calculateRowTotal(row) {
if (row.quantity != null && row.price != null) {
row.amountTotal = this.$calc.mul(row.quantity , row.price);
row.taxTotal = row.amountTotal - this.$calc.div(row.amountTotal , (1 + row.taxRate));
} else {
row.amountTotal = 0;
row.taxTotal = 0;
}
row.amountTotal = this.$calc.mul(row.quantity || 0, row.price || 0);
row.taxTotal = row.amountTotal - this.$calc.div(row.amountTotal, (1 + row.taxRate || 0));
},
/** 获取厂商列表 */
getVendorList() {

View File

@ -228,7 +228,6 @@ import {listAllVendor} from "@/api/base/vendor";
import {getDicts} from "@/api/system/dict/data";
export default {
name: "PurchaseOrderDetailView",
dicts: ['approve_status'],
@ -309,7 +308,11 @@ export default {
created() {
this.getVendorList().then(() => {
getDicts("product_type").then(response => {
this.productTypeOptions = response.data;
this.productTypeOptions = response.data.map(item => ({
value: item.dictValue,
label: item.dictLabel,
id:item.id
}));
});
// orderData
if (this.orderData) {

View File

@ -168,7 +168,7 @@
>发起供应商确认
</el-button>
<el-button
v-if="scope.row.approveStatus === '2' && (!scope.row.confirmStatus || scope.row.confirmStatus === ''|| scope.row.confirmStatus === '2')"
v-if="scope.row.approveStatus === '2' && (!scope.row.confirmStatus || scope.row.confirmStatus === ''|| scope.row.confirmStatus === '1')"
size="mini"
type="text"
icon="el-icon-refresh-left"

View File

@ -5,20 +5,12 @@ import java.io.InputStream;
import java.util.*;
import cn.hutool.core.collection.CollUtil;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.sip.domain.OmsInventoryInner;
import com.ruoyi.sip.domain.ProjectOrderFileLog;
import com.ruoyi.sip.dto.inventory.InventoryInfoExcelDto;
import com.ruoyi.sip.service.IInventoryAuthService;
import com.ruoyi.sip.service.IOmsInventoryInnerService;
import com.ruoyi.sip.vo.ExecutionOrderVo;
import com.ruoyi.sip.vo.OuterDeliveryVo;
import com.ruoyi.sip.vo.OuterViewVo;
import liquibase.pro.packaged.A;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@ -171,7 +163,8 @@ public class InventoryOuterController extends BaseController
@PostMapping("/importData")
@ResponseBody
public AjaxResult importTemplate(@RequestPart("file") MultipartFile file, @RequestParam(value = "productCode") String productCode,@RequestParam(value = "quantity") Long quantity) {
public AjaxResult importTemplate(@RequestPart("file") MultipartFile file, @RequestParam(value = "productCode") String productCode
, @RequestParam(value = "orderType") String orderType,@RequestParam(value = "quantity") Long quantity) {
ExcelUtil<InventoryInfoExcelDto> util = new ExcelUtil<InventoryInfoExcelDto>(InventoryInfoExcelDto.class);
try (InputStream inputStream = file.getInputStream()) {
@ -182,7 +175,7 @@ public class InventoryOuterController extends BaseController
if (inventoryInfoExcelDtoList.size()!=quantity.intValue()){
return AjaxResult.error("导入数据应等于发货数量");
}
return AjaxResult.success(innerService.getInventoryInfoList(inventoryInfoExcelDtoList, productCode));
return AjaxResult.success(innerService.getInventoryInfoList(inventoryInfoExcelDtoList, productCode, orderType));
} catch (IOException e) {
throw new ServiceException("读取excel错误,请联系管理员");

View File

@ -1,5 +1,6 @@
package com.ruoyi.sip.controller.vue;
import cn.hutool.core.collection.CollUtil;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
@ -8,9 +9,11 @@ import com.ruoyi.common.enums.ApproveStatusEnum;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.sip.domain.OmsPurchaseOrder;
import com.ruoyi.sip.domain.VendorInfo;
import com.ruoyi.sip.dto.inventory.OmsPurchaseOrderItemDto;
import com.ruoyi.sip.flowable.domain.Todo;
import com.ruoyi.sip.flowable.service.TodoService;
import com.ruoyi.sip.service.IInventoryAuthService;
import com.ruoyi.sip.service.IOmsPurchaseOrderHistoryService;
import com.ruoyi.sip.service.IOmsPurchaseOrderService;
import org.apache.shiro.authz.annotation.RequiresPermissions;
@ -19,7 +22,9 @@ import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
* Controller
@ -39,6 +44,9 @@ public class OmsPurchaseOrderController extends BaseController
@Autowired
private TodoService todoService;
@Autowired
private IInventoryAuthService inventoryAuthService;
/**
*
*/
@ -46,6 +54,14 @@ public class OmsPurchaseOrderController extends BaseController
@GetMapping("/list")
public TableDataInfo list(OmsPurchaseOrder omsPurchaseOrder)
{
if (!inventoryAuthService.authAll()) {
List<VendorInfo> vendorInfos = inventoryAuthService.currentVendor();
if (CollUtil.isEmpty(vendorInfos)) {
return getDataTable(Collections.emptyList());
}
omsPurchaseOrder.setAuthVendorCodeList(vendorInfos.stream().map(VendorInfo::getVendorCode).collect(Collectors.toList()));
}
startPage();
List<OmsPurchaseOrder> list = omsPurchaseOrderService.selectOmsPurchaseOrderList(omsPurchaseOrder);
clearPage();
@ -59,6 +75,14 @@ public class OmsPurchaseOrderController extends BaseController
@GetMapping("/item/list")
public TableDataInfo listItem(OmsPurchaseOrderItemDto omsPurchaseOrder)
{
if (!inventoryAuthService.authAll()) {
List<VendorInfo> vendorInfos = inventoryAuthService.currentVendor();
if (CollUtil.isEmpty(vendorInfos)) {
return getDataTable(Collections.emptyList());
}
omsPurchaseOrder.setAuthVendorCodeList(vendorInfos.stream().map(VendorInfo::getVendorCode).collect(Collectors.toList()));
}
startPage();
List<OmsPurchaseOrderItemDto> list = omsPurchaseOrderService.listItem(omsPurchaseOrder);
return getDataTable(list);
@ -70,7 +94,14 @@ public class OmsPurchaseOrderController extends BaseController
@GetMapping("/vendor/list")
public TableDataInfo listVendor(OmsPurchaseOrder omsPurchaseOrder)
{
if (!inventoryAuthService.authAll()) {
List<VendorInfo> vendorInfos = inventoryAuthService.currentVendor();
if (CollUtil.isEmpty(vendorInfos)) {
return getDataTable(Collections.emptyList());
}
omsPurchaseOrder.setAuthVendorCodeList(vendorInfos.stream().map(VendorInfo::getVendorCode).collect(Collectors.toList()));
}
omsPurchaseOrder.setApproveStatus(ApproveStatusEnum.APPROVE_COMPLETE.getCode());
omsPurchaseOrder.setFlowType(OmsPurchaseOrder.FlowTypeEnum.ONLINE.getCode());
startPage();

View File

@ -110,7 +110,8 @@ public class VueInventoryOuterController extends BaseController
}
@PostMapping("/importData")
@ResponseBody
public AjaxResult importTemplate(@RequestPart("file") MultipartFile file, @RequestParam(value = "productCode") String productCode, @RequestParam(value = "quantity") Long quantity) {
public AjaxResult importTemplate(@RequestPart("file") MultipartFile file, @RequestParam(value = "productCode") String productCode
,@RequestParam(value = "orderType",defaultValue = "1") String orderType, @RequestParam(value = "quantity") Long quantity) {
ExcelUtil<InventoryInfoExcelDto> util = new ExcelUtil<InventoryInfoExcelDto>(InventoryInfoExcelDto.class);
try (InputStream inputStream = file.getInputStream()) {
@ -121,7 +122,7 @@ public class VueInventoryOuterController extends BaseController
if (inventoryInfoExcelDtoList.size()!=quantity.intValue()){
return AjaxResult.error("导入数据应等于发货数量");
}
return AjaxResult.success(innerService.getInventoryInfoList(inventoryInfoExcelDtoList, productCode));
return AjaxResult.success(innerService.getInventoryInfoList(inventoryInfoExcelDtoList, productCode,orderType));
} catch (IOException e) {
throw new ServiceException("读取excel错误,请联系管理员");

View File

@ -1,16 +1,19 @@
package com.ruoyi.sip.controller.vue;
import cn.hutool.core.collection.CollUtil;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.sip.domain.VendorInfo;
import com.ruoyi.sip.service.IInventoryAuthService;
import com.ruoyi.sip.service.IVendorInfoService;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Collections;
import java.util.List;
/**
@ -25,6 +28,8 @@ public class VueVendorInfoController extends BaseController {
@Autowired
private IVendorInfoService vendorInfoService;
@Autowired
private IInventoryAuthService inventoryAuthService;
/**
*
*/
@ -80,7 +85,7 @@ public class VueVendorInfoController extends BaseController {
*/
@GetMapping("/listAll")
public AjaxResult listAll() {
List<VendorInfo> list = vendorInfoService.selectVendorInfoList(new VendorInfo());
return AjaxResult.success(list);
return AjaxResult.success(inventoryAuthService.currentVendor());
}
}

View File

@ -87,7 +87,7 @@ public class VueWarehouseInfoController extends BaseController {
public AjaxResult listAll() {
OmsWarehouseInfo params = new OmsWarehouseInfo();
params.setWarehouseStatus(OmsWarehouseInfo.WarehouseStatusEnum.NORMAL.getValue());
List<OmsWarehouseInfo> list = omsWarehouseInfoService.list(params);
List<OmsWarehouseInfo> list = omsWarehouseInfoService.listByAuth(params);
return AjaxResult.success(list);
}
}

View File

@ -38,6 +38,7 @@ public class OmsPurchaseOrder extends BaseEntity
private Long vendorId;
private String vendorCode;
private List<String> authVendorCodeList;
private String vendorName;
private String vendorUser;
private String vendorPhone;

View File

@ -65,5 +65,5 @@ public interface IOmsInventoryInnerService
void importByOuter(List<InventoryInfo> inventoryInfoList, String productCode, String purchaseNo,Long itemId);
Map<String,Object> getInventoryInfoList(List<InventoryInfoExcelDto> inventoryInfoExcelDtoList, String productCode);
Map<String,Object> getInventoryInfoList(List<InventoryInfoExcelDto> inventoryInfoExcelDtoList, String productCode, String orderType);
}

View File

@ -3,6 +3,7 @@ package com.ruoyi.sip.service.impl;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import cn.hutool.core.collection.CollUtil;
@ -259,24 +260,30 @@ public class OmsInventoryInnerServiceImpl implements IOmsInventoryInnerService {
}
@Override
public Map<String,Object> getInventoryInfoList(List<InventoryInfoExcelDto> inventoryInfoExcelDtoList, String productCode) {
public Map<String,Object> getInventoryInfoList(List<InventoryInfoExcelDto> inventoryInfoExcelDtoList, String productCode, String orderType) {
long count = inventoryInfoExcelDtoList.stream().filter(item -> !item.getProductCode().equals(productCode)).count();
if (count > 0){
throw new ServiceException("导入清单的产品与出库单不符");
}
// List<String> warehouseNameList = inventoryInfoExcelDtoList.stream().map(InventoryInfoExcelDto::getWarehouseName).distinct().collect(Collectors.toList());
// if (warehouseNameList.size() > 1){
// throw new ServiceException("导入清单只能有一个仓库");
// }
List<ProductInfo> productInfos = productInfoService.selectProductInfoByCodeList(Collections.singletonList(productCode));
if (CollUtil.isEmpty(productInfos)){
throw new ServiceException("产品编码对应产品未找到");
}
// List<OmsWarehouseInfo> warehouseInfoList = warehouseInfoService.listByNameList(warehouseNameList);
// if (CollUtil.isEmpty(warehouseInfoList)) {
// throw new ServiceException("仓库未找到,导入失败");
// }
// Map<String, OmsWarehouseInfo> warehouseInfoMap = warehouseInfoList.stream().collect(Collectors.toMap(OmsWarehouseInfo::getWarehouseName, Function.identity(), (v1, v2) -> v1));
Map<String, OmsWarehouseInfo> warehouseInfoMap=Collections.emptyMap();
if ("2".equalsIgnoreCase(orderType)){
List<String> warehouseNameList = inventoryInfoExcelDtoList.stream().map(InventoryInfoExcelDto::getWarehouseName).distinct().collect(Collectors.toList());
if (warehouseNameList.size() > 1){
throw new ServiceException("导入清单只能有一个仓库");
}
List<OmsWarehouseInfo> warehouseInfoList = warehouseInfoService.listByNameList(warehouseNameList);
if (CollUtil.isEmpty(warehouseInfoList)) {
throw new ServiceException("仓库未找到,导入失败");
}
warehouseInfoMap = warehouseInfoList.stream().collect(Collectors.toMap(OmsWarehouseInfo::getWarehouseName, Function.identity(), (v1, v2) -> v1));
}
Map<String, OmsWarehouseInfo> finalWarehouseInfoMap=warehouseInfoMap;
List<InventoryInfo> inventoryInfoList = inventoryInfoExcelDtoList.stream().map(item -> {
InventoryInfo info = new InventoryInfo();
info.setInventoryStatus(InventoryInfo.InventoryStatusEnum.INNER.getCode());
@ -285,9 +292,12 @@ public class OmsInventoryInnerServiceImpl implements IOmsInventoryInnerService {
info.setModel(productInfos.get(0).getModel());
info.setProductDesc(productInfos.get(0).getDescription());
info.setInnerPrice(item.getInnerPrice());
// OmsWarehouseInfo omsWarehouseInfo = warehouseInfoMap.get(item.getWarehouseName());
// info.setWarehouseId(omsWarehouseInfo.getId());
// info.setWarehouseName(omsWarehouseInfo.getWarehouseName());
if ("2".equalsIgnoreCase(orderType)){
OmsWarehouseInfo omsWarehouseInfo = finalWarehouseInfoMap.get(item.getWarehouseName());
info.setWarehouseId(omsWarehouseInfo.getId());
info.setWarehouseName(omsWarehouseInfo.getWarehouseName());
}
return info;
}).collect(Collectors.toList());

View File

@ -20,6 +20,7 @@ import com.ruoyi.sip.flowable.service.TodoService;
import com.ruoyi.sip.mapper.OmsPurchaseOrderItemHistoryMapper;
import com.ruoyi.sip.mapper.OmsPurchaseOrderHistoryMapper;
import com.ruoyi.sip.service.ICnareaService;
import com.ruoyi.sip.service.IInventoryAuthService;
import com.ruoyi.sip.service.IVendorInfoService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
@ -373,6 +374,7 @@ public class OmsPurchaseOrderServiceImpl implements IOmsPurchaseOrderService, To
for (OmsPurchaseOrderItem omsPurchaseOrderItem : omsPurchaseOrderItemList)
{
omsPurchaseOrderItem.setPurchaseId(id);
omsPurchaseOrderItem.setInnerQuantity(BigDecimal.ZERO);
list.add(omsPurchaseOrderItem);
}
if (list.size() > 0)
@ -490,7 +492,7 @@ public class OmsPurchaseOrderServiceImpl implements IOmsPurchaseOrderService, To
OmsPurchaseOrder omsPurchaseOrder = new OmsPurchaseOrder();
omsPurchaseOrder.setPurchaseNo(businessKey);
omsPurchaseOrder.setApproveStatus(ApproveStatusEnum.APPROVE_COMPLETE.getCode());
if (existOrder.getFlowType().equalsIgnoreCase(OmsPurchaseOrder.FlowTypeEnum.OFFLINE.getValue())){
if (existOrder.getFlowType().equalsIgnoreCase(OmsPurchaseOrder.FlowTypeEnum.OFFLINE.getCode())){
omsPurchaseOrder.setConfirmStatus(OmsPurchaseOrder.ConfirmStatusEnum.CONFIRM.getCode());
}
omsPurchaseOrder.setApproveTime(DateUtils.getNowDate());

View File

@ -523,7 +523,7 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
public String exportList(ProjectOrderInfo projectOrderInfo) {
try {
// 获取项目信息列表
List<ProjectOrderInfo> projectInfos = fetchProjectInfos(projectOrderInfo);
List<ProjectOrderInfo> projectInfos = this.selectProjectOrderInfoList(projectOrderInfo);
// 补充项目详细数据
enrichProjectData(projectInfos);

View File

@ -87,6 +87,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="flowType != null "> and t1.flow_type = #{flowType}</if>
<if test="vendorName != null "> and t2.vendor_name = #{vendorName}</if>
<if test="ownerName != null "> and t1.owner_name = #{ownerName}</if>
<if test="authVendorCodeList != null and authVendorCodeList.size>0 "> and t2.vendor_code in
<foreach item="item" collection="authVendorCodeList" separator="," open="(" close=")">#{item}</foreach>
</if>
</where>
</select>
@ -192,6 +195,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#{item}
</foreach>
</if>
<if test="authVendorCodeList != null and authVendorCodeList.size>0 "> and t4.vendor_code in
<foreach item="item" collection="authVendorCodeList" separator="," open="(" close=")">#{item}</foreach>
</if>
</where>
order by t2.create_time desc