From bb7dd1f513149ecd2887895c807861fdd06a43f6 Mon Sep 17 00:00:00 2001
From: chen.lin <1442464845@qq.com>
Date: 星期三, 11 二月 2026 15:29:27 +0800
Subject: [PATCH] 展示库存明细
---
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java | 175 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 173 insertions(+), 2 deletions(-)
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java
index 3b301d7..a42985b 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java
@@ -8,12 +8,16 @@
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.api.utils.LocUtils;
import com.vincent.rsf.server.common.constant.Constants;
+import com.vincent.rsf.server.common.domain.BaseParam;
+import com.vincent.rsf.server.common.domain.PageParam;
import com.vincent.rsf.server.manager.controller.dto.ExistDto;
import com.vincent.rsf.server.manager.controller.dto.OrderOutItemDto;
import com.vincent.rsf.server.manager.controller.params.*;
import com.vincent.rsf.server.manager.enums.*;
+import com.vincent.rsf.server.manager.entity.Matnr;
import com.vincent.rsf.server.manager.entity.*;
import com.vincent.rsf.server.manager.mapper.AsnOrderMapper;
+import com.vincent.rsf.server.manager.mapper.LocItemMapper;
import com.vincent.rsf.server.manager.service.*;
import com.vincent.rsf.server.manager.utils.LocManageUtil;
import com.vincent.rsf.server.manager.utils.OptimalAlgorithmUtil;
@@ -81,7 +85,73 @@
private LocService locService;
@Autowired
private WaveOrderRelaServiceImpl waveOrderRelaService;
+ @Autowired
+ private TaskItemService taskItemService;
+ @Autowired
+ private LocItemMapper locItemMapper;
+ @Override
+ public PageParam<Matnr, BaseParam> pageMatnrForOutStock(PageParam<Matnr, BaseParam> pageParam, Map<String, Object> params) {
+ PageParam<Matnr, BaseParam> page = matnrService.getMatnrPage(pageParam, params);
+ List<Matnr> records = page.getRecords();
+ if (records == null || records.isEmpty()) {
+ return page;
+ }
+ List<Long> matnrIds = records.stream().map(Matnr::getId).collect(Collectors.toList());
+ String locUseStatus = params.get("locUseStatus") != null ? params.get("locUseStatus").toString() : null;
+ List<Map<String, Object>> stockList = locItemMapper.listStockByMatnrIds(matnrIds, locUseStatus);
+ Map<Long, Double> stockQtyMap = new HashMap<>();
+ Map<Long, String> locStatusDescMap = new HashMap<>();
+ Map<Long, String> locCodesMap = new HashMap<>();
+ for (Map<String, Object> row : stockList) {
+ Long matnrId = getLong(row, "matnrId", "matnrid");
+ if (matnrId == null) continue;
+ Object qty = getAny(row, "stockQty", "stockqty");
+ double v = qty instanceof Number ? ((Number) qty).doubleValue() : 0d;
+ stockQtyMap.put(matnrId, v);
+ String locCodes = getStr(row, "locCodes", "loccodes");
+ if (locCodes != null && !locCodes.isEmpty()) {
+ locCodesMap.put(matnrId, locCodes);
+ }
+ String locStatuses = getStr(row, "locStatuses", "locstatuses");
+ if (locStatuses != null && !locStatuses.isEmpty()) {
+ String desc = Arrays.stream(locStatuses.split(","))
+ .map(String::trim)
+ .map(LocStsType::getDescByType)
+ .collect(Collectors.joining(","));
+ locStatusDescMap.put(matnrId, desc);
+ } else if (locUseStatus != null && !locUseStatus.isEmpty()) {
+ locStatusDescMap.put(matnrId, LocStsType.getDescByType(locUseStatus));
+ }
+ }
+ for (Matnr record : records) {
+ record.setStockQty(stockQtyMap.getOrDefault(record.getId(), 0d));
+ record.setLocUseStatus$(locStatusDescMap.get(record.getId()));
+ record.setLocCodes$(locCodesMap.get(record.getId()));
+ }
+ return page;
+ }
+
+ private static Long getLong(Map<String, Object> map, String... keys) {
+ Object v = getAny(map, keys);
+ if (v == null) return null;
+ if (v instanceof Long) return (Long) v;
+ if (v instanceof Number) return ((Number) v).longValue();
+ try { return Long.parseLong(v.toString()); } catch (NumberFormatException e) { return null; }
+ }
+
+ private static String getStr(Map<String, Object> map, String... keys) {
+ Object v = getAny(map, keys);
+ return v != null ? v.toString() : null;
+ }
+
+ private static Object getAny(Map<String, Object> map, String... keys) {
+ for (String key : keys) {
+ Object v = map.get(key);
+ if (v != null) return v;
+ }
+ return null;
+ }
/**
* @param
@@ -419,6 +489,7 @@
* @time 2025/4/29 13:47
*/
@Override
+ @Transactional(rollbackFor = Exception.class)
public R updateOrderItem(AsnOrderAndItemsParams params, Long loginUserId) {
WkOrder orders = params.getOrders();
if (Objects.isNull(orders)) {
@@ -433,12 +504,102 @@
if (Objects.isNull(params.getItems()) || params.getItems().isEmpty()) {
throw new CoolException("鏄庣粏鍙傛暟涓嶈兘涓虹┖锛侊紒");
}
+ // 鍒犻櫎/淇敼鏄庣粏鍓嶆敹闆嗗綋鍓嶅崟鎹笅鐨勬槑缁� id锛岀敤浜庢牎楠屼笌鍚屾搴撲綅鐘舵��
+ List<Long> existingIds = asnOrderItemService.list(
+ new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, orders.getId()))
+ .stream().map(WkOrderItem::getId).collect(Collectors.toList());
+ Set<Long> requestedIds = params.getItems().stream()
+ .map(item -> item.get("id"))
+ .filter(Objects::nonNull)
+ .map(id -> Long.valueOf(id.toString()))
+ .collect(Collectors.toSet());
+ // 宸茬敓鎴愬伐浣滄。鐨勬槑缁嗕笉鍏佽鍒犻櫎
+ for (Long existingId : existingIds) {
+ if (!requestedIds.contains(existingId) && hasGeneratedTask(orders.getId(), existingId)) {
+ throw new CoolException("璇ユ槑缁嗗凡鐢熸垚宸ヤ綔妗o紝涓嶈兘鍒犻櫎");
+ }
+ }
+ // 宸茬敓鎴愬伐浣滄。鐨勬槑缁嗕笉鍏佽淇敼
+ for (Map<String, Object> item : params.getItems()) {
+ Object idObj = item.get("id");
+ if (idObj != null && hasGeneratedTask(orders.getId(), Long.valueOf(idObj.toString()))) {
+ throw new CoolException("璇ユ槑缁嗗凡鐢熸垚宸ヤ綔妗o紝涓嶈兘淇敼");
+ }
+ }
try {
svaeOrUpdateOrderItem(params, loginUserId);
} catch (Exception e) {
throw new CoolException(e.getMessage());
}
+ // 瀵规湰娆¤鍒犻櫎鐨勬槑缁嗭紙浠呭垵濮嬪寲鐘舵�侊級锛氬厛鍚屾搴撲綅鐘舵�侊紝鍐嶅垹闄ゆ槑缁嗚褰�
+ for (Long existingId : existingIds) {
+ if (!requestedIds.contains(existingId)) {
+ syncLocStatusOnOrderItemRemoved(orders.getId(), existingId, loginUserId);
+ outStockItemService.removeById(existingId);
+ }
+ }
+ // 閲嶆柊姹囨�讳富鍗曟暟閲忥紙鍒犻櫎鏄庣粏鍚庯級
+ List<WkOrderItem> afterItems = asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>()
+ .eq(WkOrderItem::getOrderId, orders.getId()));
+ Double sum = afterItems.stream().mapToDouble(WkOrderItem::getAnfme).sum();
+ orders.setAnfme(sum);
+ this.updateById(orders);
return R.ok();
+ }
+
+ /**
+ * 鍒ゆ柇鍑哄簱鍗曟槑缁嗘槸鍚﹀凡鐢熸垚宸ヤ綔妗o紙瀛樺湪鍏宠仈鐨勪换鍔℃槑缁嗭級
+ */
+ private boolean hasGeneratedTask(Long orderId, Long orderItemId) {
+ return taskItemService.count(new LambdaQueryWrapper<TaskItem>()
+ .eq(TaskItem::getSourceId, orderId)
+ .eq(TaskItem::getOrderItemId, orderItemId)) > 0;
+ }
+
+ /**
+ * 鍑哄簱鍗曟槑缁嗚鍒犻櫎鏃跺悓姝ュ簱浣嶇姸鎬侊細閲婃斁璇ユ槑缁嗗叧鑱旂殑搴撲綅棰勭害銆佸洖婊� LocItem.workQty銆佹仮澶嶅簱浣嶄负鍦ㄥ簱(F)
+ */
+ private void syncLocStatusOnOrderItemRemoved(Long orderId, Long orderItemId, Long loginUserId) {
+ List<TaskItem> taskItems = taskItemService.list(new LambdaQueryWrapper<TaskItem>()
+ .eq(TaskItem::getSourceId, orderId)
+ .eq(TaskItem::getOrderItemId, orderItemId));
+ if (taskItems.isEmpty()) {
+ return;
+ }
+ Set<Long> affectedLocIds = new HashSet<>();
+ Date now = new Date();
+ for (TaskItem taskItem : taskItems) {
+ if (taskItem.getSource() == null) {
+ continue;
+ }
+ LocItem locItem = locItemService.getById(taskItem.getSource());
+ if (locItem == null) {
+ continue;
+ }
+ Double anfme = taskItem.getAnfme() != null ? taskItem.getAnfme() : 0.0;
+ Double newWorkQty = Math.round((locItem.getWorkQty() - anfme) * 1000000) / 1000000.0;
+ locItem.setWorkQty(newWorkQty >= 0 ? newWorkQty : 0)
+ .setOrderId(null)
+ .setOrderItemId(null)
+ .setUpdateBy(loginUserId)
+ .setUpdateTime(now);
+ locItemService.updateById(locItem);
+ affectedLocIds.add(locItem.getLocId());
+ }
+ for (Long locId : affectedLocIds) {
+ long stillReserved = locItemService.count(new LambdaQueryWrapper<LocItem>()
+ .eq(LocItem::getLocId, locId)
+ .isNotNull(LocItem::getOrderId));
+ if (stillReserved == 0) {
+ Loc loc = locService.getById(locId);
+ if (loc != null && LocStsType.LOC_STS_TYPE_R.type.equals(loc.getUseStatus())) {
+ loc.setUseStatus(LocStsType.LOC_STS_TYPE_F.type)
+ .setUpdateBy(loginUserId)
+ .setUpdateTime(now);
+ locService.updateById(loc);
+ }
+ }
+ }
}
@Override
@@ -579,6 +740,8 @@
locItem.setOutQty(param.getOutQty())
.setBatch(param.getBatch())
+ .setOrderId(outId)
+ .setOrderItemId(orderItem.getId())
.setSourceId(outId)
.setSourceCode(orderItem.getOrderCode())
.setSource(orderItem.getId());
@@ -636,7 +799,12 @@
TaskType.TASK_TYPE_OUT.type,
TaskType.TASK_TYPE_MERGE_OUT.type,
TaskType.TASK_TYPE_PICK_AGAIN_OUT.type);
- List<DeviceSite> sites = deviceSiteService.list(new LambdaQueryWrapper<DeviceSite>().in(DeviceSite::getType, list).groupBy(DeviceSite::getSite));
+ // 鍏堟煡鍏ㄩ儴鍐嶆寜 site 鍘婚噸锛岄伩鍏� GROUP BY 涓� only_full_group_by 鍐茬獊
+ List<DeviceSite> all = deviceSiteService.list(new LambdaQueryWrapper<DeviceSite>().in(DeviceSite::getType, list));
+ List<DeviceSite> sites = all.stream()
+ .collect(Collectors.toMap(DeviceSite::getSite, d -> d, (a, b) -> a))
+ .values().stream()
+ .collect(Collectors.toList());
return R.ok(sites);
}
@@ -709,10 +877,13 @@
}
// 璇ュ簱浣嶅彲鍒嗛厤鏁伴噺锛氬彇鏈寰呭垎閰嶄笌搴撲綅搴撳瓨鐨勮緝灏忓��
double allocatable = Math.min(issued.doubleValue(), locItem.getAnfme() != null ? locItem.getAnfme() : 0);
+ // 褰撳垎閰嶉噺绛変簬搴撲綅搴撳瓨鏃讹紝浣跨敤搴撲綅搴撳瓨绮惧害浣滀负鍑哄簱鏁伴噺锛岄伩鍏嶆埅鏂鑷寸晫闈㈡樉绀�/搴撳瓨鏍¢獙涓嶄竴鑷达紙濡傚簱瀛�15.123457琚埅鎴�15.123锛�
+ double outQtyToSet = (locItem.getAnfme() != null && Math.abs(allocatable - locItem.getAnfme()) < 1e-6)
+ ? locItem.getAnfme() : allocatable;
ExistDto existDto = new ExistDto().setBatch(locItem.getBatch()).setMatnr(locItem.getMatnrCode()).setLocNo(locItem.getLocCode());
if (existDtos.add(existDto)) {
// 棣栨浣跨敤璇ュ簱浣嶏細鍔犲叆鍒楄〃骞舵墸鍑� issued
- locItem.setOutQty(allocatable);
+ locItem.setOutQty(outQtyToSet);
locItem.setBarcode(loc.getBarcode());
OrderOutItemDto orderOutItemDto = new OrderOutItemDto();
orderOutItemDto.setLocItem(locItem);
--
Gitblit v1.9.1