feat(transfer): 添加调拨单审批功能和调拨类型字段

- 在WmsTransferOrder实体中添加调拨类型、审批人、审批时间和审批状态字段
- 在WmsMaterialCoil实体中添加调拨类型字段用于关联调拨信息
- 实现调拨单审批接口,支持通过或驳回操作
- 更新调拨单明细处理逻辑,确保调拨类型正确传递到钢卷信息
- 添加调拨单取消功能,可恢复调拨前的状态
- 在导出VO中增加调拨类型字段支持Excel导出
- 更新查询条件支持按调拨类型、审批状态等字段筛选
- 完善调拨流程中的数据验证和错误处理机制
This commit is contained in:
2026-04-10 09:24:42 +08:00
parent 255a6dc616
commit c8987f6fdd
15 changed files with 224 additions and 33 deletions

View File

@@ -96,4 +96,19 @@ public class WmsTransferOrderController extends BaseController {
@PathVariable Long[] orderIds) {
return toAjax(iWmsTransferOrderService.deleteWithValidByIds(Arrays.asList(orderIds), true));
}
/**
* 审批调拨单
*
* @param orderId 调拨单ID
* @param approveStatus 审批状态 1-通过 2-驳回
*/
@Log(title = "调拨单审批", businessType = BusinessType.UPDATE)
@PutMapping("/approve/{orderId}/{approveStatus}")
public R<Void> approve(@NotNull(message = "主键不能为空")
@PathVariable Long orderId,
@NotNull(message = "审批状态不能为空")
@PathVariable Integer approveStatus) {
return toAjax(iWmsTransferOrderService.approve(orderId, approveStatus));
}
}

View File

@@ -205,5 +205,10 @@ public class WmsMaterialCoil extends BaseEntity {
* 钢卷表中的表面处理
*/
private String coilSurfaceTreatment;
/**
* 调拨类型
*/
private String transferType;
}

View File

@@ -46,6 +46,22 @@ public class WmsTransferOrder extends BaseEntity {
* 备注
*/
private String remark;
/**
* 调拨类型
*/
private String transferType;
/**
* 审批人
*/
private String approveBy;
/**
* 审批时间
*/
private Date approveTime;
/**
* 审批状态 0-待审批 1-已通过 2-已驳回
*/
private Integer approveStatus;
/**
* 删除标记(0正常 1删除)
*/

View File

@@ -346,5 +346,10 @@ public class WmsMaterialCoilBo extends BaseEntity {
*/
@TableField(exist = false)
private Boolean orderByAbnormal;
/**
* 调拨类型
*/
private String transferType;
}

View File

@@ -52,5 +52,27 @@ public class WmsTransferOrderBo extends BaseEntity {
*/
private String remark;
/**
* 调拨类型
*/
private String transferType;
/**
* 审批人
*/
private String approveBy;
/**
* 审批时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date approveTime;
/**
* 审批状态 0-待审批 1-已通过 2-已驳回
*/
private Integer approveStatus;
}

View File

@@ -208,4 +208,10 @@ public class WmsMaterialCoilAllExportVo {
*/
@ExcelProperty(value = "实测厚度")
private String actualThickness;
/**
* 调拨类型
*/
@ExcelProperty(value = "调拨类型")
private String transferType;
}

View File

@@ -205,4 +205,10 @@ public class WmsMaterialCoilExportVo {
* 销售人员
*/
private String saleName;
/**
* 调拨类型
*/
@ExcelProperty(value = "调拨类型")
private String transferType;
}

View File

@@ -324,5 +324,10 @@ public class WmsMaterialCoilVo extends BaseEntity {
private Date actionCompleteTime;
private String saleNickName;
/**
* 调拨类型
*/
private String transferType;
}

View File

@@ -57,5 +57,29 @@ public class WmsTransferOrderVo {
@ExcelProperty(value = "备注")
private String remark;
/**
* 调拨类型
*/
@ExcelProperty(value = "调拨类型")
private String transferType;
/**
* 审批人
*/
@ExcelProperty(value = "审批人")
private String approveBy;
/**
* 审批时间
*/
@ExcelProperty(value = "审批时间")
private Date approveTime;
/**
* 审批状态 0-待审批 1-已通过 2-已驳回
*/
@ExcelProperty(value = "审批状态 0-待审批 1-已通过 2-已驳回")
private Integer approveStatus;
}

View File

@@ -46,4 +46,12 @@ public interface IWmsTransferOrderService {
* 校验并批量删除调拨单主信息
*/
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
/**
* 审批调拨单
* @param orderId 调拨单ID
* @param approveStatus 审批状态 1-通过 2-驳回
* @return 结果
*/
Boolean approve(Long orderId, Integer approveStatus);
}

View File

@@ -538,6 +538,8 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
qw.eq(bo.getReservedWidth() != null, "mc.reserved_width", bo.getReservedWidth());
// 钢卷表面处理
qw.eq(bo.getCoilSurfaceTreatment() != null, "mc.coil_surface_treatment", bo.getCoilSurfaceTreatment());
// 调拨类型
qw.eq(StringUtils.isNotBlank(bo.getTransferType()), "mc.transfer_type", bo.getTransferType());
// 如果actualWarehouseId不为空则根据实际库区ID进行查询 如果为-1,则查询无库区的数据
if (bo.getActualWarehouseId() != null) {
if (bo.getActualWarehouseId() == -1) {
@@ -1311,6 +1313,7 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
WmsMaterialCoil newCoil = BeanUtil.toBean(bo, WmsMaterialCoil.class);
newCoil.setCoilId(null); // 清空ID让数据库自动生成新ID
newCoil.setDataType(1); // 设置为当前数据
newCoil.setTransferType(null);
newCoil.setQrcodeRecordId(oldCoil.getQrcodeRecordId()); // 继续使用原二维码
// 继承原记录的关键字段
@@ -1545,6 +1548,7 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
WmsMaterialCoil newCoil = BeanUtil.toBean(newCoilBo, WmsMaterialCoil.class);
newCoil.setCoilId(null);
newCoil.setDataType(1);
newCoil.setTransferType(null);
// 继承原钢卷的基本信息(强制继承,不能修改的字段)
newCoil.setEnterCoilNo(oldCoil.getEnterCoilNo());
newCoil.setSupplierCoilNo(oldCoil.getSupplierCoilNo()); // 保留厂家原料卷号
@@ -1668,6 +1672,7 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
WmsMaterialCoil newCoil = BeanUtil.toBean(bo, WmsMaterialCoil.class);
newCoil.setCoilId(null);
newCoil.setDataType(1);
newCoil.setTransferType(null);
// 从第一个参与合卷的原始钢卷获取基本信息
if (!bo.getNewCoils().isEmpty()) {
@@ -4217,6 +4222,7 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
WmsMaterialCoil childCoil = BeanUtil.toBean(childCoilBo, WmsMaterialCoil.class);
childCoil.setCoilId(null);
childCoil.setDataType(1); // 当前数据
childCoil.setTransferType(null);
childCoil.setEnterCoilNo(parentCoil.getEnterCoilNo());
childCoil.setSupplierCoilNo(parentCoil.getSupplierCoilNo());
childCoil.setExclusiveStatus(0); // 子卷不被锁定
@@ -4924,17 +4930,17 @@ public class WmsMaterialCoilServiceImpl implements IWmsMaterialCoilService {
public List<WmsMaterialCoilVo> queryMismatchedItemCoils() {
// 用SQL子查询直接找出itemId和itemType不匹配的钢卷
List<WmsMaterialCoil> mismatchedCoils = baseMapper.selectMismatchedItemCoils();
if (mismatchedCoils == null || mismatchedCoils.isEmpty()) {
return new ArrayList<>();
}
// 批量填充关联信息
List<WmsMaterialCoilVo> voList = mismatchedCoils.stream()
.map(coil -> BeanUtil.toBean(coil, WmsMaterialCoilVo.class))
.collect(Collectors.toList());
fillRelatedObjectsBatch(voList);
return voList;
}

View File

@@ -6,6 +6,7 @@ import com.klp.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.klp.common.utils.StringUtils;
import com.klp.domain.*;
import com.klp.domain.bo.WmsMaterialCoilBo;
import com.klp.domain.vo.WmsMaterialCoilVo;
@@ -40,6 +41,7 @@ public class WmsTransferOrderItemServiceImpl implements IWmsTransferOrderItemSer
private final IWmsMaterialCoilService coilService;
private final IWmsWarehouseService warehouseService;
private final WmsWarehouseMapper warehouseMapper;
private final WmsTransferOrderMapper wmsTransferOrderMapper;
/**
* 查询调拨单明细
@@ -509,50 +511,70 @@ public class WmsTransferOrderItemServiceImpl implements IWmsTransferOrderItemSer
Long orderItemId = bo.getOrderItemId();
Long coilId = bo.getCoilId();
Long itemId = bo.getItemIdAfter();
String itemType = bo.getMaterialTypeAfter() != null ? (bo.getMaterialTypeAfter() == 1 ? "raw_material" : "product") : null;
Long warehouseId = bo.getWarehouseIdAfter();
if (coilId == null) {
throw new IllegalArgumentException("coilId不能为空");
}
// 查询钢卷
WmsMaterialCoil coil = coilMapper.selectById(coilId);
if (coil == null) {
throw new IllegalArgumentException("钢卷不存在");
}
// 如果传了才修改钢卷
if (itemId != null) {
coil.setItemId(itemId);
}
if (itemType != null) {
coil.setItemType(itemType);
coil.setMaterialType(bo.getMaterialTypeAfter() == 1 ? "原料" : "成品");
}
if (warehouseId != null) {
coil.setWarehouseId(warehouseId);
}
coilMapper.updateById(coil);
// 查询调拨明细
LambdaQueryWrapper<WmsTransferOrderItem> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(true, WmsTransferOrderItem::getCoilId, coilId);
wrapper.eq(orderItemId != null, WmsTransferOrderItem::getOrderItemId, orderItemId);
wrapper.eq(transferId != null, WmsTransferOrderItem::getTransferId, transferId);
WmsTransferOrderItem item = baseMapper.selectOne(wrapper);
if (item != null) {
// 如果没传itemIdAfter则用itemIdBefore的值
item.setItemIdAfter(itemId != null ? itemId : item.getItemIdBefore());
// 如果没传materialTypeAfter则用materialTypeBefore的值
if (bo.getMaterialTypeAfter() != null) {
item.setMaterialTypeAfter(bo.getMaterialTypeAfter());
} else {
item.setMaterialTypeAfter(item.getMaterialTypeBefore());
}
// 如果没传warehouseIdAfter则用warehouseIdBefore的值
item.setWarehouseIdAfter(warehouseId != null ? warehouseId : item.getWarehouseIdBefore());
baseMapper.updateById(item);
if (item == null) {
throw new IllegalArgumentException("调拨明细不存在");
}
// 确定最终值:如果没传则使用改之前的值
Long finalItemId = itemId != null ? itemId : item.getItemIdBefore();
Long finalMaterialType = bo.getMaterialTypeAfter() != null ? bo.getMaterialTypeAfter() : item.getMaterialTypeBefore();
Long finalWarehouseId = warehouseId != null ? warehouseId : item.getWarehouseIdBefore();
String finalItemType = finalMaterialType == 1 ? "raw_material" : "product";
// 先校验itemId是否存在根据itemType
if (finalItemId != null && StringUtils.isNotBlank(finalItemType)) {
if ("raw_material".equals(finalItemType)) {
WmsRawMaterial rawMaterial = rawMaterialMapper.selectById(finalItemId);
if (rawMaterial == null) {
throw new RuntimeException("原材料不存在ID: " + finalItemId);
}
} else {
WmsProduct product = productMapper.selectById(finalItemId);
if (product == null) {
throw new RuntimeException("产品不存在ID: " + finalItemId);
}
}
}
// 更新调拨明细
item.setItemIdAfter(finalItemId);
item.setMaterialTypeAfter(finalMaterialType);
item.setWarehouseIdAfter(finalWarehouseId);
baseMapper.updateById(item);
// 更新钢卷信息
coil.setItemId(finalItemId);
coil.setItemType(finalItemType);
coil.setMaterialType(finalMaterialType == 1 ? "原料" : "成品");
coil.setWarehouseId(finalWarehouseId);
// 设置调拨类型
if (item.getTransferId() != null) {
WmsTransferOrder wmsTransferOrder = wmsTransferOrderMapper.selectById(item.getTransferId());
if (wmsTransferOrder != null) {
coil.setTransferType(wmsTransferOrder.getTransferType());
}
}
coilMapper.updateById(coil);
return true;
}
@@ -562,26 +584,43 @@ public class WmsTransferOrderItemServiceImpl implements IWmsTransferOrderItemSer
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean cancelTransfer(Long orderItemId) {
// 查询调拨明细
WmsTransferOrderItem item = baseMapper.selectById(orderItemId);
if (item == null) {
throw new IllegalArgumentException("明细记录不存在");
}
Long coilId = item.getCoilId();
if (coilId == null) {
throw new IllegalArgumentException("钢卷ID不能为空");
}
// 查询钢卷
WmsMaterialCoil coil = coilMapper.selectById(coilId);
if (coil == null) {
throw new IllegalArgumentException("钢卷不存在");
}
// 恢复到调拨前的状态
Long originalItemId = item.getItemIdBefore();
Long originalMaterialType = item.getMaterialTypeBefore();
Long originalWarehouseId = item.getWarehouseIdBefore();
WmsMaterialCoil coil = coilMapper.selectById(coilId);
if (coil != null) {
if (originalItemId != null && originalMaterialType != null) {
coil.setItemId(originalItemId);
coil.setItemType(originalMaterialType == 1 ? "raw_material" : "product");
coil.setMaterialType(originalMaterialType == 1 ? "原料" : "成品");
coil.setWarehouseId(originalWarehouseId);
coilMapper.updateById(coil);
}
if (originalWarehouseId != null) {
coil.setWarehouseId(originalWarehouseId);
}
// 清空调拨类型
coil.setTransferType(null);
coilMapper.updateById(coil);
// 逻辑删除调拨明细记录使用MyBatis-Plus的逻辑删除
baseMapper.deleteById(orderItemId);
return true;
}
}

View File

@@ -10,6 +10,7 @@ import com.klp.common.utils.StringUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.klp.common.helper.LoginHelper;
import com.klp.domain.bo.WmsTransferOrderBo;
import com.klp.domain.vo.WmsTransferOrderVo;
import com.klp.domain.WmsTransferOrder;
@@ -19,6 +20,7 @@ import com.klp.mapper.WmsTransferOrderItemMapper;
import com.klp.service.IWmsTransferOrderService;
import com.klp.service.IWmsTransferOrderItemService;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Collection;
@@ -71,6 +73,10 @@ public class WmsTransferOrderServiceImpl implements IWmsTransferOrderService {
lqw.like(StringUtils.isNotBlank(bo.getTransferName()), WmsTransferOrder::getTransferName, bo.getTransferName());
lqw.eq(bo.getTransferStatus() != null, WmsTransferOrder::getTransferStatus, bo.getTransferStatus());
lqw.eq(bo.getTransferTime() != null, WmsTransferOrder::getTransferTime, bo.getTransferTime());
lqw.like(StringUtils.isNotBlank(bo.getTransferType()), WmsTransferOrder::getTransferType, bo.getTransferType());
lqw.like(StringUtils.isNotBlank(bo.getApproveBy()), WmsTransferOrder::getApproveBy, bo.getApproveBy());
lqw.eq(bo.getApproveStatus() != null, WmsTransferOrder::getApproveStatus, bo.getApproveStatus());
lqw.eq(bo.getApproveTime() != null, WmsTransferOrder::getApproveTime, bo.getApproveTime());
return lqw;
}
@@ -125,4 +131,22 @@ public class WmsTransferOrderServiceImpl implements IWmsTransferOrderService {
// 再删除调拨单主记录
return baseMapper.deleteBatchIds(ids) > 0;
}
/**
* 审批调拨单
*/
@Override
public Boolean approve(Long orderId, Integer approveStatus) {
WmsTransferOrder order = baseMapper.selectById(orderId);
if (order == null) {
throw new RuntimeException("调拨单不存在");
}
if (order.getApproveStatus() != null && order.getApproveStatus() != 0) {
throw new RuntimeException("该调拨单已审批,不能重复审批");
}
order.setApproveStatus(approveStatus);
order.setApproveBy(LoginHelper.getUsername());
order.setApproveTime(new Date());
return baseMapper.updateById(order) > 0;
}
}