From 79ce234f181a8fa5e3e02938520395243c82a5da Mon Sep 17 00:00:00 2001
From: chen.lin <1442464845@qq.com>
Date: 星期五, 06 三月 2026 08:15:39 +0800
Subject: [PATCH] 拣货过程中的出库库存匹配+空板
---
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/OutStockServiceImpl.java | 547 +++++++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 471 insertions(+), 76 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 1852771..cc79c6d 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,17 +8,22 @@
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;
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 +33,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 +46,24 @@
* @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");
+ /** 鏁伴噺绮惧害锛堝皬鏁颁綅鏁帮級锛岀粺涓�鐢� BigDecimal 璁$畻鍚庢寜姝ょ簿搴﹁垗鍏ュ啀鍐欏洖 Double 瀛楁 */
+ private static final int QTY_SCALE = 6;
+
+ /** 灏� Map/瀹炰綋涓殑鏁伴噺杞负 BigDecimal锛岄伩鍏� double 绮惧害闂 */
+ private static BigDecimal toBigDecimal(Object o) {
+ if (o == null) return BigDecimal.ZERO;
+ if (o instanceof BigDecimal) return (BigDecimal) o;
+ if (o instanceof Number) return new BigDecimal(o.toString());
+ try { return new BigDecimal(o.toString()); } catch (NumberFormatException e) { return BigDecimal.ZERO; }
+ }
@Autowired
private AsnOrderItemService asnOrderItemService;
@@ -76,7 +95,128 @@
private LocService locService;
@Autowired
private WaveOrderRelaServiceImpl waveOrderRelaService;
+ @Autowired
+ private TaskItemService taskItemService;
+ @Autowired
+ private TaskService taskService;
+ @Autowired
+ private LocItemMapper locItemMapper;
+ @Override
+ public PageParam<Matnr, BaseParam> pageMatnrForOutStock(PageParam<Matnr, BaseParam> pageParam, Map<String, Object> params) {
+ // 鍦� getMatnrPage 涔嬪墠鍙栧嚭 locUseStatus锛歡etMatnrPage 浼氫粠 where.map 涓� remove 鎺夎閿紙涓� params 鍚屽紩鐢級锛屽鑷村悗缁彇涓嶅埌
+ String locUseStatus = params.get("locUseStatus") != null ? params.get("locUseStatus").toString().trim() : null;
+ if (locUseStatus != null && locUseStatus.isEmpty()) locUseStatus = null;
+
+ 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());
+ List<Map<String, Object>> stockByLocList = locItemMapper.listStockByMatnrIdsGroupByStatusAndLoc(matnrIds, locUseStatus);
+ Map<Long, List<Map<String, Object>>> rowsByMatnr = buildRowsByMatnrFromPerLoc(stockByLocList);
+ List<Matnr> expanded = new ArrayList<>();
+ for (Matnr record : records) {
+ List<Map<String, Object>> statusRows = rowsByMatnr.get(record.getId());
+ if (statusRows == null || statusRows.isEmpty()) {
+ record.setStockQty(0d);
+ record.setLocUseStatus$(null);
+ record.setLocCodes$(null);
+ expanded.add(record);
+ continue;
+ }
+ for (Map<String, Object> row : statusRows) {
+ BigDecimal stockQtyVal = toBigDecimal(row.get("stockQty"));
+ String useStatus = getStr(row, "useStatus", "usestatus");
+ String statusDesc = useStatus != null ? LocStsType.getDescByType(useStatus) : null;
+ String locCodesWithQty = getStr(row, "locCodes$", "loccodes$");
+ Matnr copy = cloneMatnrForRow(record);
+ copy.setStockQty(stockQtyVal.setScale(QTY_SCALE, RoundingMode.HALF_UP).doubleValue());
+ copy.setLocUseStatus$(statusDesc);
+ copy.setLocCodes$(locCodesWithQty);
+ expanded.add(copy);
+ }
+ }
+ page.setRecords(expanded);
+ return page;
+ }
+
+ /** 澶嶅埗鐗╂枡鐢ㄤ簬鎸夌姸鎬佸睍寮�琛岋紙浠呭鍒跺睍绀虹敤瀛楁锛宨d 淇濇寔鍘熸牱渚涘墠绔�夎鐢級 */
+ private static Matnr cloneMatnrForRow(Matnr source) {
+ Matnr copy = new Matnr();
+ BeanUtils.copyProperties(source, copy, "stockQty", "locUseStatus$", "locCodes$");
+ return copy;
+ }
+
+ /**
+ * 浠呯敤銆屾寜搴撲綅鏄庣粏銆嶆煡璇㈢粨鏋滃湪鍐呭瓨涓垎缁勬眹鎬伙細鎸� (matnrId, useStatus) 鑱氬悎锛�
+ * 寰楀埌 stockQty銆乴ocCodes$锛堝簱浣�(鏁伴噺),...锛夛紝鍑忚交鏁版嵁搴撳帇鍔涖��
+ */
+ private static Map<Long, List<Map<String, Object>>> buildRowsByMatnrFromPerLoc(List<Map<String, Object>> stockByLocList) {
+ Map<String, List<Map<String, Object>>> perLocByMatnrAndStatus = new HashMap<>();
+ for (Map<String, Object> locRow : stockByLocList) {
+ Long mid = getLong(locRow, "matnrId", "matnrid");
+ String us = getStr(locRow, "useStatus", "usestatus");
+ if (mid == null || us == null) continue;
+ String key = mid + ":" + us;
+ perLocByMatnrAndStatus.computeIfAbsent(key, k -> new ArrayList<>()).add(locRow);
+ }
+ Map<Long, List<Map<String, Object>>> rowsByMatnr = new HashMap<>();
+ for (Map.Entry<String, List<Map<String, Object>>> e : perLocByMatnrAndStatus.entrySet()) {
+ String[] parts = e.getKey().split(":", 2);
+ if (parts.length != 2) continue;
+ Long matnrId;
+ try { matnrId = Long.parseLong(parts[0]); } catch (NumberFormatException ex) { continue; }
+ String useStatus = parts[1];
+ List<Map<String, Object>> locs = e.getValue();
+ BigDecimal stockQty = BigDecimal.ZERO;
+ StringBuilder sb = new StringBuilder();
+ for (Map<String, Object> locRow : locs) {
+ Object q = getAny(locRow, "locQty", "locqty");
+ BigDecimal qty = toBigDecimal(q);
+ stockQty = stockQty.add(qty);
+ String code = getStr(locRow, "locCode", "loccode");
+ if (sb.length() > 0) sb.append(",");
+ sb.append(code != null ? code : "").append("(").append(formatQtyForLoc(qty)).append(")");
+ }
+ Map<String, Object> statusRow = new HashMap<>();
+ statusRow.put("matnrId", matnrId);
+ statusRow.put("useStatus", useStatus);
+ statusRow.put("stockQty", stockQty);
+ statusRow.put("locCodes$", sb.toString());
+ rowsByMatnr.computeIfAbsent(matnrId, k -> new ArrayList<>()).add(statusRow);
+ }
+ return rowsByMatnr;
+ }
+
+ private static String formatQtyForLoc(BigDecimal qty) {
+ if (qty == null) return "0";
+ BigDecimal scaled = qty.setScale(QTY_SCALE, RoundingMode.HALF_UP).stripTrailingZeros();
+ if (scaled.scale() <= 0) return scaled.toPlainString();
+ return scaled.toPlainString();
+ }
+
+ 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
@@ -100,8 +240,10 @@
});
List<WkOrderItem> orderItems = asnOrderItemService.list(new LambdaQueryWrapper<WkOrderItem>()
.eq(WkOrderItem::getOrderId, params.getOrders().getId()));
- Double sum = orderItems.stream().mapToDouble(WkOrderItem::getAnfme).sum();
- orders.setAnfme(sum);
+ BigDecimal sum = orderItems.stream()
+ .map(o -> toBigDecimal(o.getAnfme()))
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
+ orders.setAnfme(sum.setScale(QTY_SCALE, RoundingMode.HALF_UP).doubleValue());
if (!this.updateById(orders)) {
throw new CoolException("璁″垝鏀惰揣鏁伴噺淇敼澶辫触锛侊紒");
}
@@ -132,18 +274,18 @@
List<WkOrderItem> orderItems = outStockItemService.list(new LambdaQueryWrapper<WkOrderItem>().eq(WkOrderItem::getOrderId, id));
if (!orderItems.isEmpty()) {
for (WkOrderItem orderItem : orderItems) {
- if (!Objects.isNull(orderItem.getPoDetlId())) {
+ if (!Objects.isNull(orderItem.getPoDetlId())) {
DeliveryItem deliveryItem = deliveryItemService.getById(orderItem.getPoDetlId());
- Double workQty = Math.round((deliveryItem.getWorkQty() - orderItem.getAnfme()) * 1000000) / 1000000.0;
- deliveryItem.setWorkQty(workQty.compareTo(0.0) >= 0 ? workQty : 0);
+ BigDecimal workQty = toBigDecimal(deliveryItem.getWorkQty()).subtract(toBigDecimal(orderItem.getAnfme())).setScale(QTY_SCALE, RoundingMode.HALF_UP);
+ deliveryItem.setWorkQty(workQty.compareTo(BigDecimal.ZERO) >= 0 ? workQty.doubleValue() : 0);
if (!deliveryItemService.updateById(deliveryItem)) {
throw new CoolException("DO鍗曟槑缁嗘洿鏂板け璐ワ紒锛�");
}
Delivery delivery = deliveryService.getOne(new LambdaQueryWrapper<Delivery>().eq(Delivery::getCode, orderItem.getPoCode()));
if (!Objects.isNull(delivery)) {
- Double wkQty = Math.round((delivery.getWorkQty() - delivery.getAnfme()) * 1000000) / 1000000.0;
- delivery.setWorkQty(wkQty.compareTo(0.0) >= 0 ? wkQty : 0).setExceStatus(POExceStatus.PO_EXCE_STATUS_UN_EXCE.val);
+ BigDecimal wkQty = toBigDecimal(delivery.getWorkQty()).subtract(toBigDecimal(delivery.getAnfme())).setScale(QTY_SCALE, RoundingMode.HALF_UP);
+ delivery.setWorkQty(wkQty.compareTo(BigDecimal.ZERO) >= 0 ? wkQty.doubleValue() : 0).setExceStatus(POExceStatus.PO_EXCE_STATUS_UN_EXCE.val);
if (!deliveryService.updateById(delivery)) {
throw new CoolException("DO鍗曟嵁淇敼澶辫触锛侊紒");
}
@@ -206,8 +348,8 @@
if (item.getAnfme().compareTo(0.0) <= 0) {
throw new CoolException("鍑哄簱鏁伴噺涓嶈兘灏忎簬鎴栫瓑浜庨浂锛侊紒");
}
- Double anfme = Math.round((deliveryItem.getAnfme() - item.getAnfme()) * 1000000) / 1000000.0;
- if (anfme.compareTo(0.0) < 0) {
+ BigDecimal anfme = toBigDecimal(deliveryItem.getAnfme()).subtract(toBigDecimal(item.getAnfme())).setScale(QTY_SCALE, RoundingMode.HALF_UP);
+ if (anfme.compareTo(BigDecimal.ZERO) < 0) {
throw new CoolException("鍑哄簱鏁伴噺涓嶈冻锛侊紒");
}
@@ -239,9 +381,9 @@
}
});
- Double sum = orderItems.stream().mapToDouble(WkOrderItem::getAnfme).sum();
+ BigDecimal sum = orderItems.stream().map(o -> toBigDecimal(o.getAnfme())).reduce(BigDecimal.ZERO, BigDecimal::add);
//淇敼璁″垝鏁伴噺
- order.setAnfme(sum).setWorkQty(0.0);
+ order.setAnfme(sum.setScale(QTY_SCALE, RoundingMode.HALF_UP).doubleValue()).setWorkQty(0.0);
if (!this.saveOrUpdate(order)) {
throw new CoolException("涓诲崟鏁伴噺淇敼澶辫触锛侊紒");
}
@@ -254,10 +396,10 @@
exceStatus = AsnExceStatus.ASN_EXCE_STATUS_TASK_DONE.val;
}
- Double wkQty = Math.round((delivery.getWorkQty() + sum) * 1000000) / 1000000.0;
+ BigDecimal wkQty = toBigDecimal(delivery.getWorkQty()).add(sum).setScale(QTY_SCALE, RoundingMode.HALF_UP);
if (!deliveryService.update(new LambdaUpdateWrapper<Delivery>()
.set(Delivery::getExceStatus, exceStatus)
- .set(Delivery::getWorkQty, wkQty)
+ .set(Delivery::getWorkQty, wkQty.doubleValue())
.eq(Delivery::getId, key))) {
throw new CoolException("涓诲崟淇敼澶辫触锛侊紒");
}
@@ -284,9 +426,9 @@
if (orders.isEmpty()) {
throw new CoolException("褰撳墠鍗曟嵁鐘舵�佷笉鑳芥墽琛屾尝娆$敓鎴愭搷浣滐紒锛�");
}
- Double sum = orders.stream().mapToDouble(WkOrder::getAnfme).sum();
- Double workQty = orders.stream().mapToDouble(WkOrder::getWorkQty).sum();
- Double anfme = Math.round((sum - workQty) * 1000000) / 1000000.0;
+ BigDecimal sum = orders.stream().map(o -> toBigDecimal(o.getAnfme())).reduce(BigDecimal.ZERO, BigDecimal::add);
+ BigDecimal workQty = orders.stream().map(o -> toBigDecimal(o.getWorkQty())).reduce(BigDecimal.ZERO, BigDecimal::add);
+ BigDecimal anfme = sum.subtract(workQty).setScale(QTY_SCALE, RoundingMode.HALF_UP);
Wave wave = new Wave();
String ruleCode = SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_WAVE_TYPE, null);
if (StringUtils.isBlank(ruleCode)) {
@@ -296,7 +438,7 @@
.setType(Short.parseShort("1"))
.setCode(ruleCode)
.setExceStatus(WaveExceStatus.WAVE_EXCE_STATUS_INIT.val)
- .setAnfme(anfme);
+ .setAnfme(anfme.doubleValue());
if (!waveService.save(wave)) {
throw new CoolException("娉㈡淇濆瓨澶辫触锛侊紒");
}
@@ -315,8 +457,8 @@
if (!waveItemService.saveBatch(waveItems)) {
throw new CoolException("娉㈡鏄庣粏淇濆瓨澶辫触锛侊紒");
}
- double sum1 = waveItems.stream().mapToDouble(WaveItem::getAnfme).sum();
- wave.setAnfme(sum1).setGroupQty(waveItems.size());
+ BigDecimal sum1 = waveItems.stream().map(o -> toBigDecimal(o.getAnfme())).reduce(BigDecimal.ZERO, BigDecimal::add);
+ wave.setAnfme(sum1.setScale(QTY_SCALE, RoundingMode.HALF_UP).doubleValue()).setGroupQty(waveItems.size());
if (!waveService.saveOrUpdate(wave)) {
throw new CoolException("涓诲崟淇敼澶辫触锛侊紒");
}
@@ -351,10 +493,10 @@
throw new CoolException("鍑哄簱鍗曟墽琛屾暟閲忎慨鏀瑰け璐ワ紒锛�");
}
for (WkOrder order : orders) {
- Double wkQty = Math.round((order.getWorkQty() + order.getAnfme()) * 1000000) / 1000000.0;
+ BigDecimal wkQty = toBigDecimal(order.getWorkQty()).add(toBigDecimal(order.getAnfme())).setScale(QTY_SCALE, RoundingMode.HALF_UP);
if (!this.update(new LambdaUpdateWrapper<WkOrder>()
.set(WkOrder::getWaveId, wave.getId())
- .set(WkOrder::getWorkQty, wkQty)
+ .set(WkOrder::getWorkQty, wkQty.doubleValue())
.set(WkOrder::getExceStatus, AsnExceStatus.OUT_STOCK_STATUS_TASK_WAVE.val)
.eq(WkOrder::getId, order.getId()))) {
throw new CoolException("鎵ц鐘舵�佷慨鏀逛慨鏀瑰け璐ワ紒锛�");
@@ -414,6 +556,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)) {
@@ -428,12 +571,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()));
+ BigDecimal sum = afterItems.stream().map(o -> toBigDecimal(o.getAnfme())).reduce(BigDecimal.ZERO, BigDecimal::add);
+ orders.setAnfme(sum.setScale(QTY_SCALE, RoundingMode.HALF_UP).doubleValue());
+ 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;
+ }
+ BigDecimal anfme = toBigDecimal(taskItem.getAnfme());
+ BigDecimal newWorkQty = toBigDecimal(locItem.getWorkQty()).subtract(anfme).setScale(QTY_SCALE, RoundingMode.HALF_UP);
+ locItem.setWorkQty(newWorkQty.compareTo(BigDecimal.ZERO) >= 0 ? newWorkQty.doubleValue() : 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
@@ -478,34 +711,130 @@
if (Objects.isNull(param) || StringUtils.isBlank(param.getLocCode())) {
continue;
}
- Loc loc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getCode, param.getLocCode()).eq(Loc::getBarcode, param.getBarcode()));
+ // 淇锛氭瀯寤哄簱浣嶆煡璇㈡潯浠讹紝濡傛灉barcode涓虹┖锛屽彧鎸塴ocCode鏌ヨ
+ LambdaQueryWrapper<Loc> locQueryWrapper = new LambdaQueryWrapper<Loc>()
+ .eq(Loc::getCode, param.getLocCode());
+ if (StringUtils.isNotBlank(param.getBarcode())) {
+ locQueryWrapper.eq(Loc::getBarcode, param.getBarcode());
+ }
+ Loc loc = locService.getOne(locQueryWrapper);
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());
+ }
- WkOrderItem orderItem = outStockItemService.getOne(new LambdaQueryWrapper<WkOrderItem>()
+ // 淇锛氭瀯寤烘煡璇㈡潯浠讹紝鍏堟瀯寤哄熀纭�鏉′欢锛屽啀鏍规嵁鍊兼槸鍚︿负绌哄姩鎬佹坊鍔�
+ // 浼樺厛浣跨敤渚涘簲鍟嗘壒娆″尮閰嶏紝濡傛灉娌℃湁鍒欎娇鐢ㄥ簱瀛樻壒娆″尮閰�
+ LambdaQueryWrapper<WkOrderItem> orderItemWrapper = new LambdaQueryWrapper<WkOrderItem>()
.eq(WkOrderItem::getOrderId, outId)
- .eq(StringUtils.isNotBlank(locItem.getBatch()), WkOrderItem::getSplrBatch, locItem.getBatch())
- .eq(StringUtils.isNotBlank(locItem.getFieldsIndex()), WkOrderItem::getFieldsIndex, locItem.getFieldsIndex())
- .eq(WkOrderItem::getMatnrId, locItem.getMatnrId()));
+ .eq(WkOrderItem::getMatnrId, locItem.getMatnrId());
+
+ // 浼樺厛浣跨敤渚涘簲鍟嗘壒娆″尮閰�
+ if (StringUtils.isNotBlank(locItem.getSplrBatch())) {
+ orderItemWrapper.eq(WkOrderItem::getSplrBatch, locItem.getSplrBatch());
+ } else if (StringUtils.isNotBlank(locItem.getBatch())) {
+ // 濡傛灉LocItem鍙湁batch瀛楁锛屽皾璇曞悓鏃跺尮閰峎kOrderItem鐨刡atch鍜宻plrBatch瀛楁
+ // 鍥犱负鏌愪簺鎯呭喌涓婰ocItem鐨刡atch鍙兘瀵瑰簲WkOrderItem鐨剆plrBatch
+ 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());
+ }
+ // 鍚屼竴鍑哄簱鍗曚笅鍚屼竴鐗╂枡鍙兘鏈夊鏉℃槑缁嗭紙濡傚琛屽悎骞讹級锛岀敤 list 鍙栦粛鏈夊墿浣欐暟閲忕殑绗竴鏉�
+ List<WkOrderItem> orderItemCandidates = outStockItemService.list(orderItemWrapper);
+ WkOrderItem orderItem = orderItemCandidates.stream()
+ .filter(o -> o.getAnfme() != null && o.getWorkQty() != null && o.getAnfme().compareTo(o.getWorkQty()) > 0)
+ .findFirst()
+ .orElse(null);
+ // 涓ユ牸鍖归厤鏈壘鍒版椂锛氬啀鎸夈�屽悓鍗曞彿+鍚岀墿鏂欍�嶅鏉惧尮閰嶏紝閬垮厤鍘熸槑缁� fields_index 涓虹┖鑰屽垎閰嶅甫绁ㄥ彿瀵艰嚧閲嶅鍒涘缓涓�鏉�
if (Objects.isNull(orderItem)) {
- throw new CoolException("鍗曟嵁鏄庣粏涓嶅瓨鍦紒锛�");
+ LambdaQueryWrapper<WkOrderItem> relaxedWrapper = new LambdaQueryWrapper<WkOrderItem>()
+ .eq(WkOrderItem::getOrderId, outId)
+ .eq(WkOrderItem::getMatnrId, locItem.getMatnrId());
+ if (StringUtils.isNotBlank(locItem.getSplrBatch())) {
+ relaxedWrapper.eq(WkOrderItem::getSplrBatch, locItem.getSplrBatch());
+ } else if (StringUtils.isNotBlank(locItem.getBatch())) {
+ relaxedWrapper.and(w -> w.eq(WkOrderItem::getBatch, locItem.getBatch()).or().eq(WkOrderItem::getSplrBatch, locItem.getBatch()));
+ }
+ orderItem = outStockItemService.list(relaxedWrapper).stream()
+ .filter(o -> o.getAnfme() != null && o.getWorkQty() != null && o.getAnfme().compareTo(o.getWorkQty()) > 0)
+ .findFirst()
+ .orElse(null);
+ if (orderItem != null && StringUtils.isNotBlank(locItem.getFieldsIndex()) && !locItem.getFieldsIndex().equals(orderItem.getFieldsIndex())) {
+ orderItem.setFieldsIndex(locItem.getFieldsIndex());
+ outStockItemService.updateById(orderItem);
+ }
+ }
+
+ // 鎵句笉鍒板崟鎹槑缁嗘椂锛氬嚭搴撳崟瀛樺湪鍒欒嚜鍔ㄥ垱寤篧kOrderItem锛堝簱瀛樿皟鏁存垨鍒嗛厤鏃跺嚭搴撳崟鏆傛棤璇ョ墿鏂欒锛�
+ if (Objects.isNull(orderItem)) {
+ WkOrder outOrder = outStockService.getById(outId);
+ if (Objects.isNull(outOrder)) {
+ throw new CoolException("鍑哄簱鍗曟嵁涓嶅瓨鍦紒锛�");
+ }
+ boolean isStockRevise = locItem.getWkType() != null
+ && locItem.getWkType().equals(Short.parseShort(OrderWorkType.ORDER_WORK_TYPE_STOCK_REVISE.type));
+ if (isStockRevise) {
+ log.info("搴撳瓨璋冩暣浜х敓鐨勫簱瀛橈紝鑷姩鍒涘缓WkOrderItem - 鍑哄簱鍗旾D锛歿}锛岀墿鏂橧D锛歿}锛屾壒娆★細{}",
+ outId, locItem.getMatnrId(), locItem.getBatch());
+ } else {
+ log.info("鍑哄簱鍗曚笅鏃犲尮閰嶆槑缁嗭紝鑷姩鍒涘缓WkOrderItem - 鍑哄簱鍗旾D锛歿}锛岀墿鏂橧D锛歿}锛屾壒娆★細{}",
+ outId, locItem.getMatnrId(), locItem.getBatch());
+ }
+ 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锛歿}锛岀墿鏂橧D锛歿}",
+ orderItem.getId(), outId, locItem.getMatnrId());
}
locItem.setOutQty(param.getOutQty())
.setBatch(param.getBatch())
+ .setOrderId(outId)
+ .setOrderItemId(orderItem.getId())
.setSourceId(outId)
.setSourceCode(orderItem.getOrderCode())
.setSource(orderItem.getId());
locItems.add(locItem);
LocToTaskParams taskParams = new LocToTaskParams();
+ // 鍑哄簱鍗曚笅鍙戜换鍔℃椂锛屽嚭搴撳彛鏈紶鍒欓粯璁� 1001
+ String siteNo = StringUtils.isNotBlank(param.getSiteNo()) ? param.getSiteNo() : "1001";
taskParams.setType(Constants.TASK_TYPE_ORDER_OUT_STOCK)
.setOrgLoc(loc.getCode())
.setItems(locItems)
.setSourceId(outId)
- .setSiteNo(param.getSiteNo());
+ .setSiteNo(siteNo);
try {
//鐢熸垚鍑哄簱浠诲姟
locItemService.generateTask(TaskResouceType.TASK_RESOUCE_ORDER_TYPE.val, taskParams, loginUserId);
@@ -514,9 +843,9 @@
throw new CoolException(e.getMessage());
}
- Double workQty = Math.round((orderItem.getWorkQty() + locItem.getOutQty()) * 1000000) / 1000000.0;
+ BigDecimal workQty = toBigDecimal(orderItem.getWorkQty()).add(toBigDecimal(locItem.getOutQty())).setScale(QTY_SCALE, RoundingMode.HALF_UP);
- orderItem.setUpdateBy(loginUserId).setUpdateTime(new Date()).setWorkQty(workQty);
+ orderItem.setUpdateBy(loginUserId).setUpdateTime(new Date()).setWorkQty(workQty.doubleValue());
if (!outStockItemService.updateById(orderItem)) {
throw new CoolException("鍗曟嵁鏄庣粏淇敼澶辫触锛侊紒");
@@ -524,15 +853,15 @@
}
}
- Double sum = Items.stream().mapToDouble(OutStockToTaskParams::getOutQty).sum();
+ BigDecimal sum = Items.stream().map(OutStockToTaskParams::getOutQty).map(OutStockServiceImpl::toBigDecimal).reduce(BigDecimal.ZERO, BigDecimal::add);
//鏇存柊鍑哄簱鍗曟槑缁嗗強涓诲崟
WkOrder outOrder = outStockService.getById(outId);
if (Objects.isNull(outOrder)) {
throw new CoolException("鍑哄簱鍗曟嵁涓嶅瓨鍦紒锛�");
}
- Double workQty = Math.round((outOrder.getWorkQty() + sum) * 1000000) / 1000000.0;
+ BigDecimal workQty = toBigDecimal(outOrder.getWorkQty()).add(sum).setScale(QTY_SCALE, RoundingMode.HALF_UP);
- outOrder.setWorkQty(workQty).setExceStatus(AsnExceStatus.OUT_STOCK_STATUS_TASK_CREATE.val);
+ outOrder.setWorkQty(workQty.doubleValue()).setExceStatus(AsnExceStatus.OUT_STOCK_STATUS_TASK_CREATE.val);
if (!outStockService.updateById(outOrder)) {
throw new CoolException("鍑哄簱鍗曠姸鎬佷慨鏀瑰け璐ワ紒锛�");
@@ -552,7 +881,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);
}
@@ -569,16 +903,16 @@
if (!items.isEmpty()) {
for (WkOrderItem orderItem : items) {
DeliveryItem deliveryItem = deliveryItemService.getById(orderItem.getPoDetlId());
- Double workQty = Math.round((deliveryItem.getWorkQty() - orderItem.getAnfme()) * 1000000) / 1000000.0;
- deliveryItem.setWorkQty(workQty.compareTo(0.0) >= 0 ? workQty : 0);
+ BigDecimal workQty = toBigDecimal(deliveryItem.getWorkQty()).subtract(toBigDecimal(orderItem.getAnfme())).setScale(QTY_SCALE, RoundingMode.HALF_UP);
+ deliveryItem.setWorkQty(workQty.compareTo(BigDecimal.ZERO) >= 0 ? workQty.doubleValue() : 0);
if (!deliveryItemService.updateById(deliveryItem)) {
throw new CoolException("DO鍗曟槑缁嗘洿鏂板け璐ワ紒锛�");
}
Delivery delivery = deliveryService.getOne(new LambdaQueryWrapper<Delivery>().eq(Delivery::getCode, orderItem.getPoCode()));
if (!Objects.isNull(delivery)) {
- Double wkQty = Math.round((delivery.getWorkQty() - delivery.getAnfme()) * 1000000) / 1000000.0;
- delivery.setWorkQty(wkQty.compareTo(0.0) >= 0 ? wkQty : 0).setExceStatus(POExceStatus.PO_EXCE_STATUS_UN_EXCE.val);
+ BigDecimal wkQty = toBigDecimal(delivery.getWorkQty()).subtract(toBigDecimal(delivery.getAnfme())).setScale(QTY_SCALE, RoundingMode.HALF_UP);
+ delivery.setWorkQty(wkQty.compareTo(BigDecimal.ZERO) >= 0 ? wkQty.doubleValue() : 0).setExceStatus(POExceStatus.PO_EXCE_STATUS_UN_EXCE.val);
if (!deliveryService.updateById(delivery)) {
throw new CoolException("DO鍗曟嵁淇敼澶辫触锛侊紒");
}
@@ -605,9 +939,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<>();
@@ -621,47 +954,87 @@
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) {
- 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());
- locItem.setBarcode(loc.getBarcode());
- OrderOutItemDto orderOutItemDto = new OrderOutItemDto();
- orderOutItemDto.setLocItem(locItem);
-
- List<DeviceSite> deviceSites = deviceSiteService.list(new LambdaQueryWrapper<DeviceSite>()
- .eq(DeviceSite::getChannel, loc.getChannel())
- .eq(DeviceSite::getType, issued.doubleValue() >= locItem.getAnfme() && itemList.size() == 1 ? TaskType.TASK_TYPE_OUT.type : TaskType.TASK_TYPE_PICK_AGAIN_OUT.type)
- );
-
- if (!deviceSites.isEmpty()) {
- List<OrderOutItemDto.staListDto> maps = new ArrayList<>();
- for (DeviceSite sta : deviceSites) {
- OrderOutItemDto.staListDto staListDto = new OrderOutItemDto.staListDto();
- staListDto.setStaNo(sta.getSite());
- staListDto.setStaName(sta.getSite());
- maps.add(staListDto);
- }
- orderOutItemDto.setStaNos(maps);
- //榛樿鑾峰彇绗竴绔欑偣
- DeviceSite deviceSite = deviceSites.stream().findFirst().get();
- orderOutItemDto.setSiteNo(deviceSite.getSite());
+ if (issued.compareTo(ISSUED_TOLERANCE) <= 0) {
+ break;
+ }
+ // 棰勭害鍑哄簱涓笖鏈敓鎴愭嫞鏂欏叆搴撳崟鐨勫簱浣嶏細鎵e噺銆屾嫞鏂欎腑鍗犵敤銆嶅緱鍒板墿浣欏彲鐢紝骞舵爣璁般�屾鍦ㄦ嫞鏂欎腑锛屽墿浣� X 鍙敤銆�
+ BigDecimal pickingAllocated = getPickingAllocatedOnLoc(loc.getCode(), locItem.getMatnrId(), locItem.getBatch(), locItem.getFieldsIndex());
+ BigDecimal rawAnfme = toBigDecimal(locItem.getAnfme());
+ BigDecimal available = rawAnfme.subtract(pickingAllocated).setScale(QTY_SCALE, RoundingMode.HALF_UP);
+ if (available.compareTo(BigDecimal.ZERO) < 0) available = BigDecimal.ZERO;
+ locItem.setAnfme(available.doubleValue());
+ String pickingStatus = null;
+ if (pickingAllocated.compareTo(ISSUED_TOLERANCE) > 0) {
+ pickingStatus = "姝e湪鎷f枡涓紝鍓╀綑 " + available.setScale(2, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString() + " 鍙敤";
+ }
+ // 璇ュ簱浣嶅彲鍒嗛厤鏁伴噺锛氬彇鏈寰呭垎閰嶄笌搴撲綅鍓╀綑鍙敤鐨勮緝灏忓��
+ BigDecimal allocatable = issued.min(available);
+ // 褰撳垎閰嶉噺绛変簬搴撲綅搴撳瓨鏃讹紝浣跨敤搴撲綅搴撳瓨绮惧害浣滀负鍑哄簱鏁伴噺锛岄伩鍏嶆埅鏂鑷寸晫闈㈡樉绀�/搴撳瓨鏍¢獙涓嶄竴鑷达紙濡傚簱瀛�15.123457琚埅鎴�15.123锛�
+ BigDecimal outQtyToSet = (allocatable.subtract(available).abs().compareTo(ISSUED_TOLERANCE) <= 0) ? available : allocatable;
+ ExistDto existDto = new ExistDto().setBatch(locItem.getBatch()).setMatnr(locItem.getMatnrCode()).setLocNo(locItem.getLocCode());
+ if (existDtos.add(existDto)) {
+ // 棣栨浣跨敤璇ュ簱浣嶏細鍔犲叆鍒楄〃骞舵墸鍑� issued
+ locItem.setOutQty(outQtyToSet.doubleValue());
+ String barcode = StringUtils.isNotBlank(loc.getBarcode()) ? loc.getBarcode() : null;
+ if (barcode == null && LocStsType.LOC_STS_TYPE_R.type.equals(loc.getUseStatus())) {
+ List<Task> tasksOnLoc = taskService.list(new LambdaQueryWrapper<Task>()
+ .eq(Task::getOrgLoc, loc.getCode())
+ .in(Task::getTaskStatus, Arrays.asList(TaskStsType.GENERATE_OUT.id, TaskStsType.WAVE_SEED.id))
+ .last("LIMIT 1"));
+ if (!tasksOnLoc.isEmpty() && StringUtils.isNotBlank(tasksOnLoc.get(0).getBarcode())) {
+ barcode = tasksOnLoc.get(0).getBarcode();
}
-
- list.add(orderOutItemDto);
-
- issued = issued.subtract(new BigDecimal(locItem.getAnfme().toString()));
}
+ locItem.setBarcode(barcode != null ? barcode : loc.getBarcode());
+ OrderOutItemDto orderOutItemDto = new OrderOutItemDto();
+ orderOutItemDto.setLocItem(locItem);
+ if (pickingStatus != null) {
+ orderOutItemDto.setPickingStatus(pickingStatus);
+ }
+
+ List<DeviceSite> deviceSites = deviceSiteService.list(new LambdaQueryWrapper<DeviceSite>()
+ .eq(DeviceSite::getChannel, loc.getChannel())
+ .eq(DeviceSite::getType, issued.compareTo(toBigDecimal(locItem.getAnfme())) >= 0 && itemList.size() == 1 ? TaskType.TASK_TYPE_OUT.type : TaskType.TASK_TYPE_PICK_AGAIN_OUT.type)
+ );
+ // 鍑哄簱鍙e垪琛ㄦ帓搴忥細1001 鎺掔涓�锛屼綔涓洪粯璁�
+ deviceSites.sort((a, b) -> {
+ boolean a1001 = "1001".equals(a.getSite());
+ boolean b1001 = "1001".equals(b.getSite());
+ if (a1001 && !b1001) return -1;
+ if (!a1001 && b1001) return 1;
+ return 0;
+ });
+
+ if (!deviceSites.isEmpty()) {
+ List<OrderOutItemDto.staListDto> maps = new ArrayList<>();
+ for (DeviceSite sta : deviceSites) {
+ OrderOutItemDto.staListDto staListDto = new OrderOutItemDto.staListDto();
+ staListDto.setStaNo(sta.getSite());
+ staListDto.setStaName(sta.getSite());
+ maps.add(staListDto);
+ }
+ orderOutItemDto.setStaNos(maps);
+ //榛樿鑾峰彇绗竴绔欑偣
+ DeviceSite deviceSite = deviceSites.stream().findFirst().get();
+ orderOutItemDto.setSitesNo(deviceSite.getSite());
+ }
+
+ list.add(orderOutItemDto);
+ issued = issued.subtract(outQtyToSet);
+ } else {
+ // 璇ュ簱浣嶅凡琚墠搴忚鍗曡鍗犵敤锛氬彧鎵e噺 issued锛屼笉閲嶅鍔犲叆鍒楄〃锛岄伩鍏嶄骇鐢熲�滃簱瀛樹笉瓒斥�濊剰鏁版嵁
+ issued = issued.subtract(allocatable);
}
}
- if (issued.doubleValue() > 0) {
+ if (issued.compareTo(ISSUED_TOLERANCE) > 0) {
+ BigDecimal remaining = issued.setScale(QTY_SCALE, RoundingMode.HALF_UP);
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.doubleValue())
+ .setOutQty(remaining.doubleValue())
.setUnit(wkOrderItem.getStockUnit())
.setBatch(wkOrderItem.getSplrBatch());
OrderOutItemDto orderOutItemDto = new OrderOutItemDto();
@@ -675,6 +1048,25 @@
}
/**
+ * 璇ュ簱浣嶄笅銆屾嫞鏂欏嚭搴撱�嶄笖鏈敓鎴愭嫞鏂欏叆搴撳崟鐨勪换鍔″崰鐢ㄧ殑鏁伴噺锛堝悓涓�鐗╂枡+鎵规+绁ㄥ彿锛�
+ */
+ private BigDecimal getPickingAllocatedOnLoc(String locCode, Long matnrId, String batch, String fieldsIndex) {
+ List<Task> tasks = taskService.list(new LambdaQueryWrapper<Task>()
+ .eq(Task::getOrgLoc, locCode)
+ .eq(Task::getTaskType, TaskType.TASK_TYPE_PICK_AGAIN_OUT.type)
+ .in(Task::getTaskStatus, Arrays.asList(TaskStsType.GENERATE_OUT.id, TaskStsType.WAVE_SEED.id)));
+ if (tasks.isEmpty()) return BigDecimal.ZERO;
+ Set<Long> taskIds = tasks.stream().map(Task::getId).collect(Collectors.toSet());
+ LambdaQueryWrapper<TaskItem> q = new LambdaQueryWrapper<TaskItem>()
+ .in(TaskItem::getTaskId, taskIds)
+ .eq(TaskItem::getMatnrId, matnrId);
+ if (StringUtils.isNotBlank(batch)) q.eq(TaskItem::getBatch, batch);
+ if (StringUtils.isNotBlank(fieldsIndex)) q.eq(TaskItem::getFieldsIndex, fieldsIndex);
+ List<TaskItem> items = taskItemService.list(q);
+ return items.stream().map(ti -> toBigDecimal(ti.getAnfme())).reduce(BigDecimal.ZERO, BigDecimal::add);
+ }
+
+ /**
* @param
* @param wave
* @return
@@ -685,11 +1077,11 @@
private List<WaveItem> mergeWave(List<WkOrderItem> orderItems, Wave wave) {
List<WaveItem> items = new ArrayList<>();
orderItems.forEach(order -> {
- Double anfme = Math.round((order.getAnfme() - order.getWorkQty()) * 1000000) / 1000000.0;
+ BigDecimal anfme = toBigDecimal(order.getAnfme()).subtract(toBigDecimal(order.getWorkQty())).setScale(QTY_SCALE, RoundingMode.HALF_UP);
WaveItem item = new WaveItem();
BeanUtils.copyProperties(order, item);
item.setId(null)
- .setAnfme(anfme)
+ .setAnfme(anfme.doubleValue())
.setMatnrId(order.getMatnrId())
.setMaktx(order.getMaktx())
.setWaveId(wave.getId())
@@ -711,7 +1103,7 @@
p1.getUnit(),
p1.getTrackCode(),
p1.getFieldsIndex(),
- Math.round((p1.getAnfme() + p2.getAnfme())* 1000000) / 1000000.0,
+ toBigDecimal(p1.getAnfme()).add(toBigDecimal(p2.getAnfme())).setScale(QTY_SCALE, RoundingMode.HALF_UP).doubleValue(),
p1.getWorkQty(),
p1.getTenantId(),
p1.getStatus(),
@@ -743,6 +1135,9 @@
return R.error("鍑哄簱鍗曚笉瀛樺湪锛侊紒");
}
order.setExceStatus(AsnExceStatus.OUT_STOCK_STATUS_TASK_DONE.val);
+ if (order.getQty() == null || order.getQty().compareTo(0.0) == 0) {
+ order.setQty(order.getWorkQty() != null ? order.getWorkQty() : 0.0);
+ }
if (!this.updateById(order)) {
throw new CoolException("瀹屾垚鍑哄簱鍗曞け璐ワ紒锛�");
}
--
Gitblit v1.9.1