fix(inventory): 优化库存管理和出库流程

- 修复 SN 码解析逻辑,增加数字校验
- 更新出库管理界面,优化排序和状态显示
- 优化订单执行跟踪界面,调整排序方式
- 优化项目订单审批流程,重构审批回调逻辑
dev_1.0.0
chenhao 2025-08-18 15:25:03 +08:00
parent 53ccb630d5
commit 0656894960
9 changed files with 124 additions and 54 deletions

View File

@ -593,7 +593,6 @@ function initWarehouseTable(data) {
function onEditableSave(field, row, rowIndex, oldValue, $el) {
if (!row['defaultWarehouse'] && row[field] > row['availableCount']) {
$.modal.msgError("库存不足")
row[field] = oldValue
@ -605,8 +604,8 @@ function initWarehouseTable(data) {
totalConfirmQuantity += Number(item.confirmQuantity || 0)
});
let generateNumber = $('#out-generatedQuantity').text();
totalConfirmQuantity += Number(generateNumber)
if (totalConfirmQuantity > Number($('#out-quantity').text())) {
let allTotal=totalConfirmQuantity + Number(generateNumber)
if (allTotal > Number($('#out-quantity').text())) {
$.modal.msgError("本次提交出库数量不能大于应出库数量")
row[field] = oldValue
return;
@ -626,7 +625,7 @@ function initWarehouseTable(data) {
$('#outer-model').val(model)
$('#outer-vendorName').val(vendorName)
$('#out-quantity').text(quantity)
$('#out-generatedQuantity').text(generatedQuantity)
$('#out-generatedQuantity').text(Number(generatedQuantity)+Number(confirmQuantity))
$('#deliveryTime').val(getNowDate());
$('#deliveryTime').attr('disabled', true);
parent.$('.layui-layer-btn').css('display', 'none')
@ -702,6 +701,7 @@ function initWarehouseTable(data) {
var options = {
id: "outer-table",
data: data ?? [[${inventoryOuterList}]],
sidePagination: "client",
showSearch: false,
showRefresh: false,
showToggle: false,

View File

@ -118,7 +118,7 @@
</form>
</div>
<input id="uploadInput" type="file" accept=".xls,.xlsx,.zip,.rar" style="display: none">
<input id="uploadInput" type="file" accept=".zip,.rar" style="display: none">
<input type="hidden" id="orderId">
<input type="hidden" id="versionCode">
<div class="col-sm-12 select-table table-striped">
@ -229,8 +229,8 @@
removeUrl: prefix + "/remove",
exportUrl: prefix + "/export",
modalName: "订单执行跟踪",
sortName:'outerStatus',
sortOrder: 'asc',
sortName:'approveTime',
sortOrder: 'desc',
fixedColumns: true,
fixedRightNumber: 1,
columns: [{

View File

@ -97,7 +97,16 @@
field: 'availableCount',
title: '实时库存',
formatter: function (value, row, index) {
return value ??0;
let showValue= value ??0;
let showHtml=''
if (value>200){
showHtml= `<span style="color: #1ab394">${showValue}</span>`
}else if (value<=0){
showHtml= `<span style="color: red">${showValue}</span>`
}else{
showHtml= `<span style="color: #f59a4d">${showValue}</span>`
}
return showHtml;
}
},
{

View File

@ -71,10 +71,6 @@
}
},
{
field: 'warehouseName',
title: '出库仓'
},
{
field: 'createByName',
title: '经办人'

View File

@ -203,7 +203,6 @@
// 解析SN码分离前缀和数字部分
let snPrefix = "";
let snNumber = "";
debugger
// 从字符串末尾开始查找数字部分
for (let i = productSn.length - 1; i >= 0; i--) {
if (!isNaN(productSn[i]) && productSn[i] !== ' ') {
@ -214,6 +213,10 @@ debugger
}
}
let snNumberLength = snNumber.length;
if (snNumberLength === 0) {
$.modal.msgError("SN码最后一位必须为数字,否则无法按顺序计算对应SN码");
return;
}
let startNumber = parseInt(snNumber);
// 计算当前SN码的数字部分
@ -275,6 +278,10 @@ debugger
}
}
let snNumberLength = snNumber.length;
if (snNumberLength === 0) {
$.modal.msgError("SN码最后一位必须为数字,否则无法按顺序计算对应SN码");
return;
}
let startNumber = parseInt(snNumber);
for (let i = 0; i <quantity; i++) {
// 计算当前SN码的数字部分

View File

@ -58,6 +58,8 @@
removeUrl: prefix + "/remove",
exportUrl: prefix + "/export",
modalName: "发货管理",
sortName:'t1.createTime',
sortOrder:'desc',
columns: [{
title: '序号',
formatter: function (value, row, index) {
@ -140,7 +142,7 @@
function received(id) {
$.modal.confirm("确认要确认接收吗?", function () {
$.operate.post(prefix + "/status", {"id": id, "outerStatus": '3'},()=>{
// $.table.search()
// $.table.refresh()
});
})
}
@ -148,7 +150,7 @@
function refundable(id) {
$.modal.confirm("确认要确认退回吗?", function () {
$.operate.post(prefix + "/status", {"id": id, "outerStatus": '4'},()=>{
// $.table.search()
// $.table.refresh()
});
})
}

View File

@ -116,7 +116,7 @@ public class ExecutionTrackServiceImpl implements IExecutionTrackService {
inventoryOuter.setProductCodeList(productCodeList);
List<InventoryOuter> inventoryOuters = outerService.selectInventoryOuterList(inventoryOuter);
vo.setInventoryOuterList(inventoryOuters);
vo.setInventoryOuterList(inventoryOuters.stream().sorted(Comparator.comparing(InventoryOuter::getCreateTime).reversed()).collect(Collectors.toList()));
// 根据出库单状态设置generatedQuantity和confirmQuantity
if (inventoryOuters != null && !inventoryOuters.isEmpty()) {
Map<String, List<InventoryOuter>> outersByProductCode = inventoryOuters.stream()

View File

@ -112,6 +112,7 @@ public class OmsInventoryInnerServiceImpl implements IOmsInventoryInnerService {
item.setInnerCode(omsInventoryInner.getInnerCode());
item.setCreateBy(currentUserId);
item.setCreateTime(nowDate);
item.setInventoryStatus(InventoryInfo.InventoryStatusEnum.INNER.getCode());
});
//校验sn是否重复
List<String> repeatSnList = inventoryInfoService.checkUnq(inventoryInfoList.stream().map(InventoryInfo::getProductSn).collect(Collectors.toList()));
@ -199,9 +200,9 @@ public class OmsInventoryInnerServiceImpl implements IOmsInventoryInnerService {
return info;
}).collect(Collectors.toList());
List<ProductInfo> productInfos = productInfoService.selectProductInfoByCodeList(Collections.singletonList(productCode));
OmsInventoryInner omsInventoryInner = new OmsInventoryInner();
omsInventoryInner.setVendorCode(inventoryAuthService.currentVendor().get(0).getVendorCode());
omsInventoryInner.setVendorCode(productInfos.get(0).getVendorCode());
omsInventoryInner.setProductCode(productCode);
omsInventoryInner.setWarehouseId(warehouseInfoList.get(0).getId());
omsInventoryInner.setInventoryInfoList(inventoryInfoList);

View File

@ -1008,48 +1008,103 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
@Override
public boolean todoApproveCallback(Todo todo) {
if (CollUtil.isNotEmpty(todo.getVariables())) {
Integer approveBtn = (Integer) todo.getVariables().get("approveBtn");
if (approveBtn != null && approveBtn.equals(0)) {
//审批驳回 修改状态
ProjectOrderInfo projectOrderInfo = new ProjectOrderInfo();
projectOrderInfo.setOrderStatus(ProjectOrderInfo.OrderStatus.APPROVE_REJECT.getCode());
projectOrderInfo.setOrderCode(todo.getBusinessKey());
if ("公司领导".equals(todo.getTaskName())) {
projectOrderInfo.setVersionCode("add");
}
projectOrderInfoMapper.updateProjectOrderInfoByCode(projectOrderInfo);
}
if ("公司领导".equals(todo.getTaskName()) && approveBtn.equals(1)) {
ProjectOrderInfo dbProjectOrderInfo = projectOrderInfoMapper.selectProjectOrderInfoByCode(todo.getBusinessKey());
ProjectOrderInfo projectOrderInfo = new ProjectOrderInfo();
projectOrderInfo.setOrderStatus(ProjectOrderInfo.OrderStatus.APPROVE_COMPLETE.getCode());
projectOrderInfo.setApproveTime(DateUtils.getNowDate());
//修改执行单时间 只有直签且有现金折扣的时间才是配置时间 否则默认30天
int addHour = ProjectOrderInfo.ProcessTemplateEnum.DIRECT_SIGNING.getCode().equals(dbProjectOrderInfo.getProcessTemplate())
&& dbProjectOrderInfo.getDiscountFold() != null && dbProjectOrderInfo.getDiscountFold().compareTo(BigDecimal.ONE) < 0 ? endHour : 30;
projectOrderInfo.setOrderEndTime(DateUtils.addHours(DateUtils.getNowDate(), addHour));
projectOrderInfo.setOrderCode(todo.getBusinessKey());
projectOrderInfoMapper.updateProjectOrderInfoByCode(projectOrderInfo);
projectOrderInfoMapper.bakData(projectOrderInfo);
//修改产品数据
// projectInfo
if (dbProjectOrderInfo.getDiscountFold().compareTo(BigDecimal.ONE) != 0) {
if (CollUtil.isEmpty(todo.getVariables())) {
return TodoCommonTemplate.super.todoApproveCallback(todo);
}
productInfoService.calcByDiscountFold(dbProjectOrderInfo.getDiscountFold(), dbProjectOrderInfo.getProjectId());
}
//查询商务
List<SysUser> sysUsers = userService.listByRoleId(businessRoleId);
List<String> emailList = sysUsers.stream().map(SysUser::getEmail).filter(StringUtils::isNotEmpty).collect(Collectors.toList());
//查询代理商
List<PartnerInfo> partnerInfos = partnerInfoService.listByOrderCode(Collections.singletonList(dbProjectOrderInfo.getOrderCode()));
emailList.addAll(partnerInfos.stream().map(PartnerInfo::getContactEmail).filter(StringUtils::isNotEmpty).collect(Collectors.toList()));
this.sendPartnerMail(emailList.stream().distinct().collect(Collectors.toList()), dbProjectOrderInfo);
Integer approveBtn = (Integer) todo.getVariables().get("approveBtn");
if (approveBtn == null) {
return TodoCommonTemplate.super.todoApproveCallback(todo);
}
String taskName = todo.getTaskName();
String businessKey = todo.getBusinessKey();
// 审批驳回处理
if (approveBtn.equals(0)) {
handleRejectOrder(taskName, businessKey);
} else if (approveBtn.equals(1)) {
// 审批通过处理
if ("产品经理".equals(taskName)) {
handleProductManagerApproval(businessKey);
} else if ("公司领导".equals(taskName)) {
handleCompanyLeaderApproval(businessKey);
}
}
return TodoCommonTemplate.super.todoApproveCallback(todo);
}
/**
*
*/
private void handleRejectOrder(String taskName, String businessKey) {
ProjectOrderInfo projectOrderInfo = new ProjectOrderInfo();
projectOrderInfo.setOrderStatus(ProjectOrderInfo.OrderStatus.APPROVE_REJECT.getCode());
projectOrderInfo.setOrderCode(businessKey);
if ("公司领导".equals(taskName)) {
projectOrderInfo.setVersionCode("add");
}
projectOrderInfoMapper.updateProjectOrderInfoByCode(projectOrderInfo);
}
/**
*
*/
private void handleProductManagerApproval(String businessKey) {
ProjectOrderInfo dbProjectOrderInfo = projectOrderInfoMapper.selectProjectOrderInfoByCode(businessKey);
// 查询商务和代理商邮箱
List<String> emailList = new ArrayList<>();
// 查询商务邮箱
List<SysUser> sysUsers = userService.listByRoleId(businessRoleId);
emailList.addAll(sysUsers.stream()
.map(SysUser::getEmail)
.filter(StringUtils::isNotEmpty)
.collect(Collectors.toList()));
// 查询代理商邮箱
List<PartnerInfo> partnerInfos = partnerInfoService.listByOrderCode(Collections.singletonList(dbProjectOrderInfo.getOrderCode()));
emailList.addAll(partnerInfos.stream()
.map(PartnerInfo::getContactEmail)
.filter(StringUtils::isNotEmpty)
.collect(Collectors.toList()));
// 发送邮件
this.sendPartnerMail(emailList.stream().distinct().collect(Collectors.toList()), dbProjectOrderInfo);
}
/**
*
*/
private void handleCompanyLeaderApproval(String businessKey) {
ProjectOrderInfo dbProjectOrderInfo = projectOrderInfoMapper.selectProjectOrderInfoByCode(businessKey);
ProjectOrderInfo projectOrderInfo = new ProjectOrderInfo();
projectOrderInfo.setOrderStatus(ProjectOrderInfo.OrderStatus.APPROVE_COMPLETE.getCode());
projectOrderInfo.setApproveTime(DateUtils.getNowDate());
// 修改执行单时间 只有直签且有现金折扣的时间才是配置时间 否则默认30天
int addHour = ProjectOrderInfo.ProcessTemplateEnum.DIRECT_SIGNING.getCode().equals(dbProjectOrderInfo.getProcessTemplate())
&& dbProjectOrderInfo.getDiscountFold() != null
&& dbProjectOrderInfo.getDiscountFold().compareTo(BigDecimal.ONE) < 0 ? endHour : 30;
projectOrderInfo.setOrderEndTime(DateUtils.addHours(DateUtils.getNowDate(), addHour));
projectOrderInfo.setOrderCode(businessKey);
projectOrderInfoMapper.updateProjectOrderInfoByCode(projectOrderInfo);
projectOrderInfoMapper.bakData(projectOrderInfo);
// 修改产品数据
if (dbProjectOrderInfo.getDiscountFold().compareTo(BigDecimal.ONE) != 0) {
productInfoService.calcByDiscountFold(dbProjectOrderInfo.getDiscountFold(), dbProjectOrderInfo.getProjectId());
}
}
@Override
public Object completedTodoDetail(String businessKey, String processKey, String todoId) {
return null;