chen.lin
昨天 d3f479a5e246d808688f85ca0b59e86c92621dbf
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java
@@ -19,6 +19,7 @@
import com.vincent.rsf.server.manager.utils.OptimalAlgorithmUtil;
import com.vincent.rsf.server.system.constant.SerialRuleCode;
import com.vincent.rsf.server.system.utils.SerialRuleUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -28,6 +29,7 @@
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;
@@ -40,11 +42,14 @@
 * @return
 * @time 2025/3/7 08:02
 */
@Slf4j
@Service("outStockServiceImpl")
public class OutStockServiceImpl extends ServiceImpl<AsnOrderMapper, WkOrder> implements OutStockService {
    public Logger logger = LoggerFactory.getLogger(this.getClass());
    /** 出库剩余量容差:小于等于此值视为已分配完,避免浮点误差产生多余“库存不足”行 */
    private static final BigDecimal ISSUED_TOLERANCE = new BigDecimal("0.000001");
    @Autowired
    private AsnOrderItemService asnOrderItemService;
@@ -488,21 +493,83 @@
            if (!Objects.isNull(loc)) {
                List<LocItem> locItems = new ArrayList<>();
                LocItem locItem = locItemService.getById(param.getId());
                if (Objects.isNull(locItem)) {
                    throw new CoolException("库位明细不存在,ID:" + param.getId());
                }
                // 修复:构建查询条件,先构建基础条件,再根据值是否为空动态添加
                // 优先使用供应商批次匹配,如果没有则使用库存批次匹配
                LambdaQueryWrapper<WkOrderItem> orderItemWrapper = new LambdaQueryWrapper<WkOrderItem>()
                        .eq(WkOrderItem::getOrderId, outId)
                        .eq(WkOrderItem::getMatnrId, locItem.getMatnrId());
                if (StringUtils.isNotBlank(locItem.getBatch())) {
                    orderItemWrapper.eq(WkOrderItem::getSplrBatch, locItem.getBatch());
                // 优先使用供应商批次匹配
                if (StringUtils.isNotBlank(locItem.getSplrBatch())) {
                    orderItemWrapper.eq(WkOrderItem::getSplrBatch, locItem.getSplrBatch());
                } else if (StringUtils.isNotBlank(locItem.getBatch())) {
                    // 如果LocItem只有batch字段,尝试同时匹配WkOrderItem的batch和splrBatch字段
                    // 因为某些情况下LocItem的batch可能对应WkOrderItem的splrBatch
                    orderItemWrapper.and(wrapper -> wrapper
                            .eq(WkOrderItem::getBatch, locItem.getBatch())
                            .or()
                            .eq(WkOrderItem::getSplrBatch, locItem.getBatch())
                    );
                }
                if (StringUtils.isNotBlank(locItem.getFieldsIndex())) {
                    orderItemWrapper.eq(WkOrderItem::getFieldsIndex, locItem.getFieldsIndex());
                }
                WkOrderItem orderItem = outStockItemService.getOne(orderItemWrapper);
                // 如果找不到单据明细,且LocItem来自库存调整,则自动创建WkOrderItem
                if (Objects.isNull(orderItem)) {
                    throw new CoolException("单据明细不存在!!");
                    // 检查是否是库存调整产生的库存
                    if (locItem.getWkType() != null &&
                        locItem.getWkType().equals(Short.parseShort(OrderWorkType.ORDER_WORK_TYPE_STOCK_REVISE.type))) {
                        // 获取出库单信息
                        WkOrder outOrder = outStockService.getById(outId);
                        if (Objects.isNull(outOrder)) {
                            throw new CoolException("出库单据不存在!!");
                        }
                        log.info("库存调整产生的库存,自动创建WkOrderItem - 出库单ID:{},物料ID:{},批次:{}",
                                outId, locItem.getMatnrId(), locItem.getBatch());
                        // 创建WkOrderItem
                        orderItem = new WkOrderItem();
                        orderItem.setOrderId(outId)
                                .setOrderCode(outOrder.getCode())
                                .setMatnrId(locItem.getMatnrId())
                                .setMatnrCode(locItem.getMatnrCode())
                                .setMaktx(locItem.getMaktx())
                                .setBatch(StringUtils.isNotBlank(param.getBatch()) ? param.getBatch() : locItem.getBatch())
                                .setSplrBatch(StringUtils.isNotBlank(locItem.getSplrBatch()) ? locItem.getSplrBatch() :
                                             (StringUtils.isNotBlank(locItem.getBatch()) ? locItem.getBatch() : null))
                                .setFieldsIndex(locItem.getFieldsIndex())
                                .setAnfme(param.getOutQty())
                                .setWorkQty(0.0)
                                .setStockUnit(locItem.getUnit())
                                .setPurUnit(locItem.getUnit())
                                .setSpec(locItem.getSpec())
                                .setModel(locItem.getModel())
                                .setCreateBy(loginUserId)
                                .setUpdateBy(loginUserId)
                                .setCreateTime(new Date())
                                .setUpdateTime(new Date());
                        if (!outStockItemService.save(orderItem)) {
                            throw new CoolException("库存调整单据明细创建失败!!");
                        }
                        log.info("WkOrderItem创建成功 - ID:{},出库单ID:{},物料ID:{}",
                                orderItem.getId(), outId, locItem.getMatnrId());
                    } else {
                        throw new CoolException("单据明细不存在!!出库单ID:" + outId + ",物料ID:" + locItem.getMatnrId() +
                                (StringUtils.isNotBlank(locItem.getSplrBatch()) ? ",供应商批次:" + locItem.getSplrBatch() :
                                 StringUtils.isNotBlank(locItem.getBatch()) ? ",库存批次:" + locItem.getBatch() : "") +
                                (StringUtils.isNotBlank(locItem.getFieldsIndex()) ? ",字段索引:" + locItem.getFieldsIndex() : ""));
                    }
                }
                locItem.setOutQty(param.getOutQty())
@@ -617,9 +684,8 @@
        Set<ExistDto> existDtos = new HashSet<>();
        for (WkOrderItem wkOrderItem : wkOrderItems) {
            BigDecimal issued = new BigDecimal(wkOrderItem.getAnfme().toString())
                    .subtract(new BigDecimal(wkOrderItem.getWorkQty().toString())
                    );
            if (issued.doubleValue() <= 0) {
                    .subtract(new BigDecimal(wkOrderItem.getWorkQty().toString()));
            if (issued.compareTo(ISSUED_TOLERANCE) <= 0) {
                continue;
            }
            List<LocItem> locItems = new ArrayList<>();
@@ -633,7 +699,7 @@
            for (LocItem locItem : locItems) {
                Loc loc = locService.getById(locItem.getLocId());
                List<LocItem> itemList = locItemService.list(new LambdaQueryWrapper<LocItem>().eq(LocItem::getLocCode, locItem.getLocCode()));
                if (issued.doubleValue() > 0) {
                if (issued.compareTo(ISSUED_TOLERANCE) > 0) {
                    ExistDto existDto = new ExistDto().setBatch(locItem.getBatch()).setMatnr(locItem.getMatnrCode()).setLocNo(locItem.getLocCode());
                    if (existDtos.add(existDto)) {
                        locItem.setOutQty(issued.doubleValue() >= locItem.getAnfme() ? locItem.getAnfme() : issued.doubleValue());
@@ -666,14 +732,15 @@
                    }
                }
            }
            if (issued.doubleValue() > 0) {
            if (issued.compareTo(ISSUED_TOLERANCE) > 0) {
                double remaining = issued.setScale(6, RoundingMode.HALF_UP).doubleValue();
                LocItem locItem = new LocItem()
                        .setId(new Random().nextLong())
                        .setMatnrCode(wkOrderItem.getMatnrCode())
                        .setMaktx(wkOrderItem.getMaktx())
                        .setAnfme(0.00)
                        .setWorkQty(issued.doubleValue())
                        .setOutQty(issued.doubleValue())
                        .setWorkQty(remaining)
                        .setOutQty(remaining)
                        .setUnit(wkOrderItem.getStockUnit())
                        .setBatch(wkOrderItem.getSplrBatch());
                OrderOutItemDto orderOutItemDto = new OrderOutItemDto();