feat(inventory): 添加撤回功能并优化相关流程

- 新增撤回功能,允许用户撤回已发货的订单
- 优化发货流程,增加备注和文件上传功能
- 调整库存管理,支持撤回后的库存更新
- 修复了一些与发货和库存相关的bug
dev_1.0.0
chenhao 2025-09-01 09:07:46 +08:00
parent 7601173ea8
commit 7cbf3dba95
30 changed files with 305 additions and 37 deletions

View File

@ -14,10 +14,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.config.RuoYiConfig; import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.config.ServerConfig; import com.ruoyi.common.config.ServerConfig;
@ -113,6 +110,21 @@ public class CommonController
return AjaxResult.error(e.getMessage()); return AjaxResult.error(e.getMessage());
} }
} }
@GetMapping("/file/download")
public void download(@RequestParam("id") Integer id, HttpServletRequest request, HttpServletResponse response) {
try {
// 本地资源路径
String localPath = RuoYiConfig.getProfile();
OmsFileLog omsFileLog = fileLogService.queryById(id);
// 下载名称
String downloadPath = omsFileLog.getFileName().replace(Constants.RESOURCE_PREFIX,localPath);
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
FileUtils.setAttachmentResponseHeader(response, StringUtils.isEmpty(omsFileLog.getOriginalFilename()) ? omsFileLog.getNewFilename() : omsFileLog.getOriginalFilename());
FileUtils.writeBytes(downloadPath, response.getOutputStream());
} catch (Exception e) {
log.error("下载文件失败", e);
}
}
/** /**
* *

View File

@ -42,7 +42,10 @@ public class SysIndexController extends BaseController
@Autowired @Autowired
private SysPasswordService passwordService; private SysPasswordService passwordService;
@GetMapping("/test")
public String test(){
return "test";
}
// 系统首页 // 系统首页
@GetMapping("/index") @GetMapping("/index")
public String index(ModelMap mmap) public String index(ModelMap mmap)

View File

@ -65,9 +65,19 @@
<th:block th:include="include :: footer"/> <th:block th:include="include :: footer"/>
<script th:inline="javascript"> <script th:inline="javascript">
var editFlag = [[${@permission.hasPermi('inventory:delivery:edit')}]]; var editFlag = [[${@permission.hasPermi('inventory:delivery:edit')}]];
var recallFlag = [[${@permission.hasPermi('inventory:delivery:recall')}]];
var removeFlag = [[${@permission.hasPermi('inventory:delivery:remove')}]]; var removeFlag = [[${@permission.hasPermi('inventory:delivery:remove')}]];
var prefix = ctx + "inventory/delivery"; var prefix = ctx + "inventory/delivery";
function refundable(id){
$.modal.confirm("撤回该发货记录后无法恢复,操作不可逆转,确认无误后再执行!", function () {
$.operate.post(prefix + "/recall", {"id": id},()=>{
// $.table.refresh()
});
})
}
$(function () { $(function () {
var options = { var options = {
url: prefix + "/list", url: prefix + "/list",
@ -137,6 +147,7 @@
align: 'center', align: 'center',
formatter: function (value, row, index) { formatter: function (value, row, index) {
var actions = []; var actions = [];
actions.push('<a class="btn btn-danger btn-sm ' + recallFlag + '" href="javascript:void(0)" onclick="refundable(\'' + row.id + '\')">撤回</a> ');
actions.push('<a class="btn btn-default btn-sm " href="javascript:void(0)" onclick="$.operate.view(\'' + row.id + '\')">发货记录</a> '); actions.push('<a class="btn btn-default btn-sm " href="javascript:void(0)" onclick="$.operate.view(\'' + row.id + '\')">发货记录</a> ');
return actions.join(''); return actions.join('');

View File

@ -95,11 +95,15 @@
.text-left{ .text-left{
text-align:left !important; text-align:left !important;
} }
#generateOuter label{ #generateOuter{
padding-right: 0px; padding: 10px 50px;
label{
padding-right: 0px;
}
} }
.editable-clear-x { .editable-clear-x {
display: none !important; display: none !important;
} }
@ -561,7 +565,7 @@ function initWarehouseTable(data) {
field: 'confirmQuantity', field: 'confirmQuantity',
title: '本次提交出库', title: '本次提交出库',
formatter: function (value, row, index) { formatter: function (value, row, index) {
return $.common.sprintf("<input class='form-control' type='number' name='detailList[%s].confirmQuantity' onchange=onEdit(this.value) value='%s' min='0' max='%s'>", index, value, row.availableCount); return $.common.sprintf("<input class='form-control' type='number' name='detailList[%s].quantity' onchange=onEdit(this.value) value='%s' min='0' max='%s'>", index, value, row.availableCount);
} }
// editable: { // editable: {
@ -597,7 +601,8 @@ function initWarehouseTable(data) {
function onEdit(value) { function onEdit(value) {
let totalConfirmQuantity = 0; let totalConfirmQuantity = 0;
$("input[name$='confirmQuantity']").each(function () { $("#warehouse-table input[name$='quantity']").each(function () {
debugger
let val = $(this).val(); let val = $(this).val();
if (val && !isNaN(val)) { if (val && !isNaN(val)) {
totalConfirmQuantity += Number(val); totalConfirmQuantity += Number(val);
@ -684,7 +689,7 @@ function initWarehouseTable(data) {
yes: function (index, layero, that) { yes: function (index, layero, that) {
let totalConfirmQuantity = 0; let totalConfirmQuantity = 0;
let errFlag = false; let errFlag = false;
$("input[name$='confirmQuantity']").each(function () { $("#warehouse-table input[name$='quantity']").each(function () {
let val = $(this).val(); let val = $(this).val();
if (val && !isNaN(val)) { if (val && !isNaN(val)) {
if (Number(val) <= 0) { if (Number(val) <= 0) {
@ -701,6 +706,7 @@ function initWarehouseTable(data) {
$.modal.msgError("本次提交出库数量应大于0") $.modal.msgError("本次提交出库数量应大于0")
return; return;
} }
debugger
let generateNumber = $('#out-generatedQuantity').text(); let generateNumber = $('#out-generatedQuantity').text();
let allTotal = totalConfirmQuantity + Number(generateNumber) let allTotal = totalConfirmQuantity + Number(generateNumber)
if (allTotal > Number($('#out-quantity').text())) { if (allTotal > Number($('#out-quantity').text())) {

View File

@ -132,6 +132,7 @@
<script th:inline="javascript"> <script th:inline="javascript">
const editFlag = [[${@permission.hasPermi('inventory:execution:edit')}]]; const editFlag = [[${@permission.hasPermi('inventory:execution:edit')}]];
const recallFlag = [[${@permission.hasPermi('inventory:execution:recall')}]];
const signFlag = [[${@permission.hasPermi('inventory:execution:sign')}]]; const signFlag = [[${@permission.hasPermi('inventory:execution:sign')}]];
const signdownFlag = [[${@permission.hasPermi('inventory:execution:signdown')}]]; const signdownFlag = [[${@permission.hasPermi('inventory:execution:signdown')}]];
var removeFlag = [[${@permission.hasPermi('project:order:remove')}]]; var removeFlag = [[${@permission.hasPermi('project:order:remove')}]];
@ -319,7 +320,7 @@
if (row.signStatus == '1'){ if (row.signStatus == '1'){
actions.push(`<a class="btn btn-default btn-xs ${signdownFlag}" href="javascript:void(0)" onclick="downloadSign('${row.id}','${row.versionCode}')"><i class="fa fa-file"></i>签收文件</a>`); actions.push(`<a class="btn btn-default btn-xs ${signdownFlag}" href="javascript:void(0)" onclick="downloadSign('${row.id}','${row.versionCode}')"><i class="fa fa-file"></i>签收文件</a>`);
} }
actions.push('<a class="btn btn-danger btn-xs ' + recallFlag + '" href="javascript:void(0)" onclick="refundable(\'' + row.id + '\')">撤单</a> ');
return actions.join(''); return actions.join('');
} }
}] }]
@ -368,6 +369,13 @@
}) })
}); });
function refundable(id){
$.modal.confirm("撤回此单后,该合同下所有出库单以及关联的发货纪录将同步删除,操作不可恢复,请确认后执行!", function () {
$.operate.post(executionPrefix + "/recall", {"id": id},()=>{
// $.table.refresh()
});
})
}
function endCallBack(){ function endCallBack(){
$.table.search() $.table.search()
} }

View File

@ -365,6 +365,8 @@
// 构造提交数据 // 构造提交数据
var submitData = { var submitData = {
vendorCode: $('[name="vendorCode"]').val(), vendorCode: $('[name="vendorCode"]').val(),
remark: $('[name="remark"]').val(),
fileId: $('[name="fileId"]').val(),
inventoryInfoList: tableData inventoryInfoList: tableData
}; };
var config = { var config = {
@ -533,7 +535,7 @@
// 显示文件名 // 显示文件名
$('#fileName').val(result.originalFilename || result.data.originalFilename); $('#fileName').val(result.originalFilename || result.data.originalFilename);
// 存储文件ID // 存储文件ID
$('#fileId').val(result.fileId || result.data.fileId); $('#fileId').val(result.id || result.data.id);
// 显示删除按钮 // 显示删除按钮
$('#deleteFileBtn').show(); $('#deleteFileBtn').show();
$.modal.msgSuccess("文件上传成功"); $.modal.msgSuccess("文件上传成功");

View File

@ -37,6 +37,22 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-xs-4">
<div class="form-group">
<label class="col-sm-5 control-label">备注:</label>
<div class="col-sm-7">
<input name="remark" class="form-control" type="text" readonly th:field="*{remark}" placeholder="备注信息"/>
</div>
</div>
</div>
<div class="col-xs-4">
<div class="form-group">
<label class="col-sm-5 control-label">文件:</label>
<div class="col-sm-7">
<input name="originalFilename" class="form-control" type="text" onclick="downloadTem()" readonly th:field="*{originalFilename}" placeholder="备注信息"/>
</div>
</div>
</div>
<div class="col-xs-12"> <div class="col-xs-12">
<h2>产品信息</h2> <h2>产品信息</h2>
</div> </div>
@ -66,7 +82,12 @@
} }
initTable() initTable()
}) })
function downloadTem(){
let id=[[${omsInventoryInner.fileId}]]
window.location.href = ctx + "common/file/download?id="+id;
}
function initTable(data) { function initTable(data) {
var options = { var options = {
url: inventoryPrefix + "/list", url: inventoryPrefix + "/list",

View File

@ -80,6 +80,8 @@
viewUrl: prefix + "/view/{id}", viewUrl: prefix + "/view/{id}",
removeUrl: prefix + "/remove", removeUrl: prefix + "/remove",
exportUrl: prefix + "/export", exportUrl: prefix + "/export",
sortName: "createTime",
sortOrder: "desc",
modalName: "入库单信息", modalName: "入库单信息",
columns: [{ columns: [{
checkbox: true checkbox: true
@ -113,6 +115,10 @@
field: 'createByName', field: 'createByName',
title: '经办人' title: '经办人'
}, },
{
field: 'remark',
title: '备注'
},
{ {
field: 'createTime', field: 'createTime',
title: '入库时间' title: '入库时间'

View File

@ -143,6 +143,10 @@
<td colspan="2"> <input name="deliveryTime" class="time-input form-control" id="deliveryTime" autocomplete="off" <td colspan="2"> <input name="deliveryTime" class="time-input form-control" id="deliveryTime" autocomplete="off"
placeholder="要求发货时间"/></td> placeholder="要求发货时间"/></td>
</tr> </tr>
<tr>
<td>备注</td>
<td> <input name="remark" class="form-control" type="text"></td>
</tr>
</table> </table>
</div> </div>
@ -430,7 +434,7 @@
formatter: function (value, row, index) { formatter: function (value, row, index) {
var actions = []; var actions = [];
let disabled = Number(row.quantity) <= Number(row.deliveryGenerateQuantity) + Number(row.deliveryConfirmQuantity) let disabled = Number(row.quantity) <= Number(row.deliveryGenerateQuantity) + Number(row.deliveryConfirmQuantity)
actions.push(`<span class="btn btn-success btn-sm " href="javascript:void(0)" ${disabled ? 'style="pointer-events: none;" disabled' : ''} onclick="checkDelivery(\'${row.quantity}\',\'${row.warehouseId}\','${row.productCode}')">发货</span>`); actions.push(`<span class="btn btn-success btn-sm " href="javascript:void(0)" ${disabled ? 'style="pointer-events: none;" disabled' : ''} onclick="checkDelivery(\'${row.quantity}\','${row.deliveryGenerateQuantity}\','${row.deliveryConfirmQuantity}\',\'${row.warehouseId}\','${row.productCode}')">发货</span>`);
return actions.join(''); return actions.join('');
} }
}] }]
@ -438,7 +442,7 @@
$.table.init(options); $.table.init(options);
} }
function checkDelivery(quantity, warehouseId, productCode) { function checkDelivery(quantity,deliveryGenerateQuantity,deliveryConfirmQuantity, warehouseId, productCode) {
initModal() initModal()
// $.table.set('bootstrap-table') // $.table.set('bootstrap-table')
let width = 1000, height = 700 let width = 1000, height = 700
@ -453,7 +457,7 @@
$.table.refreshOptions($.extend(productSnOptions, { $.table.refreshOptions($.extend(productSnOptions, {
url: productPrefix + "/list", url: productPrefix + "/list",
pagination: true, pagination: true,
pageSize: quantity pageSize: quantity-deliveryGenerateQuantity-deliveryConfirmQuantity
}), 'bootstrap-table') }), 'bootstrap-table')
$('#bootstrap-table').before('<div ><span>已选:</span><span id="table-select-count">0</span><span>(台)</span></div>'); $('#bootstrap-table').before('<div ><span>已选:</span><span id="table-select-count">0</span><span>(台)</span></div>');
$('#table-select-count').text(0); $('#table-select-count').text(0);
@ -471,17 +475,22 @@
return; return;
} }
let arrays = [] let arrays = []
debugger
if (productSnData.length <= 0) { if (productSnData.length <= 0) {
arrays = $.table.selectColumns("productSn"); arrays = $.table.selectColumns("productSn");
if (arrays.length != quantity) { // if (arrays.length != quantity) {
$.modal.msgError(`产品选中数量应与发货数量一致,应发货数量为[${quantity}]`) // $.modal.msgError(`产品选中数量应与发货数量一致,应发货数量为[${quantity}]`)
return // return
} // }
} else { } else {
if (productSnData.length != quantity) { // if (productSnData.length != quantity) {
$.modal.msgError(`产品选中数量应与发货数量一致,应发货数量为[${quantity}]`) // $.modal.msgError(`产品选中数量应与发货数量一致,应发货数量为[${quantity}]`)
// return
// }
}
if (arrays.length<=0){
$.modal.msgError(`应发货数量应该大于0`)
return return
}
} }
//保存数据 //保存数据
@ -489,13 +498,14 @@
productSnList: arrays, productSnList: arrays,
logisticsCode: $('#logisticsCode').val(), logisticsCode: $('#logisticsCode').val(),
productCode: productCode, productCode: productCode,
quantity: quantity, quantity: arrays.length,
warehouseId: warehouseId, warehouseId: warehouseId,
logisticsCompany: $('#logisticsCompany').val(), logisticsCompany: $('#logisticsCompany').val(),
deliveryType: $('#deliveryType').val(), deliveryType: $('#deliveryType').val(),
deliveryTime: $('#deliveryTime').val(), deliveryTime: $('#deliveryTime').val(),
deliveryTimeType: $('#deliveryTimeType').val(), deliveryTimeType: $('#deliveryTimeType').val(),
outerCode: $('[name="outerCode"]').val(), outerCode: $('[name="outerCode"]').val(),
remark: $('[name="remark"]').val(),
productSnDataList: productSnData, productSnDataList: productSnData,
} }
var config = { var config = {

View File

@ -108,12 +108,12 @@
visible: false visible: false
}, },
{ {
width:100, width:150,
field: 'customerCode', field: 'customerCode',
title: '客户编码' title: '客户编码'
}, },
{ {
width:200, width:250,
field: 'customerName', field: 'customerName',
title: '最终客户名称' title: '最终客户名称'
}, },
@ -148,7 +148,7 @@
title: '联系电话' title: '联系电话'
}, },
{ {
width:100, width:200,
field: 'contactEmail', field: 'contactEmail',
title: '联系邮件' title: '联系邮件'
}, },

View File

@ -157,4 +157,12 @@ public class InventoryDeliveryController extends BaseController
{ {
return toAjax(inventoryDeliveryService.deleteInventoryOuterById(id)); return toAjax(inventoryDeliveryService.deleteInventoryOuterById(id));
} }
@Log(title = "发货记录", businessType = BusinessType.DELETE)
@PostMapping( "/recall")
@ResponseBody
public AjaxResult recall(Long id)
{
inventoryDeliveryService.recall(id);
return AjaxResult.success();
}
} }

View File

@ -106,6 +106,13 @@ public class InventoryExecutionController extends BaseController {
public AjaxResult checkOutPreview(@RequestParam("productCode") String productCode,@RequestParam("quantity") Integer quantity ){ public AjaxResult checkOutPreview(@RequestParam("productCode") String productCode,@RequestParam("quantity") Integer quantity ){
return AjaxResult.success(service.checkOutPreview(productCode,quantity)); return AjaxResult.success(service.checkOutPreview(productCode,quantity));
} }
@PostMapping("/recall")
@ResponseBody
@Log(title = "执行单撤单", businessType = BusinessType.DELETE)
public AjaxResult recall(Long id ){
service.recall(id);
return AjaxResult.success();
}

View File

@ -80,6 +80,7 @@ public class InventoryDelivery extends BaseEntity
private String createByName; private String createByName;
private String remark;

View File

@ -43,7 +43,9 @@ public class ProjectOrderInfo extends BaseEntity {
private String versionCode; private String versionCode;
private String industryType; private String industryType;
private String industryTypeDesc;
private String bgProperty; private String bgProperty;
private String bgPropertyDesc;
private String province; private String province;
@ -121,6 +123,7 @@ public class ProjectOrderInfo extends BaseEntity {
*/ */
// @Excel(name = "币种") // @Excel(name = "币种")
private String currencyType; private String currencyType;
private String currencyTypeDesc;
/** /**
* *
@ -169,6 +172,8 @@ public class ProjectOrderInfo extends BaseEntity {
*/ */
// @Excel(name = "公司直发") // @Excel(name = "公司直发")
private String companyDelivery; private String companyDelivery;
private String companyDeliveryDesc;
@ -207,6 +212,7 @@ public class ProjectOrderInfo extends BaseEntity {
*/ */
// @Excel(name = "下单通路") // @Excel(name = "下单通路")
private String orderChannel; private String orderChannel;
private String orderChannelDesc;
private String partnerEmail; private String partnerEmail;
@ -215,6 +221,7 @@ public class ProjectOrderInfo extends BaseEntity {
private String systemUserId; private String systemUserId;
private String level; private String level;
private String levelDesc;
/** /**
* 0: 1: * 0: 1:
*/ */
@ -248,6 +255,7 @@ public class ProjectOrderInfo extends BaseEntity {
private List<ProjectProductInfo> hardwareProjectProductInfoList; private List<ProjectProductInfo> hardwareProjectProductInfoList;
private List<ProjectProductInfo> maintenanceProjectProductInfoList; private List<ProjectProductInfo> maintenanceProjectProductInfoList;
private String keyword;
@Getter @Getter
public enum OrderStatus { public enum OrderStatus {

View File

@ -71,4 +71,7 @@ public interface InventoryInfoMapper
void deleteInventoryInfoByInnerIds(String[] idArray); void deleteInventoryInfoByInnerIds(String[] idArray);
List<InventoryInfo> listInventoryInfoByInnerIds(String[] idArray); List<InventoryInfo> listInventoryInfoByInnerIds(String[] idArray);
void recallByOrderCode(List<String> orderCode);
} }

View File

@ -75,4 +75,6 @@ public interface ProductInfoMapper
void updateCumulativeCount(@Param("quantity") Long quantity, @Param("productCode") String productCode); void updateCumulativeCount(@Param("quantity") Long quantity, @Param("productCode") String productCode);
List<String> authProductCode(VendorInfo productInfo); List<String> authProductCode(VendorInfo productInfo);
void updateCount(List<ProductInfo> values);
} }

View File

@ -24,4 +24,6 @@ public interface IExecutionTrackService {
ExecutionOrderVo selectInfo(Long id); ExecutionOrderVo selectInfo(Long id);
List<ProductWarehouseInfo> checkOutPreview(String productCode, Integer quantity); List<ProductWarehouseInfo> checkOutPreview(String productCode, Integer quantity);
void recall(Long id);
} }

View File

@ -66,4 +66,7 @@ public interface IInventoryDeliveryService
int deleteInventoryOuterById(Long id); int deleteInventoryOuterById(Long id);
List<DeliveryInfoVo> getNumberInfo(ApiDataQueryDto dto); List<DeliveryInfoVo> getNumberInfo(ApiDataQueryDto dto);
void recall(Long id);
} }

View File

@ -82,4 +82,6 @@ public interface IInventoryInfoService
List<String> checkUnq(List<String> productSnList); List<String> checkUnq(List<String> productSnList);
void deleteInventoryInfoByInnerIds(String[] idArray); void deleteInventoryInfoByInnerIds(String[] idArray);
void recallByOrderCode(List<String> orderCode);
} }

View File

@ -1,5 +1,6 @@
package com.ruoyi.sip.service; package com.ruoyi.sip.service;
import java.util.Collection;
import java.util.List; import java.util.List;
import com.ruoyi.sip.domain.MaintenanceRecordsDto; import com.ruoyi.sip.domain.MaintenanceRecordsDto;
@ -67,4 +68,7 @@ public interface IProductInfoService
void updateAvailableCount(Long quantity, String productCode); void updateAvailableCount(Long quantity, String productCode);
void updateCumulativeCount(Long outerSum,String productCode); void updateCumulativeCount(Long outerSum,String productCode);
void updateCount(List<ProductInfo> values);
} }

View File

@ -6,11 +6,13 @@ import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.sip.domain.*; import com.ruoyi.sip.domain.*;
import com.ruoyi.sip.dto.inventory.ProductDetail; import com.ruoyi.sip.dto.inventory.ProductDetail;
import com.ruoyi.sip.dto.inventory.ProductWarehouseInfo; import com.ruoyi.sip.dto.inventory.ProductWarehouseInfo;
import com.ruoyi.sip.mapper.InventoryDeliveryMapper;
import com.ruoyi.sip.mapper.ProjectOrderInfoMapper; import com.ruoyi.sip.mapper.ProjectOrderInfoMapper;
import com.ruoyi.sip.service.*; import com.ruoyi.sip.service.*;
import com.ruoyi.sip.vo.ExecutionOrderVo; import com.ruoyi.sip.vo.ExecutionOrderVo;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.*; import java.util.*;
@ -46,6 +48,8 @@ public class ExecutionTrackServiceImpl implements IExecutionTrackService {
private IVendorInfoService vendorInfoService; private IVendorInfoService vendorInfoService;
@Autowired @Autowired
private IInventoryAuthService inventoryAuthService; private IInventoryAuthService inventoryAuthService;
@Autowired
private InventoryDeliveryMapper deliveryMapper;
@Override @Override
public ExecutionOrderVo selectInfo(Long id) { public ExecutionOrderVo selectInfo(Long id) {
@ -224,5 +228,71 @@ public class ExecutionTrackServiceImpl implements IExecutionTrackService {
return productWarehouseInfoList; return productWarehouseInfoList;
}
@Override
@Transactional(rollbackFor = Exception.class)
public void recall(Long id) {
//查询订单
ProjectOrderInfo projectOrderInfo = projectOrderInfoMapper.selectProjectOrderInfoById(id);
//修改订单状态
ProjectOrderInfo updateOrder = new ProjectOrderInfo();
updateOrder.setOuterStatus(ProjectOrderInfo.OuterStatusEnum.NOT_OUTER.getCode());
updateOrder.setDeliveryStatus(ProjectOrderInfo.DeliveryStatusEnum.NOT_DELIVERY.getCode());
updateOrder.setSignStatus(ProjectOrderInfo.SignStatusEnum.NOT_SIGN.getCode());
updateOrder.setId(id);
projectOrderInfoMapper.updateProjectOrderInfo(updateOrder);
//修改库存
InventoryOuter inventoryOuter = new InventoryOuter();
inventoryOuter.setOrderCode(projectOrderInfo.getOrderCode());
List<InventoryOuter> inventoryOuters = outerService.selectInventoryOuterList(inventoryOuter);
if (CollUtil.isNotEmpty(inventoryOuters)) {
outerService.deleteInventoryOuterByIds(inventoryOuters.stream().map(item -> item.getId().toString()).collect(Collectors.joining(",")));
}
Map<String, Long> outerSumMap = inventoryOuters.stream().collect(Collectors.toMap(InventoryOuter::getProductCode, InventoryOuter::getQuantity, Long::sum));
//累计发货
List<InventoryDelivery> inventoryDeliveries = deliveryMapper.selectQuantityByOrderCodeStatus(projectOrderInfo.getOrderCode(), InventoryDelivery.DeliveryStatusEnum.CONFIRM_DELIVERY.getCode());
if (CollUtil.isNotEmpty(inventoryDeliveries)) {
deliveryMapper.deleteInventoryDeliveryByIds(inventoryOuters.stream().map(item -> item.getId().toString()).toArray(String[]::new));
}
Map<String, Long> deliveryMap = inventoryDeliveries.stream().collect(Collectors.toMap(InventoryDelivery::getProductCode, InventoryDelivery::getQuantity, Long::sum));
Map<String, ProductInfo> updateMap = new HashMap<>();
for (Map.Entry<String, Long> entry : outerSumMap.entrySet()) {
updateMap.compute(entry.getKey(), (key, value) -> {
if (value == null) {
ProductInfo productInfo = new ProductInfo();
productInfo.setProductCode(entry.getKey());
productInfo.setAvailableCount(entry.getValue());
productInfo.setCumulativeCount(0L);
return productInfo;
} else {
value.setAvailableCount(value.getAvailableCount() + entry.getValue());
return value;
}
});
}
for (Map.Entry<String, Long> entry : deliveryMap.entrySet()) {
updateMap.compute(entry.getKey(), (key, value) -> {
if (value == null) {
ProductInfo productInfo = new ProductInfo();
productInfo.setProductCode(entry.getKey());
productInfo.setAvailableCount(0L);
productInfo.setCumulativeCount(entry.getValue());
return productInfo;
} else {
value.setCumulativeCount(value.getCumulativeCount() + entry.getValue());
return value;
}
});
}
if (CollUtil.isNotEmpty(updateMap.values())) {
productInfoService.updateCount(new ArrayList<>(updateMap.values()));
}
//还原库存
inventoryInfoService.recallByOrderCode(Collections.singletonList(projectOrderInfo.getOrderCode()));
} }
} }

View File

@ -229,6 +229,44 @@ public class InventoryDeliveryServiceImpl implements IInventoryDeliveryService {
return resultList; return resultList;
} }
@Override
public void recall(Long id) {
InventoryDelivery inventoryDelivery = inventoryDeliveryMapper.selectInventoryDeliveryById(id);
deleteInventoryOuterById(id);
List<ProjectProductInfo> projectProductInfos = projectProductInfoService.listDeliveryProductByOrderCode(Collections.singletonList(inventoryDelivery.getOrderCode()));
//软硬件之和
long sum = projectProductInfos.stream().mapToLong(ProjectProductInfo::getQuantity).sum();
//已确认发货数量
List<InventoryDelivery> deliveryList = inventoryDeliveryMapper.selectQuantityByOrderCodeStatus(inventoryDelivery.getOrderCode(), InventoryDelivery.DeliveryStatusEnum.CONFIRM_DELIVERY.getCode());
long outerSum = deliveryList.stream().filter(item -> item.getOuterCode().equals(inventoryDelivery.getOuterCode())).mapToLong(InventoryDelivery::getQuantity).sum();
//修改出库单的发货状态
InventoryOuter updateDto = new InventoryOuter();
updateDto.setOuterCode(inventoryDelivery.getOuterCode());
InventoryOuter inventoryOuter = inventoryOuterMapper.selectInventoryOuterByCode(inventoryDelivery.getOuterCode());
if (outerSum == 0) {
updateDto.setDeliveryStatus(InventoryOuter.DeliveryStatusEnum.WAIT_DELIVERY.getCode());
} else {
updateDto.setDeliveryStatus(inventoryOuter.getQuantity().compareTo(outerSum) == 0 ? InventoryOuter.DeliveryStatusEnum.ALL_DELIVERY.getCode() : InventoryOuter.DeliveryStatusEnum.PART_DELIVERY.getCode());
}
updateDto.setId(inventoryOuter.getId());
//状态变化才更新
if (!updateDto.getDeliveryStatus().equals(inventoryOuter.getDeliveryStatus())) {
inventoryOuterMapper.updateInventoryOuter(updateDto);
}
long allSum = deliveryList.stream().mapToLong(InventoryDelivery::getQuantity).sum();
//修改订单的发货状态
ProjectOrderInfo updateOrder = new ProjectOrderInfo();
updateOrder.setOrderCode(inventoryDelivery.getOrderCode());
updateOrder.setUpdateTime(new Date());
updateOrder.setUpdateBy(ShiroUtils.getUserId().toString());
updateOrder.setDeliveryStatus(sum == allSum ? ProjectOrderInfo.DeliveryStatusEnum.ALL_DELIVERY.getCode() : ProjectOrderInfo.DeliveryStatusEnum.PART_DELIVERY.getCode());
projectOrderInfoService.updateProjectOrderInfoByCode(updateOrder);
//修改累计发货数量
productInfoService.updateCumulativeCount(-inventoryDelivery.getQuantity(), inventoryDelivery.getProductCode());
}
/** /**
* DeliveryInfoVo * DeliveryInfoVo
*/ */

View File

@ -197,5 +197,10 @@ public class InventoryInfoServiceImpl implements IInventoryInfoService {
inventoryInfoMapper.deleteInventoryInfoByInnerIds(idArray); inventoryInfoMapper.deleteInventoryInfoByInnerIds(idArray);
} }
@Override
public void recallByOrderCode(List<String> orderCode) {
inventoryInfoMapper.recallByOrderCode(orderCode);
}
} }

View File

@ -263,7 +263,7 @@ public class InventoryOuterServiceImpl implements IInventoryOuterService
List<InventoryDelivery> inventoryDeliveries = deliveryService.selectInventoryDeliveryList(queryDeliveryDto); List<InventoryDelivery> inventoryDeliveries = deliveryService.selectInventoryDeliveryList(queryDeliveryDto);
outerDeliveryVo.setDeliveryList(inventoryDeliveries); outerDeliveryVo.setDeliveryList(inventoryDeliveries);
//查询产品清单 //查询产品清单
Map<Long, InventoryDelivery> inventoryDeliveryMap = inventoryDeliveries.stream().collect(Collectors.toMap(InventoryDelivery::getWarehouseId, Function.identity(), (v1, v2) -> v1)); Map<Long, List<InventoryDelivery>> deliveryListMap = inventoryDeliveries.stream().collect(Collectors.groupingBy(InventoryDelivery::getWarehouseId));
InventoryOuterDetail inventoryOuterDetail = new InventoryOuterDetail(); InventoryOuterDetail inventoryOuterDetail = new InventoryOuterDetail();
inventoryOuterDetail.setOuterCode(inventoryOuter.getOuterCode()); inventoryOuterDetail.setOuterCode(inventoryOuter.getOuterCode());
List<InventoryOuterDetail> detailList = detailService.selectInventoryOuterDetailList(inventoryOuterDetail); List<InventoryOuterDetail> detailList = detailService.selectInventoryOuterDetailList(inventoryOuterDetail);
@ -278,13 +278,14 @@ public class InventoryOuterServiceImpl implements IInventoryOuterService
vo.setQuantity(item.getQuantity()); vo.setQuantity(item.getQuantity());
vo.setDeliveryGenerateQuantity(0L); vo.setDeliveryGenerateQuantity(0L);
vo.setDeliveryConfirmQuantity(0L); vo.setDeliveryConfirmQuantity(0L);
InventoryDelivery inventoryDelivery = inventoryDeliveryMap.get(vo.getWarehouseId()); List<InventoryDelivery> tempDeliveryList = deliveryListMap.get(vo.getWarehouseId());
if (inventoryDelivery != null) { if (CollUtil.isNotEmpty(tempDeliveryList)){
if (inventoryDelivery.getDeliveryStatus().equals(InventoryDelivery.DeliveryStatusEnum.WAIT_DELIVERY.getCode())) { for (InventoryDelivery inventoryDelivery : tempDeliveryList) {
vo.setDeliveryGenerateQuantity(vo.getDeliveryGenerateQuantity() + item.getQuantity()); if (inventoryDelivery.getDeliveryStatus().equals(InventoryDelivery.DeliveryStatusEnum.WAIT_DELIVERY.getCode())) {
} else { vo.setDeliveryGenerateQuantity(vo.getDeliveryGenerateQuantity() + inventoryDelivery.getQuantity());
vo.setDeliveryGenerateQuantity(vo.getDeliveryGenerateQuantity() + item.getQuantity()); } else {
vo.setDeliveryConfirmQuantity(vo.getDeliveryConfirmQuantity() + item.getQuantity()); vo.setDeliveryConfirmQuantity(vo.getDeliveryConfirmQuantity() + inventoryDelivery.getQuantity());
}
} }
} }
return vo; return vo;

View File

@ -143,4 +143,9 @@ public class ProductInfoServiceImpl implements IProductInfoService
public void updateCumulativeCount(Long outerSum, String productCode) { public void updateCumulativeCount(Long outerSum, String productCode) {
productInfoMapper.updateCumulativeCount(outerSum, productCode); productInfoMapper.updateCumulativeCount(outerSum, productCode);
} }
@Override
public void updateCount(List<ProductInfo> values) {
productInfoMapper.updateCount(values);
}
} }

View File

@ -58,8 +58,7 @@ import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource; import javax.annotation.Resource;
import static com.ruoyi.common.utils.ShiroUtils.getSysUser; import static com.ruoyi.common.utils.ShiroUtils.getSysUser;
import static com.ruoyi.sip.service.impl.ProjectInfoServiceImpl.INDUSTRY_TYPE_DICT_TYPE; import static com.ruoyi.sip.service.impl.ProjectInfoServiceImpl.*;
import static com.ruoyi.sip.service.impl.ProjectInfoServiceImpl.INDUSTRY_TYPE_YYS_DICT_TYPE;
/** /**
* Service * Service
@ -142,6 +141,17 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To
projectOrderInfo.setContractFileList(contractFileList); projectOrderInfo.setContractFileList(contractFileList);
projectOrderInfo.setConfigFileList(fileLogMap.get(ProjectOrderFileLog.FileTypeEnum.CONFIG.getCode())); projectOrderInfo.setConfigFileList(fileLogMap.get(ProjectOrderFileLog.FileTypeEnum.CONFIG.getCode()));
projectOrderInfo.setBgPropertyDesc(DictUtils.getDictLabel(BG_TYPE_DICT_TYPE, projectOrderInfo.getBgProperty()));
String dictType= "YYS".equals(projectOrderInfo.getBgProperty())?"bg_yys":"bg_hysy";
projectOrderInfo.setIndustryTypeDesc(DictUtils.getDictLabel(dictType, projectOrderInfo.getIndustryType()));
projectOrderInfo.setOrderChannelDesc(StringUtils.isEmpty(projectOrderInfo.getOrderChannel()) ? "" :
"1".equals(projectOrderInfo.getOrderChannel()) ? "总代" : "直签");
projectOrderInfo.setLevelDesc(DictUtils.getDictLabel("identify_level", projectOrderInfo.getLevel()));
projectOrderInfo.setCompanyDeliveryDesc(DictUtils.getDictLabel("company_delivery", projectOrderInfo.getCompanyDelivery()));
return projectOrderInfo; return projectOrderInfo;
} }

View File

@ -21,7 +21,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</resultMap> </resultMap>
<sql id="selectInventoryDeliveryVo"> <sql id="selectInventoryDeliveryVo">
select t1.id, t1.outer_code, t1.warehouse_id,t1.quantity, t1.logistics_company,t1.delivery_status, t1.logistics_code select t1.id, t1.outer_code, t1.warehouse_id,t1.quantity, t1.logistics_company,t1.delivery_status, t1.logistics_code,t1.remark
, t1.delivery_time_type, t1.delivery_time, t1.delivery_type, t1.create_by, t1.create_time, t1.update_by, t1.update_time , t1.delivery_time_type, t1.delivery_time, t1.delivery_type, t1.create_by, t1.create_time, t1.update_by, t1.update_time
,t2.warehouse_name, ,t2.warehouse_name,
t5.project_code, t5.project_name, t5.project_code, t5.project_name,
@ -120,6 +120,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="createTime != null">create_time,</if> <if test="createTime != null">create_time,</if>
<if test="updateBy != null">update_by,</if> <if test="updateBy != null">update_by,</if>
<if test="updateTime != null">update_time,</if> <if test="updateTime != null">update_time,</if>
<if test="remark != null and remark!=''">remark,</if>
</trim> </trim>
<trim prefix="values (" suffix=")" suffixOverrides=","> <trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="outerCode != null">#{outerCode},</if> <if test="outerCode != null">#{outerCode},</if>
@ -135,6 +136,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="createTime != null">#{createTime},</if> <if test="createTime != null">#{createTime},</if>
<if test="updateBy != null">#{updateBy},</if> <if test="updateBy != null">#{updateBy},</if>
<if test="updateTime != null">#{updateTime},</if> <if test="updateTime != null">#{updateTime},</if>
<if test="remark != null and remark!=''">#{remark},</if>
</trim> </trim>
</insert> </insert>
@ -154,6 +156,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="createTime != null">create_time = #{createTime},</if> <if test="createTime != null">create_time = #{createTime},</if>
<if test="updateBy != null">update_by = #{updateBy},</if> <if test="updateBy != null">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if> <if test="updateTime != null">update_time = #{updateTime},</if>
<if test="remark != null and remark!=''">remark=#{remark},</if>
</trim> </trim>
where id = #{id} where id = #{id}
</update> </update>

View File

@ -153,6 +153,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#{id} #{id}
</foreach> </foreach>
</update> </update>
<update id="recallByOrderCode">
update oms_inventory_info
set inventory_status = 0,outer_code=null
where outer_code in (select outer_code from oms_inventory_outer where order_code in <foreach item="orderCode" collection="list" separator="," open="(" close=")">
#{orderCode}
</foreach>)
</update>
<delete id="deleteInventoryInfoById" parameterType="Long"> <delete id="deleteInventoryInfoById" parameterType="Long">
delete from oms_inventory_info where id = #{id} delete from oms_inventory_info where id = #{id}

View File

@ -112,6 +112,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="deliveryStatus != null and deliveryStatus != ''">and t1.delivery_status = #{deliveryStatus}</if> <if test="deliveryStatus != null and deliveryStatus != ''">and t1.delivery_status = #{deliveryStatus}</if>
<if test="outerStatus != null and outerStatus != ''">and t1.outer_status = #{outerStatus}</if> <if test="outerStatus != null and outerStatus != ''">and t1.outer_status = #{outerStatus}</if>
<if test="signStatus != null and signStatus != ''">and t1.sign_status = #{signStatus}</if> <if test="signStatus != null and signStatus != ''">and t1.sign_status = #{signStatus}</if>
<if test="keyword != null and keyword != ''">and (t1.order_code like concat('%',#{keyword},'%') or t2.project_name like concat('%',#{keyword},'%') or t2.customer_name like concat('%',#{keyword},'%'))</if>
<if test="deliveryTimeStart != null or deliveryTimeEnd != null"> <if test="deliveryTimeStart != null or deliveryTimeEnd != null">
<choose> <choose>
<when test="deliveryTimeStart != null and deliveryTimeEnd != null"> <when test="deliveryTimeStart != null and deliveryTimeEnd != null">

View File

@ -174,6 +174,14 @@
set cumulative_count=ifnull(cumulative_count,0) + #{quantity} set cumulative_count=ifnull(cumulative_count,0) + #{quantity}
where product_code = #{productCode} where product_code = #{productCode}
</update> </update>
<update id="updateCount">
<foreach item="item" index="index" collection="list" separator=";">
update product_info
set available_count=ifnull(available_count,0) + #{item.availableCount},
cumulative_count=ifnull(cumulative_count,0) - #{item.cumulativeCount}
where product_code = #{item.productCode}
</foreach>
</update>
<delete id="deleteProductInfoById" parameterType="Long"> <delete id="deleteProductInfoById" parameterType="Long">
update product_info set status=1, deleted_at=now() where id = #{id} update product_info set status=1, deleted_at=now() where id = #{id}