feat(wms): 新增即入即出和外协入库功能,调拨单新增调拨原因字段

- 新增即入即出入库单类型,实现物料直接从入库到出库的快速流转
- 增加外协入库功能,支持外部协作单位的物料入库
- 优化入库单和出库单的生成逻辑,增加批次码和出库记录的处理
- 调整库存查询方式,改为仅根据批次码查询
- 修复部分领域对象的属性类型,如BigDecimal
master
zangch@mesnac.com 4 months ago
parent a3114f135e
commit dfc361d850

@ -1,27 +1,25 @@
package org.dromara.wms.controller;
import java.util.List;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.wms.domain.bo.WmsInstockOrderBo;
import org.dromara.wms.domain.vo.WmsInstockOrderVo;
import org.dromara.wms.service.IWmsInstockOrderService;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.springframework.web.bind.annotation.*;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import java.util.List;
/**
*

@ -1,26 +1,27 @@
package org.dromara.wms.controller;
import java.util.List;
import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.web.core.BaseController;
import org.dromara.common.mybatis.core.page.PageQuery;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.wms.domain.vo.WmsInstockRecordVo;
import org.dromara.wms.domain.bo.WmsInstockRecordBo;
import org.dromara.wms.service.IWmsInstockRecordService;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.wms.domain.bo.WmsInstockRecordBo;
import org.dromara.wms.domain.vo.WmsInstockRecordVo;
import org.dromara.wms.service.IWmsInstockRecordService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
*

@ -0,0 +1,35 @@
package org.dromara.wms.controller.api;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.wms.domain.bo.WmsInstockOrderBo;
import org.dromara.wms.service.IWmsInstockOrderService;
import org.dromara.wms.service.IWmsInstockRecordService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RequiredArgsConstructor
@RestController
@RequestMapping("/wsmApi")
public class apiController {
private final IWmsInstockRecordService wmsInstockRecordService;//入库记录服务
private final IWmsInstockOrderService wmsInstockOrderService;//入库单服务
//质检入库
@PostMapping("/qcInstore")
public R<Boolean> qcInstore(String instockCode){
return R.ok(wmsInstockRecordService.completeQualityCheck(instockCode));
}
//外协单入库
@PostMapping("/outSourceInstore")
public R<Boolean> outSourceInstore(WmsInstockOrderBo bo){
bo.setInstockType("5");//外协单入库
return R.ok(wmsInstockOrderService.createOutsourceInstockOrder(bo));
}
}

@ -1,13 +1,10 @@
package org.dromara.wms.domain;
import org.dromara.common.tenant.core.TenantEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.Serial;
import java.util.Date;
/**
* wms_allocate_order
@ -98,6 +95,13 @@ public class WmsAllocateOrder{
*
*/
private String inMethod;
/**
*
*/
private String allocateReason;
/**
* id
*/

@ -1,13 +1,16 @@
package org.dromara.wms.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import com.ibm.icu.math.BigDecimal;
import org.dromara.common.tenant.core.TenantEntity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.tenant.core.TenantEntity;
import java.io.Serial;
import java.math.BigDecimal;
/**
* wms_outstock_record
@ -58,7 +61,7 @@ public class WmsOutstockRecord extends TenantEntity {
*
*/
@TableField(typeHandler = JacksonTypeHandler.class)
private java.math.BigDecimal outstockQty;
private BigDecimal outstockQty;
/**
*
@ -75,7 +78,7 @@ public class WmsOutstockRecord extends TenantEntity {
* erp
*/
@TableField(typeHandler = JacksonTypeHandler.class)
private java.math.BigDecimal erpSynchronousQty;
private BigDecimal erpSynchronousQty;
/**
@ -91,7 +94,7 @@ public class WmsOutstockRecord extends TenantEntity {
private String materialSpec;
@TableField(exist = false)
private java.math.BigDecimal returnQty;
private BigDecimal returnQty;
private String returnFlag;
@TableField(exist = false)
private Long warehouseId;

@ -1,16 +1,13 @@
package org.dromara.wms.domain.bo;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import jakarta.validation.constraints.*;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import org.dromara.wms.domain.WmsAllocateOrder;
import java.util.Date;
/**
* wms_allocate_order
*
@ -111,6 +108,13 @@ public class WmsAllocateOrderBo extends BaseEntity {
*/
// @NotBlank(message = "入库方式不能为空", groups = { AddGroup.class, EditGroup.class })
private String inMethod;
/**
*
*/
private String allocateReason;
private String tenantId;
private String planWarehouseCode;
private String targetWarehouseCode;

@ -180,5 +180,10 @@ public class WmsInstockDetailBo{
// 打印份数(仅当不分包时有效)
private Integer printCopies;
/**
*
*/
private String batchCode;//若是外协入库可能会有条码
}

@ -44,9 +44,9 @@ public class WmsInstockOrderBo extends BaseEntity {
private String materialCategoryId;
/**
* (1,2,3,4)
* (1,2,3,456)
*/
@NotBlank(message = "工单类型(1采购订单,2生产订单,3手工,4系统生成)不能为空", groups = { AddGroup.class, EditGroup.class })
@NotBlank(message = "工单类型(1采购订单,2生产订单,3手工,4系统生成5外协入库6即入即出)不能为空", groups = { AddGroup.class, EditGroup.class })
private String instockType;
/**

@ -53,7 +53,7 @@ public class WmsOutstockRecordBo extends BaseEntity {
/**
*
*/
private java.math.BigDecimal outstockQty;
private BigDecimal outstockQty;
/**
*

@ -294,6 +294,7 @@ public class BaseMaterialInfoVo implements Serializable {
/**
*
*
*/
@ExcelProperty(value = "最大停放时间", converter = ExcelDictConvert.class)
@ExcelDictFormat(readConverterExp = "秒=")
@ -382,14 +383,16 @@ public class BaseMaterialInfoVo implements Serializable {
*/
private String unitName;//JOIN
/**
/**
* (0,1)
*/
@ExcelDictFormat(dictType = "is_high_value")
private String isHighValue;
/**
* (0,1)
*/
@ExcelDictFormat(dictType = "inspection_request")
private String inspectionRequest;
}

@ -1,14 +1,9 @@
package org.dromara.wms.domain.vo;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.wms.domain.WmsAllocateOrder;
@ -122,6 +117,14 @@ public class WmsAllocateOrderVo implements Serializable {
*/
@ExcelProperty(value = "入库方式")
private String inMethod;
/**
*
*/
@ExcelProperty(value = "调拨原因")
private String allocateReason;
/**
* id
*/

@ -10,6 +10,7 @@ import org.dromara.wms.domain.WmsOutstockDetail;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
@ -101,7 +102,7 @@ public class WmsOutstockDetailVo implements Serializable {
/**
*
*/
private java.math.BigDecimal completeQty;
private BigDecimal completeQty;
/**
* AGV0 / 1 / 2

@ -67,4 +67,12 @@ public interface IWmsInstockOrderService {
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
Integer approveInstockOrder(WmsInstockOrderBo bo);
/**
*
*
* @param bo
* @return
*/
Boolean createOutsourceInstockOrder(WmsInstockOrderBo bo);
}

@ -1,12 +1,11 @@
package org.dromara.wms.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
@ -14,22 +13,17 @@ import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.wms.domain.BaseMaterialCategory;
import org.dromara.wms.domain.WmsBaseWarehouse;
import org.dromara.wms.domain.WmsConfiguration;
import org.dromara.wms.domain.WmsInstockOrder;
import org.dromara.wms.domain.bo.WmsInstockOrderBo;
import org.dromara.wms.domain.bo.*;
import org.dromara.wms.domain.vo.WmsBaseLocationVo;
import org.dromara.wms.domain.vo.WmsInstockOrderVo;
import org.dromara.wms.mapper.WmsInstockOrderMapper;
import org.dromara.wms.service.IWmsInstockDetailService;
import org.dromara.wms.service.IWmsInstockOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.dromara.wms.service.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
@ -44,14 +38,22 @@ public class WmsInstockOrderServiceImpl implements IWmsInstockOrderService {
private static final AtomicInteger sequence = new AtomicInteger(999);
private static final String auditPass = "1";
private final WmsInstockOrderMapper baseMapper;
@Autowired
private IWmsInstockDetailService wmsInstockDetailService;
private final IWmsInstockDetailService wmsInstockDetailService;
private final IWmsOutstockRecordService wmsOutstockRecordService;
private final IWmsInstockPrintService wmsInstockPrintService;
private final IWmsBaseLocationService baseLocationService;
private final IWmsInventoryService inventoryService;
private final IWmsInstockRecordService wmsInstockRecordService;
public static Integer nextSequence() {
return sequence.incrementAndGet();
}
/**
*
*
@ -169,6 +171,7 @@ public class WmsInstockOrderServiceImpl implements IWmsInstockOrderService {
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public WmsInstockOrderVo insertByBo(WmsInstockOrderBo bo) {
String username = LoginHelper.getUsername();
Date date = new Date();
@ -183,36 +186,72 @@ public class WmsInstockOrderServiceImpl implements IWmsInstockOrderService {
}else {
orderLast = generateOrder(value);
}
// "即入即出" 逻辑:在子表保存完成后处理
if ("6".equals(bo.getInstockType())) {
bo.setAuditStatus("1");//即入即出直接通过
bo.setAuditBy(username);
bo.setAuditTime(date);
bo.setAuditComments("即入即出自动通过");
}
String inStockOrder = order + orderDate + orderLast;
WmsInstockOrder add = MapstructUtils.convert(bo, WmsInstockOrder.class);
List<WmsConfiguration> allConfigurationList = baseMapper.selectAllConfiguration(bo.getWarehouseId());
if (CollectionUtils.isNotEmpty(allConfigurationList)){
//查询入库单不用审批的配置
List<WmsConfiguration> unAuditConfigurationList = baseMapper.selectUnAuditByConfiguration(bo.getWarehouseId());
if (CollectionUtils.isNotEmpty(unAuditConfigurationList)){
add.setAuditStatus(auditPass);
}else {
//查询入库单是否有对应审批配置
List<WmsConfiguration> configurationList = baseMapper.selectAuditByConfiguration(bo.getWarehouseId());
if (CollectionUtils.isNotEmpty(configurationList)){
add.setAuditBy(configurationList.get(0).getAuditBy());
}
}
}else {
add.setAuditStatus(auditPass);
}
validEntityBeforeSave(add);
add.setInstockCode(inStockOrder);
add.setCreateBy(username);
// 保存入库单主表
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setInstockId(add.getInstockId());
if (!flag) {
throw new ServiceException("入库单主表保存失败");
}
LambdaQueryWrapper<WmsInstockOrder> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(WmsInstockOrder::getInstockCode,inStockOrder);
WmsInstockOrderVo instockOrderVo = baseMapper.selectVoOne(wrapper);
return instockOrderVo;
MPJLambdaWrapper<WmsInstockOrder> addOne = buildQueryWrapper(bo);
WmsInstockOrderVo orderVo = baseMapper.selectVoOne(addOne);
// 设置生成的主键ID
bo.setInstockId(orderVo.getInstockId());
bo.setInstockCode(inStockOrder);
// 处理入库单子表
if (bo.getDetailListBo() != null && !bo.getDetailListBo().isEmpty()) {
// 为每个明细设置入库单信息
for (WmsInstockDetailBo detail : bo.getDetailListBo()) {
detail.setInstockId(orderVo.getInstockId());
detail.setInstockCode(inStockOrder);
}
// 批量保存入库单子表
boolean detailFlag = wmsInstockDetailService.insertByBo(bo.getDetailListBo());
if (!detailFlag) {
throw new ServiceException("入库单子表保存失败");
}
}
// "即入即出" 逻辑:在子表保存完成后处理
if ("6".equals(bo.getInstockType())) {
if (!inAndOut(bo)) {
throw new ServiceException("即入即出入库单生成失败");
}
}
// List<WmsConfiguration> allConfigurationList = baseMapper.selectAllConfiguration(bo.getWarehouseId());
// if (CollectionUtils.isNotEmpty(allConfigurationList)){
// //查询入库单不用审批的配置
// List<WmsConfiguration> unAuditConfigurationList = baseMapper.selectUnAuditByConfiguration(bo.getWarehouseId());
// if (CollectionUtils.isNotEmpty(unAuditConfigurationList)){
// add.setAuditStatus(auditPass);
// }else {
// //查询入库单是否有对应审批配置
// List<WmsConfiguration> configurationList = baseMapper.selectAuditByConfiguration(bo.getWarehouseId());
// if (CollectionUtils.isNotEmpty(configurationList)){
// add.setAuditBy(configurationList.get(0).getAuditBy());
// }
// }
// }else {
// add.setAuditStatus(auditPass);
// }
return orderVo;
}
public String generateOrder(Integer value){
if (value.toString().length()<3){
@ -224,6 +263,165 @@ public class WmsInstockOrderServiceImpl implements IWmsInstockOrderService {
return value.toString();
}
/**
*
*
* 1.
* 2.
* 3.
* 4. 使
* 5. 0
*
* @param bo
* @return
*/
@Transactional(rollbackFor = Exception.class)
private boolean inAndOut(WmsInstockOrderBo bo) {
try {
// 获取默认库位,直接为第一个
List<WmsBaseLocationVo> locationList = baseLocationService.queryVoList(new WmsBaseLocationBo());
if (locationList == null || locationList.isEmpty()) {
throw new ServiceException("即入即出:默认库位不存在");
}
WmsBaseLocationVo defaultLocation = locationList.get(0);
String defaultLocationCode = defaultLocation.getLocationCode();
// 获取当前登录用户
String username = LoginHelper.getUsername();
Date currentTime = new Date();
// 处理每个入库明细 - 注意:此时明细已经保存到数据库
if (bo.getDetailListBo() != null && !bo.getDetailListBo().isEmpty()) {
for (WmsInstockDetailBo detail : bo.getDetailListBo()) {
// 1. 生成唯一批次码(入库单号 + 物料编码 + 序列号)
String batchCode = generateBatchCodeForInOut(bo.getInstockCode(), detail.getMaterialCode());
// 2. 创建入库记录
WmsInstockRecordBo instockRecord = new WmsInstockRecordBo();
instockRecord.setInstockCode(bo.getInstockCode());
instockRecord.setBatchCode(batchCode);
instockRecord.setMaterialId(detail.getMaterialId());
instockRecord.setWarehouseId(bo.getWarehouseId());
instockRecord.setLocationCode(defaultLocationCode);
instockRecord.setMaterialCode(detail.getMaterialCode());
instockRecord.setMaterialName(detail.getMaterialName());
instockRecord.setInstockQty(detail.getInstockQty().doubleValue());
instockRecord.setMaterialCategoryId(detail.getMaterialCategoryId());
instockRecord.setErpSynchronousStatus("0"); // 默认未同步
instockRecord.setErpSynchronousQty(0.0);
// 保存入库记录
boolean inRecordResult = wmsInstockRecordService.insertByBo(instockRecord);
if (!inRecordResult) {
throw new ServiceException("即入即出:入库记录保存失败 - " + detail.getMaterialCode());
}
// 3. 创建出库记录(即入即出:入库后立即出库)
WmsOutstockRecordBo outstockRecord = new WmsOutstockRecordBo();
outstockRecord.setOutstockCode(generateOutstockCodeForInOut(bo.getInstockCode())); // 基于入库单号生成关联出库单号
outstockRecord.setOutstockId(null); // 即入即出模式没有正式出库单ID
outstockRecord.setBatchCode(batchCode); // 使用同一批次码
outstockRecord.setMaterialId(detail.getMaterialId());
outstockRecord.setLocationCode(defaultLocationCode);
outstockRecord.setOutstockQty(detail.getInstockQty());
outstockRecord.setMaterialCategoryId(detail.getMaterialCategoryId());
// outstockRecord.setErpSynchronousStatus("0"); // 默认未同步
// outstockRecord.setErpSynchronousQty(BigDecimal.ZERO);// 默认未同步
// 保存出库记录
boolean outRecordResult = wmsOutstockRecordService.insertByBo(outstockRecord);
if (!outRecordResult) {
throw new ServiceException("即入即出:出库记录保存失败 - " + detail.getMaterialCode());
}
// 4. 库存处理:即入即出模式下,理论上不产生库存积压
// 但可以选择性地记录库存流水用于追溯
// TODO: 根据业务需求决定是否需要记录库存变动流水
}
} else {
throw new ServiceException("即入即出:入库明细为空,无法处理");
}
return true;
} catch (Exception e) {
throw new ServiceException("即入即出处理失败:" + e.getMessage());
}
}
/**
*
* BC + + 6
*
* @return
*/
private String generateBatchCode() {
Date date = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
String dateStr = format.format(date);
Integer sequence = nextSequence();
String sequenceStr = String.format("%06d", sequence);
return "BC" + dateStr + sequenceStr;
}
/**
*
* OUT + + 3
*
* @return
*/
private String generateOutstockCode() {
Date date = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
String dateStr = format.format(date);
Integer sequence = nextSequence();
String sequenceStr = String.format("%03d", sequence);
return "OUT" + dateStr + sequenceStr;
}
/**
*
* BC + 8 + 6 + 3
*
* @param instockCode
* @param materialCode
* @return
*/
private String generateBatchCodeForInOut(String instockCode, String materialCode) {
String prefix = "BC";
// 获取入库单号后8位去除前缀IN
String instockSuffix = instockCode.length() >= 8 ?
instockCode.substring(instockCode.length() - 8) : instockCode;
// 获取物料编码后6位不足时前补0
String materialSuffix = materialCode.length() >= 6 ?
materialCode.substring(materialCode.length() - 6) :
String.format("%06d", Integer.parseInt(materialCode.replaceAll("[^0-9]", "0")));
// 生成3位序列号
Integer sequence = nextSequence();
String sequenceStr = String.format("%03d", sequence % 1000);
return prefix + instockSuffix + materialSuffix + sequenceStr;
}
/**
*
* OUT + 10
*
* @param instockCode
* @return
*/
private String generateOutstockCodeForInOut(String instockCode) {
String prefix = "OUT";
// 获取入库单号后10位去除前缀IN确保唯一性
String instockSuffix = instockCode.length() >= 10 ?
instockCode.substring(instockCode.length() - 10) : instockCode;
return prefix + instockSuffix;
}
/**
*
*
@ -282,4 +480,86 @@ public class WmsInstockOrderServiceImpl implements IWmsInstockOrderService {
int count = wmsInstockDetailService.deleteByInstockId(ids);
return delete>0;
}
/**
*
* 1.
* 2.
* 3.
* 4.
*/
/**
*
* 1.
* 2.
* 3.
* 4.
*
* @param bo
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean createOutsourceInstockOrder(WmsInstockOrderBo bo) {
// 1. 获取当前登录用户名
String username = LoginHelper.getUsername();
// 2. 生成入库单号:格式为 IN + 年月日 + 3位序列号
Date date = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
String orderDate = format.format(date);
String order = "IN";
String orderLast = "";
Integer value = nextSequence();
if (value.toString().length() == 4) {
sequence.set(1);
orderLast = generateOrder(sequence.get());
} else {
orderLast = generateOrder(value);
}
String inStockOrder = order + orderDate + orderLast;
// 3. 转换并设置入库单主表信息
WmsInstockOrder add = MapstructUtils.convert(bo, WmsInstockOrder.class);
add.setInstockCode(inStockOrder);
add.setCreateBy(username);
// add.setAuditStatus("1"); // 外协入库默认审核通过
// 4. 保存入库单主表
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
// 5. 处理入库单子表
bo.getDetailListBo().forEach(detail -> {
// 设置明细关联的入库单ID和单号
detail.setInstockId(add.getInstockId());
detail.setInstockCode(inStockOrder);
// 6. 保存入库单子表(单个保存)
wmsInstockDetailService.insertByBo(Collections.singletonList(detail));
// 7. 如果明细中有批次号,则生成打印记录
if (StringUtils.isNotBlank(detail.getBatchCode())) {
WmsInstockPrintBo printBo = new WmsInstockPrintBo();
// 设置打印记录信息
printBo.setInstockCode(inStockOrder);
printBo.setBatchCode(detail.getBatchCode());
printBo.setMaterialQty(detail.getInstockQty().longValue());
printBo.setApportionQty(detail.getApportionQty());
printBo.setMaterialId(detail.getMaterialId());
printBo.setMaterialCode(detail.getMaterialCode());
printBo.setMaterialName(detail.getMaterialName());
printBo.setMaterialSpe(detail.getMaterialSpe());
printBo.setUnitName(detail.getUnitName());
printBo.setCodeYesNo(detail.getCodeYesNo());
printBo.setMaterialCategoryId(detail.getMaterialCategoryId());
// 8. 保存打印记录
wmsInstockPrintService.insertByBo(printBo);
}
});
}
return flag;
}
}

@ -11,6 +11,7 @@ import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.wms.domain.BaseMaterialCategory;
import org.dromara.wms.domain.WmsInstockOrder;
import org.dromara.wms.domain.WmsInstockRecord;
import org.dromara.wms.domain.bo.WmsInstockOrderBo;
import org.dromara.wms.domain.bo.WmsInstockPrintBo;
@ -23,6 +24,7 @@ import org.dromara.wms.domain.vo.WmsInventoryVo;
import org.dromara.wms.mapper.WmsInstockOrderMapper;
import org.dromara.wms.mapper.WmsInstockRecordMapper;
import org.dromara.wms.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -44,11 +46,13 @@ public class WmsInstockRecordServiceImpl implements IWmsInstockRecordService {
private final WmsInstockRecordMapper baseMapper;
private final IWmsInventoryService inventoryService;
private final IWmsInstockOrderService instockOrderService;
// private final IWmsInstockOrderService instockOrderService;
private final WmsInstockOrderMapper instockOrderMapper;
private final IWmsInstockDetailService instockDetailService;
private final IWmsInstockPrintService instockPrintService;
/**
*
*
@ -174,10 +178,17 @@ public class WmsInstockRecordServiceImpl implements IWmsInstockRecordService {
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean completeQualityCheck(String instockCode) {
// 查询入库单信息
// 查询入库单信息, 只根据入库单号查询
WmsInstockOrderBo orderBo = new WmsInstockOrderBo();
orderBo.setInstockCode(instockCode);
List<WmsInstockOrderVo> orders = instockOrderService.queryList(orderBo);
MPJLambdaWrapper<WmsInstockOrder> lqwInstockOrder = JoinWrappers.lambda(WmsInstockOrder.class)
.selectAll(WmsInstockOrder.class)
.eq(StringUtils.isNotBlank(orderBo.getInstockCode()), WmsInstockOrder::getInstockCode, orderBo.getInstockCode())
.orderByDesc(WmsInstockOrder::getCreateTime);
List<WmsInstockOrderVo> orders = instockOrderMapper.selectVoList(lqwInstockOrder);
if (orders.isEmpty()) {
throw new ServiceException("入库单不存在 " + instockCode);
}
@ -220,8 +231,8 @@ public class WmsInstockRecordServiceImpl implements IWmsInstockRecordService {
instockPrintService.updateByBo(newPrintBo);
// 更新库存信息
WmsInventoryVo inventoryVo = inventoryService.queryByBatchAndLocation(recordBo.getBatchCode(), recordBo.getLocationCode());
// 更新库存信息,todo只根据批次号
WmsInventoryVo inventoryVo = inventoryService.queryByBatchAndLocation(recordBo.getBatchCode());
double qty = recordBo.getInstockQty();
if (inventoryVo == null) {
// 如果库存记录不存在,则新增一条库存记录

@ -225,17 +225,16 @@ public class WmsInventoryServiceImpl implements IWmsInventoryService {
/**
*
*
* @param batchCode
* @param locationCode
* @return VO
*/
@Override
public WmsInventoryVo queryByBatchAndLocation(String batchCode, String locationCode) {
public WmsInventoryVo queryByBatchAndLocation(String batchCode) {
LambdaQueryWrapper<WmsInventory> lqw = Wrappers.lambdaQuery();
lqw
.eq(WmsInventory::getBatchCode, batchCode)
.eq(WmsInventory::getLocationCode, locationCode);
.eq(WmsInventory::getBatchCode, batchCode);
return baseMapper.selectVoOne(lqw);
}

@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
@ -14,10 +15,13 @@ import org.dromara.wms.domain.BaseMaterialCategory;
import org.dromara.wms.domain.WmsBaseWarehouse;
import org.dromara.wms.domain.WmsOutstockOrder;
import org.dromara.wms.domain.bo.WmsOutstockOrderBo;
import org.dromara.wms.domain.bo.WmsOutstockRecordBo;
import org.dromara.wms.domain.vo.WmsOutstockOrderVo;
import org.dromara.wms.mapper.WmsOutstockOrderMapper;
import org.dromara.wms.mapper.WmsOutstockRecordMapper;
import org.dromara.wms.service.IWmsOutstockDetailService;
import org.dromara.wms.service.IWmsOutstockOrderService;
import org.dromara.wms.service.IWmsOutstockRecordService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -47,6 +51,9 @@ public class WmsOutstockOrderServiceImpl implements IWmsOutstockOrderService {
@Autowired
private IWmsOutstockDetailService wmsOutstockDetailService;
private final IWmsOutstockRecordService wmsOutstockRecordService;//出库记录Service
private final WmsOutstockRecordMapper wmsOutstockRecordMapper;//出库记录Mapper
/**
*
*
@ -132,45 +139,114 @@ public class WmsOutstockOrderServiceImpl implements IWmsOutstockOrderService {
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public WmsOutstockOrderVo insertByBo(WmsOutstockOrderBo bo) {
// 获取当前登录用户名
String username = LoginHelper.getUsername();
// 获取当前时间并格式化为指定格式
Date date = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHssmm");
String orderDate = format.format(date);
// 出库单号前缀
String order = "OU";
String orderLast="";
String orderLast = "";
// 获取下一个序列号
Integer value = nextSequence();
if (value.toString().length()==4){
// 如果序列号长度等于4则重置序列号从1开始
if (value.toString().length() == 4) {
sequence.set(1);
orderLast = generateOrder(sequence.get());
}else {
} else {
orderLast = generateOrder(value);
}
// 生成完整的出库单号
String outStockOrder = order + orderDate + orderLast;
// 转换业务对象为实体对象
WmsOutstockOrder add = MapstructUtils.convert(bo, WmsOutstockOrder.class);
// 验证实体数据是否合规
validEntityBeforeSave(add);
// 设置出库单号、创建人
add.setOutstockCode(outStockOrder);
add.setCreateBy(username);
if("4".equals(add.getOutstockType())){ // 出库类型4为 AGV 出库
Boolean agvFlag = agvAction(add);
if (agvFlag) {
// 1) 保存出库单信息
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setOutstockId(add.getOutstockId());
}
// 2) 写入出库记录(最小必要字段,后续可按业务补充)
WmsOutstockRecordBo record = new WmsOutstockRecordBo();
record.setOutstockCode(outStockOrder); // 关联出库单号
record.setMaterialCategoryId(add.getMaterialCategoryId()); // 若为空则由后续流程补充
// TODO根据业务需要补齐其他字段例如仓库、物料、数量、位置等
boolean rec = wmsOutstockRecordService.insertByBo(record);
if (!rec) {
throw new ServiceException("AGV出库生成出库记录失败");
}
// 3) 查询并返回出库单视图
LambdaQueryWrapper<WmsOutstockOrder> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(WmsOutstockOrder::getOutstockCode, outStockOrder);
return baseMapper.selectVoOne(wrapper);
} else {
// AGV 调用失败,直接返回 null 或抛出异常按需处理
return null;
}
}
// 保存出库单信息
boolean flag = baseMapper.insert(add) > 0;
// 如果保存成功设置出库单ID
if (flag) {
bo.setOutstockId(add.getOutstockId());
}
// 根据出库单号查询最新出库单信息
LambdaQueryWrapper<WmsOutstockOrder> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(WmsOutstockOrder::getOutstockCode,outStockOrder);
wrapper.eq(WmsOutstockOrder::getOutstockCode, outStockOrder);
List<WmsOutstockOrderVo> vos = baseMapper.selectVoList(wrapper);
// 返回出库单视图对象
return vos.get(0);
}
public String generateOrder(Integer value){
if (value.toString().length()<3){
/**
*
* @param value
* @return
*/
public String generateOrder(Integer value) {
// 如果序列号小于3位前面补0
if (value.toString().length() < 3) {
String fixedLengthString = String.format("%03d", value);
return fixedLengthString;
}else if (value.toString().length()==3){
} else if (value.toString().length() == 3) {
// 如果正好是3位直接返回
return value.toString();
}
// 其他情况直接返回字符串形式
return value.toString();
}
/**
* agv
* @param wmsOutstockOrder
* @return
*/
private Boolean agvAction(WmsOutstockOrder wmsOutstockOrder){
//TODO:调用agv接口
return true;
}
/**
*
*

Loading…
Cancel
Save