| | |
| | | |
| | | @Override |
| | | public OrderDetlPakout selectItem(Long orderId, String matnr, String batch, String brand, String standby1, String standby2, String standby3, String boxType1, String boxType2, String boxType3) { |
| | | return this.baseMapper.selectItem(orderId, matnr, batch,brand,standby1,standby2,standby3,boxType1,boxType2,boxType3); |
| | | // 延迟出库后,man_order_detl_pakout 会按托盘拆明细。 |
| | | // 旧的 orderId + 物料维度可能命中多条记录,不能再用 mapper 返回单对象的 selectOne 语义。 |
| | | // 这里统一改为列表查询并按 id 取第一条,避免 TooManyResultsException;需要精确回写时请优先使用 pallet_id。 |
| | | return selectFirst(buildItemWrapper(orderId, null, matnr, batch, brand, standby1, standby2, standby3, boxType1, boxType2, boxType3)); |
| | | } |
| | | |
| | | @Override |
| | | public OrderDetlPakout selectItem(String orderNo, String matnr, String batch, String brand, String standby1, String standby2, String standby3, String boxType1, String boxType2, String boxType3) { |
| | | return this.baseMapper.selectItemByOrderNo(orderNo, matnr, batch,brand,standby1,standby2,standby3,boxType1,boxType2,boxType3); |
| | | // 同上,orderNo + 物料维度在新模型中不保证唯一,只作为旧数据的兜底匹配。 |
| | | return selectFirst(buildItemWrapper(null, orderNo, matnr, batch, brand, standby1, standby2, standby3, boxType1, boxType2, boxType3)); |
| | | } |
| | | |
| | | @Override |
| | |
| | | if (Cools.isEmpty(orderNo) || Cools.isEmpty(palletId)) { |
| | | return null; |
| | | } |
| | | return this.selectOne(new EntityWrapper<OrderDetlPakout>() |
| | | .eq("order_no", orderNo) |
| | | .eq("pallet_id", palletId)); |
| | | // orderNo + palletId 是延迟出库订单明细的精确匹配键。 |
| | | // 仍然使用 selectList 取第一条,防止历史脏数据里同一托盘重复时 selectOne 直接中断定时线程。 |
| | | EntityWrapper<OrderDetlPakout> wrapper = new EntityWrapper<>(); |
| | | wrapper.eq("order_no", orderNo) |
| | | .eq("pallet_id", palletId) |
| | | .orderBy("id", true); |
| | | return selectFirst(wrapper); |
| | | } |
| | | |
| | | @Override |
| | |
| | | public boolean increaseWorkQty(Long orderId, String matnr, String batch, String brand, String standby1, String standby2, String standby3, String boxType1, String boxType2, String boxType3, Double workQty) { |
| | | return this.baseMapper.increaseWorkQty(orderId, matnr, batch,brand,standby1,standby2,standby3,boxType1,boxType2,boxType3, workQty) > 0; |
| | | } |
| | | |
| | | private EntityWrapper<OrderDetlPakout> buildItemWrapper(Long orderId, String orderNo, String matnr, String batch, String brand, |
| | | String standby1, String standby2, String standby3, |
| | | String boxType1, String boxType2, String boxType3) { |
| | | EntityWrapper<OrderDetlPakout> wrapper = new EntityWrapper<>(); |
| | | wrapper.eq("matnr", matnr) |
| | | .eq("batch", batch) |
| | | .eq("brand", brand) |
| | | .eq("standby1", standby1) |
| | | .eq("standby2", standby2) |
| | | .eq("standby3", standby3) |
| | | .eq("box_type1", boxType1) |
| | | .eq("box_type2", boxType2) |
| | | .eq("box_type3", boxType3) |
| | | .orderBy("id", true); |
| | | if (!Cools.isEmpty(orderId)) { |
| | | wrapper.eq("order_id", orderId); |
| | | } |
| | | if (!Cools.isEmpty(orderNo)) { |
| | | wrapper.eq("order_no", orderNo); |
| | | } |
| | | return wrapper; |
| | | } |
| | | |
| | | private OrderDetlPakout selectFirst(EntityWrapper<OrderDetlPakout> wrapper) { |
| | | List<OrderDetlPakout> rows = this.selectList(wrapper); |
| | | return Cools.isEmpty(rows) ? null : rows.get(0); |
| | | } |
| | | } |
| | |
| | | } |
| | | for (WrkDetl wrkDetl : wrkDetls101) { |
| | | // 更新订单完成数量 |
| | | OrderDetlPakout orderDetlPakout = orderDetlPakoutService.selectItem(wrkDetl.getOrderNo(), wrkDetl.getMatnr(), wrkDetl.getBatch(), wrkDetl.getBrand(), wrkDetl.getStandby1(), wrkDetl.getStandby2(), wrkDetl.getStandby3(), |
| | | wrkDetl.getBoxType1(), wrkDetl.getBoxType2(), wrkDetl.getBoxType3()); |
| | | if (orderDetlPakout == null) { |
| | | orderDetlPakout = orderDetlPakoutService.selectItem(wrkDetl.getOrderNo(), wrkDetl.getMatnr(), wrkDetl.getBatch(), wrkDetl.getBrand(), wrkDetl.getStandby1(), wrkDetl.getStandby2(), wrkDetl.getStandby3(), |
| | | wrkDetl.getBoxType1(), wrkDetl.getBoxType2(), wrkDetl.getBoxType3()); |
| | | } |
| | | try { |
| | | if (!increasePakoutOrderQty(wrkMast, wrkDetl, orderDetlPakout)) { |
| | | if (!increasePakoutOrderQty(wrkMast, wrkDetl)) { |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("全板出库 ===>> 更新订单完成数量失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getSourceLocNo() + "]"); |
| | | } |
| | |
| | | } |
| | | } |
| | | // 更新订单完成数量 |
| | | OrderDetlPakout orderDetlPakout = orderDetlPakoutService.selectItem(wrkDetl.getOrderNo(), wrkDetl.getMatnr(), wrkDetl.getBatch(), wrkDetl.getBrand(), wrkDetl.getStandby1(), wrkDetl.getStandby2(), wrkDetl.getStandby3(), |
| | | wrkDetl.getBoxType1(), wrkDetl.getBoxType2(), wrkDetl.getBoxType3()); |
| | | try { |
| | | if (!increasePakoutOrderQty(wrkMast, wrkDetl, orderDetlPakout)) { |
| | | if (!increasePakoutOrderQty(wrkMast, wrkDetl)) { |
| | | TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
| | | return FAIL.setMsg("并板途中捡料 ===>> 更新订单完成数量失败; [workNo=" + wrkMast.getWrkNo() + "],[locNo=" + wrkMast.getSourceLocNo() + "]"); |
| | | } |
| | |
| | | * 新增的延迟出库订单明细按 pallet_id 保存接口托盘号,因此优先使用 orderNo + palletId 精确回写; |
| | | * 如果是历史订单或旧数据没有 pallet_id,则退回原来的物料/批次/备用字段匹配方式。 |
| | | */ |
| | | private boolean increasePakoutOrderQty(WrkMast wrkMast, WrkDetl wrkDetl, OrderDetlPakout matchedOrderDetl) { |
| | | private boolean increasePakoutOrderQty(WrkMast wrkMast, WrkDetl wrkDetl) { |
| | | if (wrkDetl == null || Cools.isEmpty(wrkDetl.getOrderNo())) { |
| | | return true; |
| | | } |
| | | String palletId = null; |
| | | if (wrkDetl != null && !Cools.isEmpty(wrkDetl.getZpallet())) { |
| | | if (!Cools.isEmpty(wrkDetl.getZpallet())) { |
| | | palletId = wrkDetl.getZpallet(); |
| | | } else if (wrkMast != null) { |
| | | palletId = wrkMast.getBarcode(); |
| | | } |
| | | // stationId > 600 的延迟出库订单是一托盘一行明细;同一订单、物料、批次、进仓编号下会有多行。 |
| | | // 因此完成回写必须优先用 orderNo + palletId 精确定位,否则旧的物料维度查询会命中多行。 |
| | | if (!Cools.isEmpty(palletId) |
| | | && orderDetlPakoutService.increaseQtyByOrderNoAndPallet(wrkDetl.getOrderNo(), palletId, wrkDetl.getAnfme())) { |
| | | return true; |
| | | } |
| | | // 兼容历史订单:旧数据可能没有 pallet_id,只能退回原来的物料/批次/备用字段匹配。 |
| | | // 这里不再调用批量 update SQL,而是先取一条明细后按 id 更新,避免重复明细时把多行 qty 一起加上。 |
| | | OrderDetlPakout matchedOrderDetl = orderDetlPakoutService.selectItem(wrkDetl.getOrderNo(), wrkDetl.getMatnr(), |
| | | wrkDetl.getBatch(), wrkDetl.getBrand(), wrkDetl.getStandby1(), wrkDetl.getStandby2(), wrkDetl.getStandby3(), |
| | | wrkDetl.getBoxType1(), wrkDetl.getBoxType2(), wrkDetl.getBoxType3()); |
| | | if (Cools.isEmpty(matchedOrderDetl)) { |
| | | return true; |
| | | } |
| | | return orderDetlPakoutService.increaseQtyByOrderNo(wrkDetl.getOrderNo(), wrkDetl.getMatnr(), |
| | | matchedOrderDetl.getBatch(), wrkDetl.getBrand(), wrkDetl.getStandby1(), wrkDetl.getStandby2(), wrkDetl.getStandby3(), |
| | | wrkDetl.getBoxType1(), wrkDetl.getBoxType2(), wrkDetl.getBoxType3(), wrkDetl.getAnfme()); |
| | | matchedOrderDetl.setQty(safeDouble(matchedOrderDetl.getQty()) + safeDouble(wrkDetl.getAnfme())); |
| | | matchedOrderDetl.setUpdateTime(new Date()); |
| | | return orderDetlPakoutService.updateById(matchedOrderDetl); |
| | | } |
| | | |
| | | private double safeDouble(Double value) { |
| | | return value == null ? 0.0D : value; |
| | | } |
| | | } |
| | |
| | | keepAliveSeconds: 60 |
| | | connectionTimeoutSeconds: 10 |
| | | persistenceDir: .local/iot-mqtt |
| | | caCertPath: D:/work/work-zy/gsl/zy-wms-gsl/src/main/resources/iot-certs/AmazonRootCA1.pem |
| | | clientCertPath: D:/work/work-zy/gsl/zy-wms-gsl/src/main/resources/iot-certs/device-certificate.pem.crt |
| | | privateKeyPath: D:/work/work-zy/gsl/zy-wms-gsl/src/main/resources/iot-certs/device-private.pem.key |
| | | caCertPath: D:\working\Project Documentation\临港哥斯拉项目\iot/AmazonRootCA1.pem |
| | | clientCertPath: D:\working\Project Documentation\临港哥斯拉项目\iot/device-certificate.pem.crt |
| | | privateKeyPath: D:\working\Project Documentation\临港哥斯拉项目\iot/device-private.pem.key |
| | | topics: |
| | | #亚马逊发送组托给wms,在托盘上收到纸箱后,发布堆垛指令以将托盘发送到仓库。 |
| | | egressStow: glenn/instruction/icng/egress/asrs/stow |
| | | egressStow: glenn/instruction/test_icng/egress/asrs/stow |
| | | #亚马逊发送出库指令给wms,启动拣选请求后,发布拣选指令以引导ASRS从料箱中取货。 |
| | | egressPick: glenn/instruction/icng/egress/asrs/pick |
| | | egressPick: glenn/instruction/test_icng/egress/asrs/pick |
| | | #wms入库完成发送给亚马逊,ASRS实际拖拽托盘到料箱后,发布堆垛动作以同步BPS数据。 |
| | | egressFeedback: glenn/instruction/icng/egress/asrs/feedback |
| | | egressFeedback: glenn/instruction/test_icng/egress/asrs/feedback |
| | | #wms出库完成发送给亚马逊,在ASRS实际从料箱取货后,发布拣选动作sz XBPS数据。 |
| | | ingressStow: glenn/instruction/icng/ingress/asrs/stow |
| | | ingressStow: glenn/instruction/test_icng/ingress/asrs/stow |
| | | #ASRS 接收到 XBPS 指令后,向反馈XBPS 发送响应。 |
| | | ingressPick: glenn/instruction/icng/ingress/asrs/pick |
| | | ingressPick: glenn/instruction/test_icng/ingress/asrs/pick |
| | | #在XBPs收到ASRS操作后,向反馈ASRS发送响应 |
| | | ingressFeedback: glenn/instruction/icng/ingress/asrs/feedback |
| | | ingressFeedback: glenn/instruction/test_icng/ingress/asrs/feedback |
| | | pickStationMappings: |
| | | ASRSOutbound1: 101 |