Commit 63dd6d31 by yubin

导入修改

parent ff9d771e
...@@ -683,6 +683,7 @@ export default { ...@@ -683,6 +683,7 @@ export default {
this.getList() this.getList()
}) })
this.handleShip = this.debounce(this.handleShip, 500) this.handleShip = this.debounce(this.handleShip, 500)
}, },
methods: { methods: {
debounce(fn, delay = 300) { debounce(fn, delay = 300) {
......
...@@ -719,4 +719,5 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils ...@@ -719,4 +719,5 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
} }
return sb.toString(); return sb.toString();
} }
} }
\ No newline at end of file
...@@ -117,5 +117,7 @@ public class OutboundOrderItems extends BaseEntity ...@@ -117,5 +117,7 @@ public class OutboundOrderItems extends BaseEntity
@Excel(name = "排序号") @Excel(name = "排序号")
private String updateUserCode; private String updateUserCode;
private String InventoryType;
} }
\ No newline at end of file
...@@ -116,4 +116,6 @@ public interface InventoryMapper ...@@ -116,4 +116,6 @@ public interface InventoryMapper
public List<java.util.Map<String, String>> selectInventoryTopTenByAmount(); public List<java.util.Map<String, String>> selectInventoryTopTenByAmount();
public List<java.util.Map<String, String>> selectInventoryTopTenByQuantity(); public List<java.util.Map<String, String>> selectInventoryTopTenByQuantity();
public void batchUpdateInventory(List<Inventory> inventoryList);
} }
...@@ -4,6 +4,7 @@ import java.util.*; ...@@ -4,6 +4,7 @@ import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.ruoyi.common.annotation.SerialExecution; import com.ruoyi.common.annotation.SerialExecution;
import com.ruoyi.common.config.WarehouseConfig;
import com.ruoyi.common.core.domain.entity.Materials; import com.ruoyi.common.core.domain.entity.Materials;
import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.DateUtils;
...@@ -28,6 +29,10 @@ import org.springframework.util.CollectionUtils; ...@@ -28,6 +29,10 @@ import org.springframework.util.CollectionUtils;
/** /**
* 出库单主Service业务层处理 * 出库单主Service业务层处理
* 核心修正:
* 1. 库存匹配Key统一为 仓库ID_物料ID_库位ID_库存类型
* 2. 确保inventoryType完整参与匹配
* 3. 库存扣减后≤0时强制设置inventory_status=0
* *
* @author ruoyi * @author ruoyi
* @date 2025-12-03 * @date 2025-12-03
...@@ -54,6 +59,10 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService ...@@ -54,6 +59,10 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
private MaterialsServiceImpl materialsService; private MaterialsServiceImpl materialsService;
@Autowired @Autowired
private StorageLocationsServiceImpl storageLocationsService; private StorageLocationsServiceImpl storageLocationsService;
@Autowired
private InventoryMapper inventoryMapper;
/** /**
* 查询出库单主 * 查询出库单主
* *
...@@ -63,7 +72,6 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService ...@@ -63,7 +72,6 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
@Override @Override
public OutboundOrders selectOutboundOrdersById(String id) public OutboundOrders selectOutboundOrdersById(String id)
{ {
return outboundOrdersMapper.selectOutboundOrdersById(id); return outboundOrdersMapper.selectOutboundOrdersById(id);
} }
...@@ -112,7 +120,6 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService ...@@ -112,7 +120,6 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
outboundOrdersMapper.deleteOutboundOrderItemsByOrderId(outboundOrders.getId()); outboundOrdersMapper.deleteOutboundOrderItemsByOrderId(outboundOrders.getId());
outboundOrderLogMapper.deleteOutboundOrderLogByOrdersId(outboundOrders.getId()); outboundOrderLogMapper.deleteOutboundOrderLogByOrdersId(outboundOrders.getId());
outboundOrders.setUpdateUserCode(SystemUtils.getUserName()); outboundOrders.setUpdateUserCode(SystemUtils.getUserName());
outboundOrders.setUpdateTime(DateUtils.getNowDate()); outboundOrders.setUpdateTime(DateUtils.getNowDate());
insertOutboundOrderItems(outboundOrders); insertOutboundOrderItems(outboundOrders);
...@@ -147,42 +154,161 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService ...@@ -147,42 +154,161 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
outboundOrdersMapper.deleteOutboundOrderItemsByOrderId(id); outboundOrdersMapper.deleteOutboundOrderItemsByOrderId(id);
return outboundOrdersMapper.deleteOutboundOrdersById(id); return outboundOrdersMapper.deleteOutboundOrdersById(id);
} }
@SerialExecution(group = "inventoryRefresh", fair = true) @SerialExecution(group = "inventoryRefresh", fair = true)
@Override @Override
public int ship(OutboundOrders outboundOrders) { public int ship(OutboundOrders outboundOrders) {
OutboundOrderItems outboundOrderItems1 = new OutboundOrderItems(); // 1. 查询当前出库单的所有明细
outboundOrderItems1.setOutboundOrderId(outboundOrders.getId()); OutboundOrderItems query = new OutboundOrderItems();
outboundOrderItems1.setDivisor(null); query.setOutboundOrderId(outboundOrders.getId());
List<OutboundOrderItems> outboundOrderItems = outboundOrderItemsMapper.selectOutboundOrderItemsList(outboundOrderItems1); query.setDivisor(null);
List<OutboundOrderItems> outboundOrderItems2 = outboundOrderItems; List<OutboundOrderItems> outboundOrderItems = outboundOrderItemsMapper.selectOutboundOrderItemsList(query);
// 2. 更新明细和订单状态
OutboundOrderLog outboundOrderLog = new OutboundOrderLog(); OutboundOrderLog outboundOrderLog = new OutboundOrderLog();
String updateUser = SystemUtils.getUserName();
Date updateTime = DateUtils.getNowDate();
for (OutboundOrderItems item : outboundOrderItems) {
item.setItemStatus(3L);
item.setUpdateBy(updateUser);
item.setUpdateTime(updateTime);
outboundOrderItemsMapper.updateOutboundOrderItems(item);
for (OutboundOrderItems outboundOrderItem : outboundOrderItems) { outboundOrderLog.setId(item.getId());
outboundOrderLog.setItemStatus(item.getItemStatus());
outboundOrderLogMapper.updateOutboundOrderLog(outboundOrderLog);
}
outboundOrderItem.setItemStatus(3l); outboundOrders.setOrderStatus(2L);
outboundOrderItemsMapper.updateOutboundOrderItems(outboundOrderItem); outboundOrders.setUpdateTime(updateTime);
outboundOrders.setUpdateUserCode(updateUser);
outboundOrdersMapper.updateOutboundOrders(outboundOrders);
outboundOrderLog.setId(outboundOrderItem.getId()); // 3. 执行库存扣减(包含inventoryType匹配 + 0值状态更新)
outboundOrderLog.setItemStatus(outboundOrderItem.getItemStatus()); this.deductInventory(outboundOrderItems, updateUser, updateTime);
outboundOrderLogMapper.updateOutboundOrderLog(outboundOrderLog);
return 1;
}
/**
* 核心库存扣减逻辑
* 1. 按 仓库ID_物料ID_库位ID_库存类型 匹配库存
* 2. 扣减后数量≤0时设置inventory_status=0
* @param outboundOrderItems 出库明细
* @param updateUser 操作人
* @param updateTime 操作时间
*/
private void deductInventory(List<OutboundOrderItems> outboundOrderItems, String updateUser, Date updateTime) {
if (CollectionUtils.isEmpty(outboundOrderItems)) {
return;
} }
// 1. 预加载库存映射:Key=仓库ID_物料ID_库位ID_库存类型 Value=库存对象
Map<String, Inventory> inventoryMap = this.loadInventoryMap();
// 2. 构建扣减数量Map:Key=仓库ID_物料ID_库位ID_库存类型 Value=总扣减数量
Map<String, Long> deductQtyMap = this.buildDeductQtyMap(outboundOrderItems);
outboundOrders.setId(outboundOrders.getId()); // 3. 遍历扣减Map,执行扣减+状态更新
outboundOrders.setOrderStatus(2l); List<Inventory> needUpdateList = new ArrayList<>();
outboundOrders.setUpdateTime(DateUtils.getNowDate()); for (Map.Entry<String, Long> entry : deductQtyMap.entrySet()) {
outboundOrders.setUpdateUserCode(SystemUtils.getUserName()); String key = entry.getKey();
outboundOrdersMapper.updateOutboundOrders(outboundOrders); Long deductQty = entry.getValue();
inventoryService.ship(outboundOrderItems2); // 匹配库存
return 1; Inventory inventory = inventoryMap.get(key);
if (inventory == null) {
String[] keyParts = key.split("_");
String warehouseId = keyParts.length > 0 ? keyParts[0] : "";
String materialId = keyParts.length > 1 ? keyParts[1] : "";
String locationId = keyParts.length > 2 ? keyParts[2] : "";
String inventoryType = keyParts.length > 3 ? keyParts[3] : "";
throw new ServiceException(String.format(
"仓库[%s]物料[%s]库位[%s]库存类型[%s]的库存不存在,无法扣减",
warehouseId, materialId, locationId, inventoryType));
}
// 执行数量扣减
Long currentQty = Optional.ofNullable(inventory.getQuantity()).orElse(0L);
Long newQty = currentQty - deductQty;
inventory.setQuantity(newQty);
// 核心规则:扣减后数量≤0 → 状态置0
if (newQty <= 0) {
inventory.setInventoryStatus(0L);
}
// 补充审计字段
inventory.setUpdateBy(updateUser);
inventory.setUpdateTime(updateTime);
needUpdateList.add(inventory);
}
// 4. 批量更新库存
if (!needUpdateList.isEmpty()) {
inventoryMapper.batchUpdateInventory(needUpdateList);
// 刷新库存缓存
List<String> inventoryIds = needUpdateList.stream()
.map(Inventory::getId)
.distinct()
.collect(Collectors.toList());
inventoryService.RefreshInventory(inventoryIds);
}
}
/**
* 预加载库存Map
* Key规则:仓库ID_物料ID_库位ID_库存类型
*/
private Map<String, Inventory> loadInventoryMap() {
Inventory query = new Inventory();
query.setInventoryStatus(1L);
query.setIsUsed(1L);
List<Inventory> inventoryList = inventoryService.selectInventoryList(query);
if (CollectionUtils.isEmpty(inventoryList)) {
return Collections.emptyMap();
}
Map<String, Inventory> inventoryMap = new HashMap<>();
for (Inventory inv : inventoryList) {
String key = String.join("_",
Optional.ofNullable(inv.getWarehousesId()).orElse(""),
Optional.ofNullable(inv.getMaterialId()).orElse(""),
Optional.ofNullable(inv.getLocationId()).orElse(""),
Optional.ofNullable(inv.getInventoryType()).map(String::valueOf).orElse("")
);
// 重复key保留第一个(避免覆盖)
if (!inventoryMap.containsKey(key)) {
inventoryMap.put(key, inv);
}
}
return inventoryMap;
}
/**
* 构建扣减数量Map
* Key规则:仓库ID_物料ID_库位ID_库存类型(和库存Map完全对齐)
*/
private Map<String, Long> buildDeductQtyMap(List<OutboundOrderItems> items) {
Map<String, Long> deductQtyMap = new HashMap<>();
for (OutboundOrderItems item : items) {
String key = String.join("_",
Optional.ofNullable(item.getWarehouseId()).orElse(""),
Optional.ofNullable(item.getMaterialId()).orElse(""),
Optional.ofNullable(item.getLocationId()).orElse(""),
Optional.ofNullable(item.getInventoryType()).map(String::valueOf).orElse("")
);
// 累加扣减数量
Long qty = Optional.ofNullable(item.getActualQuantity()).orElse(0L);
deductQtyMap.put(key, deductQtyMap.getOrDefault(key, 0L) + qty);
}
return deductQtyMap;
} }
@Override @Override
public List<Map<String,String>> outboundOrdersTopTenByQuantity() { public List<Map<String,String>> outboundOrdersTopTenByQuantity() {
List<Map<String,String>> o= outboundOrdersMapper.SelectOutboundOrdersMaterialsTopTenByQuantity(); return outboundOrdersMapper.SelectOutboundOrdersMaterialsTopTenByQuantity();
return o;
} }
@Override @Override
...@@ -192,7 +318,6 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService ...@@ -192,7 +318,6 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
@Override @Override
public String outboundOrdersCount() { public String outboundOrdersCount() {
return outboundOrdersMapper.outboundOrdersCount(); return outboundOrdersMapper.outboundOrdersCount();
} }
...@@ -204,48 +329,41 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService ...@@ -204,48 +329,41 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
public void insertOutboundOrderItems(OutboundOrders outboundOrders) { public void insertOutboundOrderItems(OutboundOrders outboundOrders) {
List<OutboundOrderItems> outboundOrderItemsList = outboundOrders.getOutboundOrderItemsList(); List<OutboundOrderItems> outboundOrderItemsList = outboundOrders.getOutboundOrderItemsList();
String id = outboundOrders.getId(); String id = outboundOrders.getId();
// 1. 先做空列表校验(提前返回,避免无效逻辑) if (CollectionUtils.isEmpty(outboundOrderItemsList)) {
if (outboundOrderItemsList == null || outboundOrderItemsList.isEmpty()) {
return; return;
} }
// 2. 库存校验:失败时抛异常(核心修正:! 取反 + 异常抛出后代码立即终止) // 库存校验:失败时抛异常
boolean isValid = inventoryService.inventoryLockValidation(outboundOrderItemsList); boolean isValid = inventoryService.inventoryLockValidation(outboundOrderItemsList);
if (!isValid) { // 校验失败(返回false)时抛异常 if (!isValid) {
throw new RuntimeException("库存被修改请重新确认"); // 抛异常后,方法立即停止运行 throw new RuntimeException("库存被修改请重新确认");
} }
// 2. 为明细设置订单ID和主键ID // 为明细设置订单ID和主键ID
for (OutboundOrderItems items : outboundOrderItemsList) { for (OutboundOrderItems items : outboundOrderItemsList) {
items.setOutboundOrderId(id); items.setOutboundOrderId(id);
items.setOrderId(outboundOrders.getOrderId()); items.setOrderId(outboundOrders.getOrderId());
// 生成无横线的UUID作为主键
items.setId(UUID.randomUUID().toString().replace("-", "")); items.setId(UUID.randomUUID().toString().replace("-", ""));
} }
// 3. 批量插入出库单明细 // 批量插入出库单明细
outboundOrdersMapper.batchOutboundOrderItems(outboundOrderItemsList); outboundOrdersMapper.batchOutboundOrderItems(outboundOrderItemsList);
// 4. 正确拷贝明细列表到日志列表(修复核心错误:遍历逐个拷贝) // 拷贝明细到日志列表
List<String> inventoryIds = new ArrayList<>(); List<String> inventoryIds = new ArrayList<>();
List<OutboundOrderLog> outboundOrderLogs = new ArrayList<>(); List<OutboundOrderLog> outboundOrderLogs = new ArrayList<>();
for (OutboundOrderItems items : outboundOrderItemsList) { for (OutboundOrderItems items : outboundOrderItemsList) {
OutboundOrderLog log = new OutboundOrderLog(); OutboundOrderLog log = new OutboundOrderLog();
BeanUtils.copyProperties(items, log); // 单个对象属性拷贝 BeanUtils.copyProperties(items, log);
log.setOrderId(items.getOutboundOrderId()); log.setOrderId(items.getOutboundOrderId());
outboundOrderLogs.add(log); outboundOrderLogs.add(log);
inventoryIds.add(log.getInventoryId()); inventoryIds.add(log.getInventoryId());
deleteOutboundOrdersById(items.getId());
} }
// 5. 非空校验后插入日志(避免空列表触发SQL语法错误) // 插入日志 + 刷新库存
if (!outboundOrderLogs.isEmpty()) { if (!outboundOrderLogs.isEmpty()) {
outboundOrderLogMapper.batchOutboundOrderLog(outboundOrderLogs); outboundOrderLogMapper.batchOutboundOrderLog(outboundOrderLogs);
} }
// 7. 非空校验后刷新库存
if (!inventoryIds.isEmpty()) { if (!inventoryIds.isEmpty()) {
inventoryService.RefreshInventory(inventoryIds); inventoryService.RefreshInventory(inventoryIds);
} }
...@@ -254,12 +372,12 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService ...@@ -254,12 +372,12 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
@Override @Override
public String importOutboundOrders(List<OutboundTemplateVO> inboundOrdersList, Boolean isUpdateSupport, String operName, Integer orderType) { public String importOutboundOrders(List<OutboundTemplateVO> inboundOrdersList, Boolean isUpdateSupport, String operName, Integer orderType) {
// 1. 基础空值校验(保留原有逻辑) // 1. 基础空值校验
if (CollectionUtils.isEmpty(inboundOrdersList)) { if (CollectionUtils.isEmpty(inboundOrdersList)) {
throw new ServiceException("导入数据不能为空!"); throw new ServiceException("导入数据不能为空!");
} }
// 2. 初始化变量(保留原有逻辑) // 2. 初始化变量
int totalMainSuccess = 0; int totalMainSuccess = 0;
int totalMainFailure = 0; int totalMainFailure = 0;
int totalItemSuccess = 0; int totalItemSuccess = 0;
...@@ -274,18 +392,19 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService ...@@ -274,18 +392,19 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
Map<String, List<OutboundOrderItems>> validItemMap = new HashMap<>(); Map<String, List<OutboundOrderItems>> validItemMap = new HashMap<>();
boolean hasValidateError = false; boolean hasValidateError = false;
// ========== 新增:预加载映射缓存(核心优化) ========== // 3. 预加载映射缓存
Map<String, String> sapToMaterialIdMap = loadSapToMaterialIdMap(); // 物料SAP->ID Map<String, String> sapToMaterialIdMap = loadSapToMaterialIdMap();
Map<String, String> locationNameToIdMap = loadLocationNameToIdMap(); // 库位名称->ID Map<String, String> locationNameToIdMap = loadLocationNameToIdMap();
Map<String, String> warehouseNameToIdMap = loadWarehouseNameToIdMap(); // 仓库名称->ID Map<String, String> warehouseNameToIdMap = loadWarehouseNameToIdMap();
Map<String, String> ownerNameToIdMap = loadOwnerNameToIdMap(); // 货主名称->ID Map<String, String> ownerNameToIdMap = loadOwnerNameToIdMap();
Map<String, AbstractMap.SimpleEntry<String, Long>> inventoryTOIdMap = loadInventoryTOIdMap();
// 3. 按入库单号分组(保留原有逻辑) // 4. 按入库单号分组
Map<String, List<OutboundTemplateVO>> orderGroupMap = inboundOrdersList.stream() Map<String, List<OutboundTemplateVO>> orderGroupMap = inboundOrdersList.stream()
.filter(vo -> StringUtils.isNotBlank(vo.getOrderId())) .filter(vo -> StringUtils.isNotBlank(vo.getOrderId()))
.collect(Collectors.groupingBy(OutboundTemplateVO::getOrderId)); .collect(Collectors.groupingBy(OutboundTemplateVO::getOrderId));
// 4. 第一步:仅验证所有数据(替换为预加载映射校验) // 5. 数据验证
for (Map.Entry<String, List<OutboundTemplateVO>> entry : orderGroupMap.entrySet()) { for (Map.Entry<String, List<OutboundTemplateVO>> entry : orderGroupMap.entrySet()) {
String orderId = entry.getKey(); String orderId = entry.getKey();
List<OutboundTemplateVO> voList = entry.getValue(); List<OutboundTemplateVO> voList = entry.getValue();
...@@ -294,8 +413,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService ...@@ -294,8 +413,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
try { try {
OutboundTemplateVO firstVO = voList.get(0); OutboundTemplateVO firstVO = voList.get(0);
// 检查出库单是否已存在
// 检查出库单是否已存在(保留原有逻辑)
OutboundOrders outboundOrdersQuery = new OutboundOrders(); OutboundOrders outboundOrdersQuery = new OutboundOrders();
outboundOrdersQuery.setOrderId(orderId); outboundOrdersQuery.setOrderId(orderId);
List<OutboundOrders> existMains = outboundOrdersMapper.selectOutboundOrdersList(outboundOrdersQuery); List<OutboundOrders> existMains = outboundOrdersMapper.selectOutboundOrdersList(outboundOrdersQuery);
...@@ -309,38 +427,33 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService ...@@ -309,38 +427,33 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
if (!Boolean.TRUE.equals(isUpdateSupport)) { if (!Boolean.TRUE.equals(isUpdateSupport)) {
throw new ServiceException(String.format("入库单号【%s】已存在,且不支持更新", orderId)); throw new ServiceException(String.format("入库单号【%s】已存在,且不支持更新", orderId));
} }
// 复用已有主表ID(保留原有逻辑)
mainDO = existMain; mainDO = existMain;
BeanUtils.copyProperties(firstVO, mainDO, "id", "createBy", "createTime"); BeanUtils.copyProperties(firstVO, mainDO, "id", "createBy", "createTime");
mainDO.setUpdateBy(operId); mainDO.setUpdateBy(operId);
mainDO.setWarehouseId("572ba484-199c-45d9-9735-610928ed5c70"); mainDO.setWarehouseId(WarehouseConfig.DEFAULT_WAREHOUSE_ID);
mainDO.setUpdateTime(now); mainDO.setUpdateTime(now);
mainDO.setUpdateUserCode(operId); mainDO.setUpdateUserCode(operId);
} else { } else {
// 新增主表(保留原有结构,替换货主校验为预加载映射)
mainDO = new OutboundOrders(); mainDO = new OutboundOrders();
BeanUtils.copyProperties(firstVO, mainDO, BeanUtils.copyProperties(firstVO, mainDO,
"sapNo", "materialName", "plannedQuantity", "actualQuantity", "sapNo", "materialName", "plannedQuantity", "actualQuantity",
"plannedPackages", "materialUnit", "materialRemark"); "plannedPackages", "materialUnit", "materialRemark");
// ========== 货主校验(替换为预加载映射) ========== // 货主校验
String ownerName = firstVO.getOwnerName(); String ownerName = firstVO.getOwnerName();
String ownerId = firstVO.getOwnerId(); String ownerId = firstVO.getOwnerId();
if (StringUtils.isNotBlank(ownerName)) { if (StringUtils.isNotBlank(ownerName)) {
// 从预加载映射获取货主ID,无需重复查询DB
String mappedOwnerId = ownerNameToIdMap.get(ownerName.trim()); String mappedOwnerId = ownerNameToIdMap.get(ownerName.trim());
if (StringUtils.isBlank(mappedOwnerId)) { if (StringUtils.isBlank(mappedOwnerId)) {
throw new ServiceException(String.format("业主【%s】不存在,无法新增入库单【%s】", throw new ServiceException(String.format("业主【%s】不存在,无法新增入库单【%s】",
ownerName, orderId)); ownerName, orderId));
} }
// 货主ID匹配校验
if (ownerId != null && !ownerId.equals(mappedOwnerId)) { if (ownerId != null && !ownerId.equals(mappedOwnerId)) {
throw new ServiceException(String.format("入库单号【%s】的业主ID【%s】与业主名称【%s】不匹配", throw new ServiceException(String.format("入库单号【%s】的业主ID【%s】与业主名称【%s】不匹配",
orderId, ownerId, ownerName)); orderId, ownerId, ownerName));
} }
mainDO.setOwnerId(mappedOwnerId); mainDO.setOwnerId(mappedOwnerId);
} else if (ownerId != null) { } else if (ownerId != null) {
// 仅货主ID校验(保留原有逻辑)
Owners ownerById = ownersService.selectOwnersById(ownerId); Owners ownerById = ownersService.selectOwnersById(ownerId);
if (ownerById == null) { if (ownerById == null) {
throw new ServiceException(String.format("入库单号【%s】的业主ID【%s】不存在", throw new ServiceException(String.format("入库单号【%s】的业主ID【%s】不存在",
...@@ -351,7 +464,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService ...@@ -351,7 +464,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
throw new ServiceException(String.format("入库单号【%s】的业主名称/ID不能为空", orderId)); throw new ServiceException(String.format("入库单号【%s】的业主名称/ID不能为空", orderId));
} }
// 填充主表必填字段(保留原有逻辑) // 填充主表必填字段
mainDO.setId(UUID.randomUUID().toString()); mainDO.setId(UUID.randomUUID().toString());
mainDO.setOrderId(orderId); mainDO.setOrderId(orderId);
mainDO.setOrderStatus(2L); mainDO.setOrderStatus(2L);
...@@ -365,7 +478,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService ...@@ -365,7 +478,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
mainDO.setSortNo(Optional.ofNullable(mainDO.getSortNo()).orElse(0L)); mainDO.setSortNo(Optional.ofNullable(mainDO.getSortNo()).orElse(0L));
} }
// ========== 明细校验(替换为预加载映射) ========== // 明细校验
for (int i = 0; i < voList.size(); i++) { for (int i = 0; i < voList.size(); i++) {
OutboundTemplateVO vo = voList.get(i); OutboundTemplateVO vo = voList.get(i);
int lineNo = i + 1; int lineNo = i + 1;
...@@ -374,7 +487,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService ...@@ -374,7 +487,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
BeanUtils.copyProperties(vo, itemDO, BeanUtils.copyProperties(vo, itemDO,
"orderId", "systemNo", "orderTypeId", "batchId"); "orderId", "systemNo", "orderTypeId", "batchId");
// 填充明细必填字段(保留原有逻辑) // 填充明细必填字段
itemDO.setId(UUID.randomUUID().toString()); itemDO.setId(UUID.randomUUID().toString());
itemDO.setOrderId(orderId); itemDO.setOrderId(orderId);
itemDO.setBatchCode(Optional.ofNullable(mainDO.getBatchCode()).orElse("")); itemDO.setBatchCode(Optional.ofNullable(mainDO.getBatchCode()).orElse(""));
...@@ -384,13 +497,12 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService ...@@ -384,13 +497,12 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
itemDO.setCreateUserCode(operId); itemDO.setCreateUserCode(operId);
itemDO.setSortNo(0L); itemDO.setSortNo(0L);
// ========== 物料SAP校验(替换为预加载映射) ========== // 物料SAP校验
String sapNo = vo.getSapNo() != null ? vo.getSapNo().trim() : ""; String sapNo = vo.getSapNo() != null ? vo.getSapNo().trim() : "";
if (StringUtils.isBlank(sapNo)) { if (StringUtils.isBlank(sapNo)) {
throw new ServiceException(String.format("入库单号【%s】第%d条明细的物料SAP号不能为空", throw new ServiceException(String.format("入库单号【%s】第%d条明细的物料SAP号不能为空",
orderId, lineNo)); orderId, lineNo));
} }
// 从预加载映射获取物料ID,无需重复查询DB
String materialId = sapToMaterialIdMap.get(sapNo); String materialId = sapToMaterialIdMap.get(sapNo);
if (StringUtils.isBlank(materialId)) { if (StringUtils.isBlank(materialId)) {
throw new ServiceException(String.format("入库单号【%s】第%d条明细的SAP号【%s】对应的物料不存在", throw new ServiceException(String.format("入库单号【%s】第%d条明细的SAP号【%s】对应的物料不存在",
...@@ -398,13 +510,12 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService ...@@ -398,13 +510,12 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
} }
itemDO.setMaterialId(materialId); itemDO.setMaterialId(materialId);
// ========== 库位校验(替换为预加载映射) ========== // 库位校验
String locationName = vo.getLocationName() != null ? vo.getLocationName().trim() : ""; String locationName = vo.getLocationName() != null ? vo.getLocationName().trim() : "";
if (StringUtils.isBlank(locationName)) { if (StringUtils.isBlank(locationName)) {
throw new ServiceException(String.format("入库单号【%s】第%d条明细的库位名称不能为空", throw new ServiceException(String.format("入库单号【%s】第%d条明细的库位名称不能为空",
orderId, lineNo)); orderId, lineNo));
} }
// 从预加载映射获取库位ID,无需重复查询DB
String locationId = locationNameToIdMap.get(locationName); String locationId = locationNameToIdMap.get(locationName);
if (StringUtils.isBlank(locationId)) { if (StringUtils.isBlank(locationId)) {
throw new ServiceException(String.format("入库单号【%s】第%d条明细的库位【%s】不存在", throw new ServiceException(String.format("入库单号【%s】第%d条明细的库位【%s】不存在",
...@@ -412,7 +523,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService ...@@ -412,7 +523,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
} }
itemDO.setLocationId(locationId); itemDO.setLocationId(locationId);
// ========== 仓库校验(替换为预加载映射) ========== // 仓库校验
String warehouseName = vo.getWarehouseName() != null ? vo.getWarehouseName().trim() : ""; String warehouseName = vo.getWarehouseName() != null ? vo.getWarehouseName().trim() : "";
String warehouseId = warehouseNameToIdMap.get(warehouseName); String warehouseId = warehouseNameToIdMap.get(warehouseName);
if (StringUtils.isBlank(warehouseId)) { if (StringUtils.isBlank(warehouseId)) {
...@@ -421,20 +532,17 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService ...@@ -421,20 +532,17 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
} }
itemDO.setWarehouseId(warehouseId); itemDO.setWarehouseId(warehouseId);
// ========== 库存校验(保留原有逻辑,使用预加载的ID) ========== // 库存校验(包含inventoryType)
Inventory itemsList = new Inventory(); String inventoryTypeStr = Optional.ofNullable(orderType).map(String::valueOf).orElse("");
itemsList.setWarehousesId(itemDO.getWarehouseId()); String inventoryMatchKey = String.join("_", warehouseId, materialId, locationId, inventoryTypeStr);
itemsList.setMaterialId(itemDO.getMaterialId()); AbstractMap.SimpleEntry<String, Long> inventoryEntry = inventoryTOIdMap.get(inventoryMatchKey);
itemsList.setLocationId(itemDO.getLocationId()); if (inventoryEntry == null) {
itemsList.setInventoryType(Long.valueOf(orderType));
List<Inventory> inventory = inventoryService.selectInventoryList(itemsList);
if (CollectionUtils.isEmpty(inventory)) {
throw new ServiceException(String.format( throw new ServiceException(String.format(
"入库单号【%s】第%d条明细:仓库【%s】+物料【%s】+库位【%s】组合的库存记录不存在", "入库单号【%s】第%d条明细:仓库【%s】+物料【%s】+库位【%s】+库存类型【%s】组合的库存记录不存在",
orderId, lineNo, vo.getWarehouseName(), vo.getMaterialName(), vo.getLocationName())); orderId, lineNo, vo.getWarehouseName(), vo.getMaterialName(), vo.getLocationName(), inventoryTypeStr));
} }
itemDO.setInventoryId(inventory.get(0).getId()); itemDO.setInventoryId(inventoryEntry.getKey());
itemDO.setInventoryType(inventoryTypeStr); // 填充库存类型
itemDO.setItemStatus(3L); itemDO.setItemStatus(3L);
itemDOList.add(itemDO); itemDOList.add(itemDO);
} }
...@@ -450,26 +558,21 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService ...@@ -450,26 +558,21 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
} }
} }
// 5. 有验证失败直接抛异常(保留原有逻辑) // 6. 有验证失败直接抛异常
if (hasValidateError) { if (hasValidateError) {
throw new ServiceException(String.format("验证失败,导入终止!失败详情:%s", failureMsg.toString())); throw new ServiceException(String.format("验证失败,导入终止!失败详情:%s", failureMsg.toString()));
} }
// 6. 验证全通过:统一执行入库/更新操作(保留原有逻辑) // 7. 执行入库/更新操作
for (Map.Entry<String, OutboundOrders> entry : validMainMap.entrySet()) { for (Map.Entry<String, OutboundOrders> entry : validMainMap.entrySet()) {
String orderId = entry.getKey(); String orderId = entry.getKey();
OutboundOrders mainDO = entry.getValue(); OutboundOrders mainDO = entry.getValue();
List<OutboundOrderItems> itemDOList = validItemMap.get(orderId); List<OutboundOrderItems> itemDOList = validItemMap.get(orderId);
if (mainDO != null) {
outboundOrdersMapper.insertOutboundOrders(mainDO); outboundOrdersMapper.insertOutboundOrders(mainDO);
totalMainSuccess++; totalMainSuccess++;
successMsg.append(String.format("入库单号【%s】已新增;\n", orderId)); successMsg.append(String.format("入库单号【%s】已新增;\n", orderId));
} else {
outboundOrdersMapper.updateOutboundOrders(mainDO);
totalMainSuccess++;
successMsg.append(String.format("入库单号【%s】已更新;\n", orderId));
}
if (!CollectionUtils.isEmpty(itemDOList)) { if (!CollectionUtils.isEmpty(itemDOList)) {
int itemSuccess = outboundOrderItemsMapper.batchInsertOutboundOrderItems(itemDOList); int itemSuccess = outboundOrderItemsMapper.batchInsertOutboundOrderItems(itemDOList);
...@@ -484,9 +587,8 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService ...@@ -484,9 +587,8 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
} }
} }
// 事务提交后执行自定义逻辑(保留原有逻辑) // 8. 事务提交后执行库存扣减
if (TransactionSynchronizationManager.isSynchronizationActive()) { if (TransactionSynchronizationManager.isSynchronizationActive()) {
Map<String, OutboundOrders> finalValidMainMap = new HashMap<>(validMainMap);
Map<String, List<OutboundOrderItems>> finalValidItemMap = new HashMap<>(validItemMap); Map<String, List<OutboundOrderItems>> finalValidItemMap = new HashMap<>(validItemMap);
String finalOperId = operId; String finalOperId = operId;
Date finalNow = now; Date finalNow = now;
...@@ -494,14 +596,18 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService ...@@ -494,14 +596,18 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
@Override @Override
public void afterCommit() { public void afterCommit() {
executeCustomLogic(finalValidMainMap, finalValidItemMap, finalOperId, finalNow); for (List<OutboundOrderItems> itemList : finalValidItemMap.values()) {
deductInventory(itemList, finalOperId, finalNow);
}
} }
}); });
} else { } else {
executeCustomLogic(validMainMap, validItemMap, operId, now); for (List<OutboundOrderItems> itemList : validItemMap.values()) {
deductInventory(itemList, operId, now);
}
} }
// 8. 结果汇总(保留原有逻辑) // 9. 结果汇总
if (totalMainFailure > 0 || totalItemFailure > 0) { if (totalMainFailure > 0 || totalItemFailure > 0) {
String finalFailureMsg = String.format( String finalFailureMsg = String.format(
"导入结果:成功新增/更新%d个入库单,失败%d个;成功导入%d条明细,失败%d条。失败详情:%s", "导入结果:成功新增/更新%d个入库单,失败%d个;成功导入%d条明细,失败%d条。失败详情:%s",
...@@ -517,10 +623,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService ...@@ -517,10 +623,7 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
} }
} }
// ========== 新增:预加载映射辅助方法(核心) ========== // ========== 预加载映射辅助方法 ==========
/**
* 预加载物料SAP号 -> 物料ID映射
*/
private Map<String, String> loadSapToMaterialIdMap() { private Map<String, String> loadSapToMaterialIdMap() {
List<Materials> materialsList = materialsService.selectMaterialsList(new Materials()); List<Materials> materialsList = materialsService.selectMaterialsList(new Materials());
if (CollectionUtils.isEmpty(materialsList)) { if (CollectionUtils.isEmpty(materialsList)) {
...@@ -529,18 +632,15 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService ...@@ -529,18 +632,15 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
return materialsList.stream() return materialsList.stream()
.filter(m -> StringUtils.isNotBlank(m.getSapNo())) .filter(m -> StringUtils.isNotBlank(m.getSapNo()))
.collect(Collectors.toMap( .collect(Collectors.toMap(
m -> m.getSapNo().trim(), // key:SAP号(去空格) m -> m.getSapNo().trim(),
Materials::getId, // value:物料ID Materials::getId,
(k1, k2) -> k1 // 重复SAP号保留第一个 (k1, k2) -> k1
)); ));
} }
/**
* 预加载库位名称(locationCode) -> 库位ID映射
*/
private Map<String, String> loadLocationNameToIdMap() { private Map<String, String> loadLocationNameToIdMap() {
StorageLocations query = new StorageLocations(); StorageLocations query = new StorageLocations();
query.setIsUsed(1L); // 只查可用库位 query.setIsUsed(1L);
List<StorageLocations> locationList = storageLocationsService.selectStorageLocationsList(query); List<StorageLocations> locationList = storageLocationsService.selectStorageLocationsList(query);
if (CollectionUtils.isEmpty(locationList)) { if (CollectionUtils.isEmpty(locationList)) {
return Collections.emptyMap(); return Collections.emptyMap();
...@@ -548,18 +648,15 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService ...@@ -548,18 +648,15 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
return locationList.stream() return locationList.stream()
.filter(l -> StringUtils.isNotBlank(l.getLocationCode())) .filter(l -> StringUtils.isNotBlank(l.getLocationCode()))
.collect(Collectors.toMap( .collect(Collectors.toMap(
l -> l.getLocationCode().trim(), // key:库位名称(去空格) l -> l.getLocationCode().trim(),
StorageLocations::getId, // value:库位ID StorageLocations::getId,
(k1, k2) -> k1 // 重复库位名称保留第一个 (k1, k2) -> k1
)); ));
} }
/**
* 预加载仓库名称 -> 仓库ID映射
*/
private Map<String, String> loadWarehouseNameToIdMap() { private Map<String, String> loadWarehouseNameToIdMap() {
Warehouses query = new Warehouses(); Warehouses query = new Warehouses();
query.setIsUsed(1L); // 只查可用仓库 query.setIsUsed(1L);
List<Warehouses> warehouseList = warehousesService.selectWarehousesList(query); List<Warehouses> warehouseList = warehousesService.selectWarehousesList(query);
if (CollectionUtils.isEmpty(warehouseList)) { if (CollectionUtils.isEmpty(warehouseList)) {
return Collections.emptyMap(); return Collections.emptyMap();
...@@ -567,15 +664,12 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService ...@@ -567,15 +664,12 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
return warehouseList.stream() return warehouseList.stream()
.filter(w -> StringUtils.isNotBlank(w.getWarehousesName())) .filter(w -> StringUtils.isNotBlank(w.getWarehousesName()))
.collect(Collectors.toMap( .collect(Collectors.toMap(
w -> w.getWarehousesName().trim(), // key:仓库名称(去空格) w -> w.getWarehousesName().trim(),
Warehouses::getId, // value:仓库ID Warehouses::getId,
(k1, k2) -> k1 // 重复仓库名称保留第一个 (k1, k2) -> k1
)); ));
} }
/**
* 预加载货主名称 -> 货主ID映射
*/
private Map<String, String> loadOwnerNameToIdMap() { private Map<String, String> loadOwnerNameToIdMap() {
List<Owners> ownerList = ownersService.selectOwnersList(new Owners()); List<Owners> ownerList = ownersService.selectOwnersList(new Owners());
if (CollectionUtils.isEmpty(ownerList)) { if (CollectionUtils.isEmpty(ownerList)) {
...@@ -584,96 +678,56 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService ...@@ -584,96 +678,56 @@ public class OutboundOrdersServiceImpl implements IOutboundOrdersService
return ownerList.stream() return ownerList.stream()
.filter(o -> StringUtils.isNotBlank(o.getOwnerName())) .filter(o -> StringUtils.isNotBlank(o.getOwnerName()))
.collect(Collectors.toMap( .collect(Collectors.toMap(
o -> o.getOwnerName().trim(), // key:货主名称(去空格) o -> o.getOwnerName().trim(),
Owners::getId, // value:货主ID Owners::getId,
(k1, k2) -> k1 // 重复货主名称保留第一个 (k1, k2) -> k1
)); ));
} }
private Map<String, String> loadInventoryTOIdMap() {
private Map<String, AbstractMap.SimpleEntry<String, Long>> loadInventoryTOIdMap() {
Inventory inventory = new Inventory(); Inventory inventory = new Inventory();
inventory.setInventoryStatus(1l); inventory.setInventoryStatus(1L);
inventory.setIsUsed(1l); inventory.setIsUsed(1L);
List<Inventory> inventoryList = inventoryService.selectInventoryList(inventory); List<Inventory> inventoryList = inventoryService.selectInventoryList(inventory);
if (CollectionUtils.isEmpty(inventoryList)) { if (CollectionUtils.isEmpty(inventoryList)) {
return Collections.emptyMap(); return Collections.emptyMap();
} }
return inventoryList.stream()
.filter(inv -> { Map<String, AbstractMap.SimpleEntry<String, Long>> emptyLocationMap = inventoryList.stream()
// 过滤有效库存:仓库/物料/库位/库存ID都不能为空 .filter(inv -> StringUtils.isNotBlank(inv.getWarehousesId())
return StringUtils.isNotBlank(inv.getWarehousesId()); && StringUtils.isNotBlank(inv.getMaterialId())
}) && inv.getInventoryType() != null
&& StringUtils.isNotBlank(inv.getId())
&& StringUtils.isBlank(inv.getLocationId()))
.collect(Collectors.toMap( .collect(Collectors.toMap(
// Key:仓库ID+物料ID+库位ID(拼接成唯一标识)
inv -> String.join("_", inv -> String.join("_",
inv.getWarehousesId().trim(), inv.getWarehousesId().trim(),
inv.getMaterialId().trim(), inv.getMaterialId().trim(),
inv.getLocationId().trim() "", inv.getInventoryType().toString()),
), inv -> new AbstractMap.SimpleEntry<>(inv.getId().trim(), Optional.ofNullable(inv.getQuantity()).orElse(0L)),
// Value:库存ID(去空格)
inv -> inv.getId().trim(),
// 重复Key处理:保留第一个(避免主键冲突)
(k1, k2) -> k1, (k1, k2) -> k1,
// 指定Map类型(可选,默认HashMap)
HashMap::new HashMap::new
)); ));
}
// 仅修改这个方法中【设置日志ID】的一行代码,其余完全保留
private void executeCustomLogic(Map<String, OutboundOrders> validMainMap,
Map<String, List<OutboundOrderItems>> validItemMap,
String operId, Date now) {
for (String orderId : validMainMap.keySet()) {
OutboundOrders mainDO = validMainMap.get(orderId);
List<OutboundOrderItems> itemList = validItemMap.get(orderId);
System.out.println(String.format("订单【%s】导入成功,主表ID:%s,明细数:%d",
orderId, mainDO.getId(), itemList.size()));
List<OutboundOrderLog> outboundOrderLogs = new ArrayList<>(); Map<String, AbstractMap.SimpleEntry<String, Long>> nonEmptyLocationMap = inventoryList.stream()
for (OutboundOrderItems item : itemList) { .filter(inv -> StringUtils.isNotBlank(inv.getWarehousesId())
OutboundOrderLog outboundOrderLog = new OutboundOrderLog(); && StringUtils.isNotBlank(inv.getMaterialId())
// ========== 唯一改动:设置日志ID = 明细ID ========== && StringUtils.isNotBlank(inv.getLocationId())
outboundOrderLog.setId(item.getId()); && StringUtils.isNotBlank(inv.getId())
outboundOrderLog.setOrderId(item.getOutboundOrderId()); && inv.getInventoryType() != null)
BeanUtils.copyProperties(item, outboundOrderLog); .collect(Collectors.toMap(
outboundOrderLogs.add(outboundOrderLog); inv -> String.join("_",
} inv.getWarehousesId().trim(),
inv.getMaterialId().trim(),
outboundOrderLogMapper.batchOutboundOrderLog(outboundOrderLogs); inv.getLocationId().trim(),
ship(itemList); inv.getInventoryType().toString()),
} inv -> new AbstractMap.SimpleEntry<>(inv.getId().trim(), Optional.ofNullable(inv.getQuantity()).orElse(0L)),
} (k1, k2) -> k1,
HashMap::new
));
public int ship(List<OutboundOrderItems> outboundOrderItems)
{
if (!outboundOrderItems.isEmpty()) {
List<String> inventoryIds = new ArrayList<>(); // 手动收集inventoryId
for (OutboundOrderItems outboundOrderItem : outboundOrderItems) {
// 直接用明细的inventoryId,不查日志!
String inventoryId = outboundOrderItem.getInventoryId();
if (StringUtils.isBlank(inventoryId)) {
throw new ServiceException("明细ID【" + outboundOrderItem.getId() + "】的库存ID为空,无法扣减");
}
Inventory inventory = inventoryService.selectInventoryById(inventoryId);
if (inventory == null) {
throw new ServiceException("库存ID【" + inventoryId + "】不存在,无法扣减");
}
// 扣减库存
inventory.setQuantity(inventory.getQuantity() - outboundOrderItem.getActualQuantity());
if (inventory.getQuantity() == 0) {
inventory.setInventoryStatus(0L);
}
inventoryService.updateInventory(inventory);
inventoryIds.add(inventoryId); // 收集库存ID用于刷新 emptyLocationMap.putAll(nonEmptyLocationMap);
} return emptyLocationMap;
inventoryService.RefreshInventory(inventoryIds);
}
return 1;
} }
} }
\ No newline at end of file
...@@ -344,4 +344,15 @@ ...@@ -344,4 +344,15 @@
select count(*) from outbound_orders where is_used = 1 and order_status=2 and inbound_date &gt;= DATE_FORMAT(CURDATE(), '%Y-%m-01') select count(*) from outbound_orders where is_used = 1 and order_status=2 and inbound_date &gt;= DATE_FORMAT(CURDATE(), '%Y-%m-01')
and inbound_date &lt; DATE_FORMAT(DATE_ADD(CURDATE(), INTERVAL 1 MONTH), '%Y-%m-01') and inbound_date &lt; DATE_FORMAT(DATE_ADD(CURDATE(), INTERVAL 1 MONTH), '%Y-%m-01')
</select> </select>
<update id="batchUpdateInventory">
<foreach collection="list" item="item" separator=";">
UPDATE inventory
SET quantity = #{item.quantity},
inventory_status = #{item.inventoryStatus},
update_by = #{item.updateBy},
update_time = #{item.updateTime}
WHERE id = #{item.id}
</foreach>
</update>
</mapper> </mapper>
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论