Bladeren bron

PDA入库流程优化:入库码盘->条码检测->上架->下发AGV任务->任务取卸货完成转移库存和修改托盘绑定库位

k 2 jaren geleden
bovenliggende
commit
5f7b4a7085

+ 130 - 130
ruoyi-admin/src/main/java/com/ruoyi/web/controller/warewms/pda/PdaController.java

@@ -92,6 +92,134 @@ public class PdaController {
     @Autowired
     private IInvLotLocIdService invLotLocIdService;
 
+    /**
+     * 物料拉动通用
+     *
+     * @param lineCallForm
+     * @return
+     */
+    @PostMapping("/lineCall/pulling")
+    public AjaxResult pulling(@RequestBody LineCallForm lineCallForm) {
+        //查询所属流程
+        FlowConfigHeaderVO flowConfigHeaderVO = flowConfigHeaderService.selectFlowConfigHeaderById(lineCallForm.getFlowId());
+        if (flowConfigHeaderVO == null) {
+            log.info("-----------指令查询不到对应的流程:" + JSON.toJSONString(lineCallForm));
+            return AjaxResult.error("指令查询不到对应的流程");
+        }
+
+        Map<String, AgvCallDTO> map = new HashMap<>();
+        List<AgvCallDTO> list = new ArrayList<>();
+        for (LineCallListFrom lform : lineCallForm.getLineCallList()) {
+
+            //入库时绑定托盘
+            if (flowConfigHeaderVO.getFlowType().equals("ASN")) {
+                PaForm paForm = new PaForm();
+                paForm.setPalletNo(lform.getPalletNo());
+                paForm.setLocationFrom("900");
+                paForm.setLocationTo(lform.getLocationFrom());
+                wmsDocAsnHeaderService.doPa(paForm);
+            }
+
+            if (flowConfigHeaderVO.getFlowType().equals("ASN") && org.apache.commons.lang3.StringUtils.isEmpty(lform.getLocationFrom())) {
+                return AjaxResult.error("入库任务必须选择起始库位");
+            }
+            if (flowConfigHeaderVO.getFlowType().equals("SO") && (lform.getQty() == null || lform.getQty().longValue() == 0)) {
+                return AjaxResult.error("出库任务必须选择数量");
+            }
+            AgvCallDTO agvCallDTO;
+            if (map.containsKey(lform.getLocationFrom() + "-" + lform.getLocationTo())) {
+                agvCallDTO = map.get(lform.getLocationFrom() + "-" + lform.getLocationTo());
+            } else {
+                agvCallDTO = new AgvCallDTO();
+                agvCallDTO.setWarehouseId(1L);//没用暂时写死
+                agvCallDTO.setLocationFrom(lform.getLocationFrom());
+                agvCallDTO.setLocationTo(lform.getLocationTo());
+                agvCallDTO.setId(lform.getId());
+            }
+            AgvCallItemDTO agvCallItemDTO = new AgvCallItemDTO();
+            agvCallItemDTO.setWarehouseId(1L);
+            agvCallItemDTO.setSku(lform.getSku());
+            agvCallItemDTO.setQty(lform.getQty());
+            agvCallItemDTO.setSupplier(lform.getSupplier());
+            agvCallItemDTO.setWeight(lform.getWeight());
+            agvCallItemDTO.setLocationFrom(lform.getLocationFrom());
+            agvCallItemDTO.setLocationTo(lform.getLocationTo());
+            agvCallDTO.getAgvCallItemDTOList().add(agvCallItemDTO);
+            LotattDTO lotattDTO = new LotattDTO();
+            List<LineCallDetailsForm> lineCallDetailsForms = lform.getLineCallDetailsFormList();
+            if (lineCallDetailsForms != null && lineCallDetailsForms.size() > 0) {
+                for (LineCallDetailsForm detailsForm : lineCallDetailsForms) {
+                    lotattDTO.setAttr(detailsForm.getLotattId(), detailsForm.getLotattValue());
+                }
+            }
+            agvCallItemDTO.setLotattDTO(lotattDTO);
+            map.put(lform.getLocationFrom() + "-" + lform.getLocationTo(), agvCallDTO);
+        }
+        for (Map.Entry<String, AgvCallDTO> entry : map.entrySet()) {
+            AgvCallDTO mapValue = entry.getValue();
+            list.add(mapValue);
+        }
+        return businessService.agvCall(flowConfigHeaderVO, list);
+    }
+
+    /**
+     * 入库码盘
+     *
+     * @param stockForm
+     * @return
+     */
+    @PostMapping("/docAsn/stock")
+    @Log(title = "码盘", businessType = BusinessType.INSERT)
+    public AjaxResult stock(@RequestBody StockForm stockForm) {
+        if (stockForm.getStockTag().equals("Y") && StringUtils.isEmpty(stockForm.getOrderNo())) {
+            return AjaxResult.error("码盘备货必须输入出库单号");
+        }
+        return wmsDocAsnHeaderService.doStock(stockForm);
+    }
+
+    /**
+     * 条码检测
+     *
+     * @param snCheckForm
+     * @return 根据入库单和条码查询出未码盘的信息,入库单数量-已码盘数量
+     */
+    @PostMapping("/docAsn/snCheck")
+    public AjaxResult snCheck(@Validated @RequestBody SnCheckForm snCheckForm) {
+        CodeSkuRelationshipVO codeSkuRelationshipVO = wmsDocAsnHeaderService.searchSn(snCheckForm);
+        return AjaxResult.success(codeSkuRelationshipVO);
+    }
+
+    /**
+     * PDA上架
+     *
+     * @param paForm
+     * @return
+     */
+    @PostMapping("/docAsn/doPa")
+    public AjaxResult doPa(@RequestBody PaForm paForm) {
+        if (StringUtils.isEmpty(paForm.getPalletNo())) {
+            return AjaxResult.error("托盘号不能为空");
+        }
+        if (StringUtils.isEmpty(paForm.getLocationFrom())) {
+            return AjaxResult.error("起始库位不能为空");
+        }
+        if (StringUtils.isEmpty(paForm.getLocationTo())) {
+            return AjaxResult.error("目标库位不能为空");
+        }
+        return wmsDocAsnHeaderService.doPa(paForm);
+    }
+
+    /**
+     * 解绑物料
+     *
+     * @param unlockForm
+     * @return
+     */
+    @PostMapping("/docAsn/unloadStock")
+    public AjaxResult unloadStock(@RequestBody UnlockForm unlockForm) {
+        return wmsDocAsnHeaderService.unloadStock(unlockForm);
+    }
+
     /**
      * 查询批次属性后台配置
      *
@@ -149,54 +277,6 @@ public class PdaController {
         return AjaxResult.success(detailsList);
     }
 
-
-    /**
-     * 码盘
-     *
-     * @param stockForm
-     * @return
-     */
-    @PostMapping("/docAsn/stock")
-    @Log(title = "码盘", businessType = BusinessType.INSERT)
-    public AjaxResult stock(@RequestBody StockForm stockForm) {
-        if (stockForm.getStockTag().equals("Y") && StringUtils.isEmpty(stockForm.getOrderNo())) {
-            return AjaxResult.error("码盘备货必须输入出库单号");
-        }
-        return wmsDocAsnHeaderService.doStock(stockForm);
-    }
-
-    /**
-     * 条码检测
-     *
-     * @param snCheckForm
-     * @return
-     */
-    @PostMapping("/docAsn/snCheck")
-    public AjaxResult snCheck(@Validated @RequestBody SnCheckForm snCheckForm) {
-        CodeSkuRelationshipVO codeSkuRelationshipVO = wmsDocAsnHeaderService.searchSn(snCheckForm);
-        return AjaxResult.success(codeSkuRelationshipVO);
-    }
-
-    /**
-     * PDA上架
-     *
-     * @param paForm
-     * @return
-     */
-    @PostMapping("/docAsn/doPa")
-    public AjaxResult doPa(@RequestBody PaForm paForm) {
-        if (StringUtils.isEmpty(paForm.getPalletNo())) {
-            return AjaxResult.error("托盘号不能为空");
-        }
-        if (StringUtils.isEmpty(paForm.getLocationFrom())) {
-            return AjaxResult.error("起始库位不能为空");
-        }
-        if (StringUtils.isEmpty(paForm.getLocationTo())) {
-            return AjaxResult.error("目标库位不能为空");
-        }
-        return wmsDocAsnHeaderService.doPa(paForm);
-    }
-
     /**
      * 查询备货绑定
      *
@@ -209,17 +289,6 @@ public class PdaController {
         return AjaxResult.success("", searchStockVOList);
     }
 
-    /**
-     * 解绑删除
-     *
-     * @param unlockForm
-     * @return
-     */
-    @PostMapping("/docAsn/unloadStock")
-    public AjaxResult unloadStock(@RequestBody UnlockForm unlockForm) {
-        return wmsDocAsnHeaderService.unloadStock(unlockForm);
-    }
-
     /**
      * 查询流程配置
      *
@@ -247,76 +316,6 @@ public class PdaController {
         return AjaxResult.success(lineCallVO);
     }
 
-    /**
-     * 物料拉动通用
-     *
-     * @param lineCallForm
-     * @return
-     */
-    @PostMapping("/lineCall/pulling")
-    public AjaxResult pulling(@RequestBody LineCallForm lineCallForm) {
-        //查询所属流程
-        FlowConfigHeaderVO flowConfigHeaderVO = flowConfigHeaderService.selectFlowConfigHeaderById(lineCallForm.getFlowId());
-        if (flowConfigHeaderVO == null) {
-            log.info("-----------指令查询不到对应的流程:" + JSON.toJSONString(lineCallForm));
-            return AjaxResult.error("指令查询不到对应的流程");
-        }
-
-        Map<String, AgvCallDTO> map = new HashMap<>();
-        List<AgvCallDTO> list = new ArrayList<>();
-        for (LineCallListFrom lform : lineCallForm.getLineCallList()) {
-
-            //入库时绑定托盘
-            if (flowConfigHeaderVO.getFlowType().equals("ASN")) {
-                PaForm paForm = new PaForm();
-                paForm.setPalletNo(lform.getPalletNo());
-                paForm.setLocationFrom("900");
-                paForm.setLocationTo(lform.getLocationFrom());
-                wmsDocAsnHeaderService.doPa(paForm);
-            }
-
-            if (flowConfigHeaderVO.getFlowType().equals("ASN") && org.apache.commons.lang3.StringUtils.isEmpty(lform.getLocationFrom())) {
-                return AjaxResult.error("入库任务必须选择起始库位");
-            }
-            if (flowConfigHeaderVO.getFlowType().equals("SO") && (lform.getQty() == null || lform.getQty().longValue() == 0)) {
-                return AjaxResult.error("出库任务必须选择数量");
-            }
-            AgvCallDTO agvCallDTO;
-            if (map.containsKey(lform.getLocationFrom() + "-" + lform.getLocationTo())) {
-                agvCallDTO = map.get(lform.getLocationFrom() + "-" + lform.getLocationTo());
-            } else {
-                agvCallDTO = new AgvCallDTO();
-                agvCallDTO.setWarehouseId(1L);//没用暂时写死
-                agvCallDTO.setLocationFrom(lform.getLocationFrom());
-                agvCallDTO.setLocationTo(lform.getLocationTo());
-                agvCallDTO.setId(lform.getId());
-            }
-            AgvCallItemDTO agvCallItemDTO = new AgvCallItemDTO();
-            agvCallItemDTO.setWarehouseId(1L);
-            agvCallItemDTO.setSku(lform.getSku());
-            agvCallItemDTO.setQty(lform.getQty());
-            agvCallItemDTO.setSupplier(lform.getSupplier());
-            agvCallItemDTO.setWeight(lform.getWeight());
-            agvCallItemDTO.setLocationFrom(lform.getLocationFrom());
-            agvCallItemDTO.setLocationTo(lform.getLocationTo());
-            agvCallDTO.getAgvCallItemDTOList().add(agvCallItemDTO);
-            LotattDTO lotattDTO = new LotattDTO();
-            List<LineCallDetailsForm> lineCallDetailsForms = lform.getLineCallDetailsFormList();
-            if (lineCallDetailsForms != null && lineCallDetailsForms.size() > 0) {
-                for (LineCallDetailsForm detailsForm : lineCallDetailsForms) {
-                    lotattDTO.setAttr(detailsForm.getLotattId(), detailsForm.getLotattValue());
-                }
-            }
-            agvCallItemDTO.setLotattDTO(lotattDTO);
-            map.put(lform.getLocationFrom() + "-" + lform.getLocationTo(), agvCallDTO);
-        }
-        for (Map.Entry<String, AgvCallDTO> entry : map.entrySet()) {
-            AgvCallDTO mapValue = entry.getValue();
-            list.add(mapValue);
-        }
-        return businessService.agvCall(flowConfigHeaderVO, list);
-    }
-
     /**
      * 分拣明细查询
      *
@@ -375,11 +374,12 @@ public class PdaController {
 
     /**
      * 出库列表
+     *
      * @return
      */
     @GetMapping("/docOrder/checkOutList")
     public AjaxResult checkOutList(@RequestParam String orderNos) {
-        List<String>  orderList = JSONArray.parseArray(orderNos,String.class);
+        List<String> orderList = JSONArray.parseArray(orderNos, String.class);
         List<CheckOutVO> checkOutVOList = wmsDocOrderHeaderService.checkOutList(orderList);
         return AjaxResult.success(checkOutVOList);
     }

+ 57 - 57
ruoyi-quartz/src/main/java/com/ruoyi/quartz/config/ScheduleConfig.java

@@ -1,57 +1,57 @@
-package com.ruoyi.quartz.config;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.scheduling.quartz.SchedulerFactoryBean;
-import javax.sql.DataSource;
-import java.util.Properties;
-
-/**
- * 定时任务配置(单机部署建议删除此类和qrtz数据库表,默认走内存会最高效)
- * 
- * @author ruoyi
- */
-@Configuration
-public class ScheduleConfig
-{
-    @Bean
-    public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource)
-    {
-        SchedulerFactoryBean factory = new SchedulerFactoryBean();
-        factory.setDataSource(dataSource);
-
-        // quartz参数
-        Properties prop = new Properties();
-        prop.put("org.quartz.scheduler.instanceName", "RuoyiScheduler");
-        prop.put("org.quartz.scheduler.instanceId", "AUTO");
-        // 线程池配置
-        prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
-        prop.put("org.quartz.threadPool.threadCount", "20");
-        prop.put("org.quartz.threadPool.threadPriority", "5");
-        // JobStore配置
-        prop.put("org.quartz.jobStore.class", "org.springframework.scheduling.quartz.LocalDataSourceJobStore");
-        // 集群配置
-        prop.put("org.quartz.jobStore.isClustered", "true");
-        prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");
-        prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");
-        prop.put("org.quartz.jobStore.txIsolationLevelSerializable", "true");
-
-        // sqlserver 启用
-        // prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?");
-        prop.put("org.quartz.jobStore.misfireThreshold", "12000");
-        prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");
-        factory.setQuartzProperties(prop);
-
-        factory.setSchedulerName("RuoyiScheduler");
-        // 延时启动
-        factory.setStartupDelay(1);
-        factory.setApplicationContextSchedulerContextKey("applicationContextKey");
-        // 可选,QuartzScheduler
-        // 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了
-        factory.setOverwriteExistingJobs(true);
-        // 设置自动启动,默认为true
-        factory.setAutoStartup(true);
-
-        return factory;
-    }
-}
+//package com.ruoyi.quartz.config;
+//
+//import org.springframework.context.annotation.Bean;
+//import org.springframework.context.annotation.Configuration;
+//import org.springframework.scheduling.quartz.SchedulerFactoryBean;
+//import javax.sql.DataSource;
+//import java.util.Properties;
+//
+///**
+// * 定时任务配置(单机部署建议删除此类和qrtz数据库表,默认走内存会最高效)
+// *
+// * @author ruoyi
+// */
+//@Configuration
+//public class ScheduleConfig
+//{
+//    @Bean
+//    public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource)
+//    {
+//        SchedulerFactoryBean factory = new SchedulerFactoryBean();
+//        factory.setDataSource(dataSource);
+//
+//        // quartz参数
+//        Properties prop = new Properties();
+//        prop.put("org.quartz.scheduler.instanceName", "RuoyiScheduler");
+//        prop.put("org.quartz.scheduler.instanceId", "AUTO");
+//        // 线程池配置
+//        prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
+//        prop.put("org.quartz.threadPool.threadCount", "20");
+//        prop.put("org.quartz.threadPool.threadPriority", "5");
+//        // JobStore配置
+//        prop.put("org.quartz.jobStore.class", "org.springframework.scheduling.quartz.LocalDataSourceJobStore");
+//        // 集群配置
+//        prop.put("org.quartz.jobStore.isClustered", "true");
+//        prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");
+//        prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");
+//        prop.put("org.quartz.jobStore.txIsolationLevelSerializable", "true");
+//
+//        // sqlserver 启用
+//        // prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?");
+//        prop.put("org.quartz.jobStore.misfireThreshold", "12000");
+//        prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");
+//        factory.setQuartzProperties(prop);
+//
+//        factory.setSchedulerName("RuoyiScheduler");
+//        // 延时启动
+//        factory.setStartupDelay(1);
+//        factory.setApplicationContextSchedulerContextKey("applicationContextKey");
+//        // 可选,QuartzScheduler
+//        // 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了
+//        factory.setOverwriteExistingJobs(true);
+//        // 设置自动启动,默认为true
+//        factory.setAutoStartup(true);
+//
+//        return factory;
+//    }
+//}

+ 9 - 5
warewms-ams/src/main/java/com/ruoyi/ams/asn/form/StockForm.java

@@ -12,17 +12,21 @@ import java.util.List;
  */
 @Data
 public class StockForm {
+    // 扫描入库单号
     private List<String> asnNo;
+    // 扫码出库单(非必填)
     private String orderNo;
-    //是否备货
+    // 是否备货(是的情况下出库单必填)
     private String stockTag;
-    //是否满托
-    private String fullTag;
-    //托盘编号
+    // 托盘编号
     private String palletNo;
+    // 产品条码(唯一,验证条码是否重复扫描)
     private String skuSn;
+    // 是否满托
+    private String fullTag;
+
     //private String sku;
     private String desc;
     private String model;
     private String qty;
-}
+}

+ 3 - 2
warewms-ams/src/main/java/com/ruoyi/ams/asn/mapper/WmsDocAsnHeaderMapper.java

@@ -120,10 +120,11 @@ public interface WmsDocAsnHeaderMapper {
     List<SearchStockVO> searchStock(@Param("palletNo") String palletNo,@Param("sku") String sku);
 
     /**
-     * 根据入库单号查询接收数
+     * 根据入库单号和产品编号查询接收数
      *
      * @param asnNoList
-     * @return
+     * @param sku
+     * @return 未接受数量
      */
     Double selectReceivedQtyByAsnNos(@Param("sku") String sku, @Param("list") List<String> asnNoList);
 }

+ 16 - 14
warewms-ams/src/main/java/com/ruoyi/ams/asn/service/IWmsDocAsnHeaderService.java

@@ -102,7 +102,7 @@ public interface IWmsDocAsnHeaderService {
     WmsDocAsnDetails queryWmsDocAsnDetailsOne(String asnNo, int asnLineNo);
 
     /**
-     * 码盘
+     * 入库码盘
      *
      * @param stockForm
      * @return
@@ -110,20 +110,20 @@ public interface IWmsDocAsnHeaderService {
     AjaxResult doStock(StockForm stockForm);
 
     /**
-     * 上架
+     * 条码检测
      *
-     * @param paForm
+     * @param snCheckForm
      * @return
      */
-    AjaxResult doPa(PaForm paForm);
+    CodeSkuRelationshipVO searchSn(SnCheckForm snCheckForm);
 
     /**
-     * 查询已码盘
+     * 上架
      *
-     * @param palletNo
+     * @param paForm
      * @return
      */
-    List<SearchStockVO> searchStock(String palletNo, String sku);
+    AjaxResult doPa(PaForm paForm);
 
     /**
      * 解绑物料
@@ -133,6 +133,15 @@ public interface IWmsDocAsnHeaderService {
      */
     AjaxResult unloadStock(UnlockForm unlockForm);
 
+    /**
+     * 查询已码盘
+     *
+     * @param palletNo
+     * @return
+     */
+    List<SearchStockVO> searchStock(String palletNo, String sku);
+
+
     /**
      * 检查关闭表头
      *
@@ -148,13 +157,6 @@ public interface IWmsDocAsnHeaderService {
      */
     List<WmsDocAsnDetails> selectStockingList(List<String> asnNos);
 
-    /**
-     * 条码检测
-     *
-     * @param snCheckForm
-     * @return
-     */
-    CodeSkuRelationshipVO searchSn(SnCheckForm snCheckForm);
 
     void addOrUpdateErp(List<ErpOrderList> erpOrderList);
 }

+ 40 - 22
warewms-ams/src/main/java/com/ruoyi/ams/asn/service/impl/WmsDocAsnHeaderServiceImpl.java

@@ -311,10 +311,11 @@ public class WmsDocAsnHeaderServiceImpl implements IWmsDocAsnHeaderService {
         //当前订单总数
         BigDecimal totalQty = new BigDecimal(stockForm.getQty());
 
-        //产品条码属于出入库单
+        //备货入库
         if (stockForm.getStockTag().equals("Y") && StringUtils.isEmpty(stockForm.getOrderNo())) {
             return AjaxResult.error("备货必须选择出库单号");
         }
+        //校验出库单
         if (stockForm.getStockTag().equals("Y")) {
             //查询出库单
             wmsDocOrderHeader = wmsDocOrderHeaderService.selectWmsDocOrderHeaderByOrderNo(stockForm.getOrderNo());
@@ -368,10 +369,12 @@ public class WmsDocAsnHeaderServiceImpl implements IWmsDocAsnHeaderService {
             wmsDocOrderHeaderService.updateWmsDocOrderHeader(wmsDocOrderHeader);
         }
 
+        // 不同的产品分类不允许放一个托盘上 todo 这边写的应该是有问题
         if (checkSameTypeByPalletNo(stockForm.getPalletNo(), codeSkuRelationshipVO.getSku()) == false) {
             throw new ServiceException("不同的产品分类不允许放一个托盘上");
         }
 
+        // 成品数量默认为1
         if (codeSkuRelationshipVO.isProduct()) {
             stockForm.setQty(BigDecimal.ONE.toString());
             totalQty = BigDecimal.ONE;
@@ -433,7 +436,7 @@ public class WmsDocAsnHeaderServiceImpl implements IWmsDocAsnHeaderService {
                                 wmsDocAsnDetailsMapper.updateWmsDocAsnDetails(updateDetails);
                             }
 
-                            //TODO 检查头单状态
+                            //修改头单状态
                             WmsDocAsnDetails detailsQuery = new WmsDocAsnDetails();
                             detailsQuery.setAsnNo(details.getAsnNo());
                             List<WmsDocAsnDetails> detailsCheckList = wmsDocAsnDetailsMapper.selectWmsDocAsnDetailsList(detailsQuery);
@@ -472,6 +475,30 @@ public class WmsDocAsnHeaderServiceImpl implements IWmsDocAsnHeaderService {
         return AjaxResult.success("操作成功");
     }
 
+    /**
+     * 条码检测
+     * 根据入库单和条码查询出未码盘的信息
+     *
+     * @param snCheckForm
+     * @return
+     */
+    @Override
+    public CodeSkuRelationshipVO searchSn(SnCheckForm snCheckForm) {
+        // 根据条码号查询出产品信息
+        CodeSkuRelationshipVO codeSkuRelationshipVO = codeSkuRelationshipService.snCheck(snCheckForm.getSn());
+        if (snCheckForm.getAsnNoList() != null && snCheckForm.getAsnNoList().size() > 0) {
+            // 根据入库单和产品编号拿到未码盘的数量
+            Double receivedQty = wmsDocAsnHeaderMapper.selectReceivedQtyByAsnNos(codeSkuRelationshipVO.getSku(), snCheckForm.getAsnNoList());
+            if (receivedQty == null) {
+                receivedQty = 0d;
+            }
+            codeSkuRelationshipVO.setReceivedQty(receivedQty);
+        } else {
+            codeSkuRelationshipVO.setReceivedQty(0d);
+        }
+        return codeSkuRelationshipVO;
+    }
+
     @Transactional
     @Override
     public AjaxResult doPa(PaForm paForm) {
@@ -528,11 +555,12 @@ public class WmsDocAsnHeaderServiceImpl implements IWmsDocAsnHeaderService {
         return AjaxResult.success("操作成功");
     }
 
-    @Override
-    public List<SearchStockVO> searchStock(String palletNo, String sku) {
-        return wmsDocAsnHeaderMapper.searchStock(palletNo, sku);
-    }
-
+    /**
+     * 解绑物料
+     *
+     * @param unlockForm
+     * @return
+     */
     @Transactional
     @Override
     public AjaxResult unloadStock(UnlockForm unlockForm) {
@@ -582,6 +610,11 @@ public class WmsDocAsnHeaderServiceImpl implements IWmsDocAsnHeaderService {
         return AjaxResult.success("解绑成功");
     }
 
+    @Override
+    public List<SearchStockVO> searchStock(String palletNo, String sku) {
+        return wmsDocAsnHeaderMapper.searchStock(palletNo, sku);
+    }
+
     @Override
     public int closeHeader(String asnNo) {
         WmsDocAsnHeader wmsDocAsnHeader = wmsDocAsnHeaderMapper.selectWmsDocAsnHeaderByAsnNo(asnNo);
@@ -597,21 +630,6 @@ public class WmsDocAsnHeaderServiceImpl implements IWmsDocAsnHeaderService {
         return wmsDocAsnDetailsMapper.selectStockingList(asnNos);
     }
 
-    @Override
-    public CodeSkuRelationshipVO searchSn(SnCheckForm snCheckForm) {
-        CodeSkuRelationshipVO codeSkuRelationshipVO = codeSkuRelationshipService.snCheck(snCheckForm.getSn());
-        if (snCheckForm.getAsnNoList() != null && snCheckForm.getAsnNoList().size() > 0) {
-            Double receivedQty = wmsDocAsnHeaderMapper.selectReceivedQtyByAsnNos(codeSkuRelationshipVO.getSku(), snCheckForm.getAsnNoList());
-            if (receivedQty == null) {
-                receivedQty = 0d;
-            }
-            codeSkuRelationshipVO.setReceivedQty(receivedQty);
-        } else {
-            codeSkuRelationshipVO.setReceivedQty(0d);
-        }
-        return codeSkuRelationshipVO;
-    }
-
     @Transactional
     @Override
     public void addOrUpdateErp(List<ErpOrderList> erpOrderList) {

+ 19 - 19
warewms-ams/src/main/java/com/ruoyi/ams/business/BusinessServiceImpl.java

@@ -108,6 +108,22 @@ public class BusinessServiceImpl implements IBusinessService {
         return this.agvCall(flowConfigHeaderVO, list);
     }
 
+    @Override
+    public AjaxResult agvCall(FlowConfigHeaderVO flowConfigHeaderVO, AgvCallDTO agvCallDTO) {
+        List<AgvCallDTO> agvCallDTOList = new ArrayList<>();
+        List<AgvCallItemDTO> callItemDTOList = new ArrayList<>();
+        AgvCallItemDTO callItemDTO = new AgvCallItemDTO();
+        callItemDTO.setLocationFrom(agvCallDTO.getLocationFrom());
+        callItemDTO.setLocationTo(agvCallDTO.getLocationTo());
+        callItemDTO.setWarehouseId(agvCallDTO.getWarehouseId());
+        callItemDTO.setLotattDTO(new LotattDTO());
+        callItemDTO.setExtParam(agvCallDTO.getExtParam());
+        callItemDTOList.add(callItemDTO);
+        agvCallDTO.setAgvCallItemDTOList(callItemDTOList);
+        agvCallDTOList.add(agvCallDTO);
+        return businessService.agvCall(flowConfigHeaderVO, agvCallDTOList);
+    }
+
     @Transactional
     @Override
     public AjaxResult agvCall(FlowConfigHeaderVO flowConfigHeaderVO, List<AgvCallDTO> agvCallDTOList) {
@@ -184,22 +200,6 @@ public class BusinessServiceImpl implements IBusinessService {
         }
     }
 
-    @Override
-    public AjaxResult agvCall(FlowConfigHeaderVO flowConfigHeaderVO, AgvCallDTO agvCallDTO) {
-        List<AgvCallDTO> agvCallDTOList = new ArrayList<>();
-        List<AgvCallItemDTO> callItemDTOList = new ArrayList<>();
-        AgvCallItemDTO callItemDTO = new AgvCallItemDTO();
-        callItemDTO.setLocationFrom(agvCallDTO.getLocationFrom());
-        callItemDTO.setLocationTo(agvCallDTO.getLocationTo());
-        callItemDTO.setWarehouseId(agvCallDTO.getWarehouseId());
-        callItemDTO.setLotattDTO(new LotattDTO());
-        callItemDTO.setExtParam(agvCallDTO.getExtParam());
-        callItemDTOList.add(callItemDTO);
-        agvCallDTO.setAgvCallItemDTOList(callItemDTOList);
-        agvCallDTOList.add(agvCallDTO);
-        return businessService.agvCall(flowConfigHeaderVO, agvCallDTOList);
-    }
-
     @Transactional
     @Override
     public BaseLocationInfo inLocationAllocation(InWarehouseDTO inWarehouseDTO, Long token) {
@@ -322,7 +322,7 @@ public class BusinessServiceImpl implements IBusinessService {
                     break;
                 }
                 if (locationInfo == null) {
-                    throw new ServiceException("没有可以分配的库位", token);
+                    throw new ServiceException("目标点没有可以分配的库位", token);
                 }
             }
         } else if (type.equals("SO")) {
@@ -339,7 +339,7 @@ public class BusinessServiceImpl implements IBusinessService {
                     break;
                 }
                 if (locationInfo == null) {
-                    throw new ServiceException("没有可以分配的库位", token);
+                    throw new ServiceException("起始点没有可以分配的库存!", token);
                 }
 
             } else { //目标库位
@@ -354,7 +354,7 @@ public class BusinessServiceImpl implements IBusinessService {
                     break;
                 }
                 if (locationInfo == null) {
-                    throw new ServiceException("没有可以分配的库位", token);
+                    throw new ServiceException("目标点没有可以分配的库位", token);
                 }
             }
         } else { //移库

+ 5 - 4
warewms-ams/src/main/java/com/ruoyi/ams/business/IBusinessService.java

@@ -31,19 +31,20 @@ public interface IBusinessService {
      * AGV呼叫业务
      *
      * @param flowConfigHeaderVO
-     * @param agvCallDTOList
+     * @param agvCallDTO
      * @return
      */
-    AjaxResult agvCall(FlowConfigHeaderVO flowConfigHeaderVO, List<AgvCallDTO> agvCallDTOList);
+    AjaxResult agvCall(FlowConfigHeaderVO flowConfigHeaderVO, AgvCallDTO agvCallDTO);
 
     /**
      * AGV呼叫业务
      *
      * @param flowConfigHeaderVO
-     * @param agvCallDTO
+     * @param agvCallDTOList
      * @return
      */
-    AjaxResult agvCall(FlowConfigHeaderVO flowConfigHeaderVO, AgvCallDTO agvCallDTO);
+    AjaxResult agvCall(FlowConfigHeaderVO flowConfigHeaderVO, List<AgvCallDTO> agvCallDTOList);
+
 
     /**
      * 入库库位分配

+ 4 - 0
warewms-ams/src/main/java/com/ruoyi/ams/erp/service/impl/SyncServiceImpl.java

@@ -49,6 +49,7 @@ public class SyncServiceImpl implements ISyncService {
 
     @Override
     public void syncSkuType() {
+        // 产品类型基础表
         List<JSONObject> list = (List<JSONObject>) redisTemplate.opsForValue().get("erpProType");
         if (list != null && list.size() > 0) {
             for (JSONObject erpProType : list) {
@@ -66,6 +67,7 @@ public class SyncServiceImpl implements ISyncService {
     @Transactional
     @Override
     public void syncSku() {
+        // 品号基础表
         List<JSONObject> list = (List<JSONObject>) redisTemplate.opsForValue().get("erpProOb");
         if (list != null && list.size() > 0) {
             for (JSONObject jsonObject : list) {
@@ -89,6 +91,7 @@ public class SyncServiceImpl implements ISyncService {
 
     @Override
     public void syncSkuBarcode() {
+        // 条码品号对照表
         List<JSONObject> list = (List<JSONObject>) redisTemplate.opsForValue().get("erpBarCode");
         if (list != null && list.size() > 0) {
             for (JSONObject code : list) {
@@ -104,6 +107,7 @@ public class SyncServiceImpl implements ISyncService {
 
     @Override
     public void syncOrderList() {
+        // ERP需求单
         List<JSONObject> list = (List<JSONObject>) redisTemplate.opsForValue().get("erpOrderList");
         if (list != null && list.size() > 0) {
             Map<String, List<ErpOrderList>> inmap = new HashMap<>();

+ 11 - 0
warewms-ams/src/main/java/com/ruoyi/ams/inv/service/IInvLotLocIdService.java

@@ -4,6 +4,7 @@ import java.math.BigDecimal;
 import java.util.List;
 
 import com.ruoyi.ams.asn.vo.StockingListVO;
+import com.ruoyi.ams.config.domain.dto.AgvCallDTO;
 import com.ruoyi.ams.config.domain.dto.LotattDTO;
 import com.ruoyi.ams.inv.domain.InvLotAtt;
 import com.ruoyi.ams.inv.domain.InvLotLocId;
@@ -186,6 +187,16 @@ public interface IInvLotLocIdService {
      */
     String initInv(String locationFrom, String sku, String customerId, Double qty, LotattDTO lotattDTO, BigDecimal qtyallocated);
 
+    /**
+     * 初始化库存
+     *
+     * @param locationId
+     * @param agvCallDTO
+     * @return
+     */
+    String initInv(String locationId, AgvCallDTO agvCallDTO);
+
+
     /**
      * 根据库位id查询库位库存包含批次属性
      *

+ 66 - 1
warewms-ams/src/main/java/com/ruoyi/ams/inv/service/impl/InvLotLocIdServiceImpl.java

@@ -3,6 +3,9 @@ package com.ruoyi.ams.inv.service.impl;
 import com.ruoyi.ams.asn.vo.StockingListVO;
 import com.ruoyi.ams.box.domain.WmsBoxInfo;
 import com.ruoyi.ams.box.service.IWmsBoxInfoService;
+import com.ruoyi.ams.business.IBusinessService;
+import com.ruoyi.ams.config.domain.dto.AgvCallDTO;
+import com.ruoyi.ams.config.domain.dto.AgvCallItemDTO;
 import com.ruoyi.ams.config.domain.dto.LotattDTO;
 import com.ruoyi.ams.inv.domain.ActTransactionLog;
 import com.ruoyi.ams.inv.domain.InvLotAtt;
@@ -14,6 +17,7 @@ import com.ruoyi.ams.inv.domain.vo.InvLotLocIdLotattVO;
 import com.ruoyi.ams.inv.mapper.InvLotAttMapper;
 import com.ruoyi.ams.inv.mapper.InvLotLocIdMapper;
 import com.ruoyi.ams.inv.service.IInvLotLocIdService;
+import com.ruoyi.ams.task.domain.WcsTask;
 import com.ruoyi.base.constant.Constant;
 import com.ruoyi.base.domain.BaseLocationInfo;
 import com.ruoyi.base.service.IBaseLocationInfoService;
@@ -56,6 +60,8 @@ public class InvLotLocIdServiceImpl implements IInvLotLocIdService {
     private IWmsBoxInfoService iWmsBoxInfoService;
     @Autowired
     private IInvLotLocIdService invLotLocIdService;
+    @Autowired
+    private IBusinessService iBusinessService;
 
     /**
      * 查询库位库存信息
@@ -207,7 +213,26 @@ public class InvLotLocIdServiceImpl implements IInvLotLocIdService {
         baseLocationFrom = baseLocationInfoService.selectBaseLocationInfoByIdOrNo(locationFrom, warehouseId);
         baseLocationTo = baseLocationInfoService.selectBaseLocationInfoByIdOrNo(locationTo, warehouseId);
 
-        // todo 下发移库任务
+        // 下发移库任务
+        String taskNo = System.currentTimeMillis() + "";
+        WcsTask wcsTask = new WcsTask();
+        wcsTask.setTaskNo(taskNo);
+        if (locationFrom != null) {
+            wcsTask.setAreaFrom(baseLocationFrom.getZoneId().toString());
+            wcsTask.setLocationFrom(baseLocationFrom.getId().toString());
+        }
+        if (locationTo != null) {
+            wcsTask.setAreaTo(baseLocationTo.getZoneId() + "");
+            wcsTask.setLocationTo(baseLocationTo.getId().toString());
+        }
+        wcsTask.setState(9L);
+        wcsTask.setPriority(1L);
+        wcsTask.setShopId(Constant.WAREHOUSE_ID.toString());
+        wcsTask.setCreateDate(new Date());
+        wcsTask.setBusinessType("01");
+        wcsTask.setTaskType(Constant.TASK_TYPE.FORWARD.getValue());
+        wcsTask.setExt8("");
+        iBusinessService.addTask(wcsTask);
 
         // 锁定起始和目标库位任务状态
         baseLocationInfoService.lockLocationStockStatus(baseLocationFrom.getId(), baseLocationTo.getId()
@@ -500,6 +525,46 @@ public class InvLotLocIdServiceImpl implements IInvLotLocIdService {
         return lotnum;
     }
 
+    @Transactional
+    @Override
+    public String initInv(String locationId, AgvCallDTO agvCallDTO) {
+        String customerId = Constant.CUSTOMER_ID;
+        List<AgvCallItemDTO> agvCallItemDTOList = agvCallDTO.getAgvCallItemDTOList();
+        for (AgvCallItemDTO agvCallItemDTO : agvCallItemDTOList) {
+            String sku = agvCallItemDTO.getSku();
+            Double qty = agvCallItemDTO.getQty() == null ? 1D : agvCallItemDTO.getQty();
+            // 批次表
+            String lotnum = idSequenceUtils.generateId("LOTNUMBER");
+            LotattDTO lotattDTO = agvCallItemDTO.getLotattDTO();
+            InvLotAtt invLotAtt = new InvLotAtt();
+            BeanUtils.copyProperties(lotattDTO, invLotAtt);
+            invLotAtt.setCustomerId(customerId);
+            invLotAtt.setSku(sku);
+            invLotAtt.setLotnum(lotnum);
+            invLotAtt.setCreateTime(DateUtils.getNowDate());
+            invLotAttMapper.insertInvLotAtt(invLotAtt);
+            // 库存表
+            InvLotLocId invLotLocId = new InvLotLocId();
+            invLotLocId.setLotnum(lotnum);
+            invLotLocId.setLocationId(locationId);
+            invLotLocId.setSku(sku);
+            invLotLocId.setCustomerId(customerId);
+            invLotLocId.setQty(new BigDecimal(qty));
+            invLotLocId.setQtyEach(new BigDecimal(qty));
+            invLotLocId.setQtyallocated(BigDecimal.ZERO);
+            invLotLocId.setQtyallocatedEach(BigDecimal.ZERO);
+            invLotLocId.setQtypa(BigDecimal.ZERO);
+            invLotLocId.setQtyrpin(BigDecimal.ZERO);
+            invLotLocId.setCreateTime(new Date());
+            invLotLocIdMapper.insertInvLotLocId(invLotLocId);
+        }
+        BaseLocationInfo baseLocationInfo = new BaseLocationInfo();
+        baseLocationInfo.setId(Long.parseLong(locationId));
+        baseLocationInfo.setIsEmpty("N");
+        baseLocationInfoService.updateBaseLocationInfo(baseLocationInfo);
+        return "";
+    }
+
     @Override
     public List<InvLotLocIdLotattVO> selectInvLocIdLotattByLocationId(Long locationId) {
         return invLotLocIdMapper.selectInvLocIdLotattByLocationId(locationId);

+ 9 - 36
warewms-ams/src/main/java/com/ruoyi/ams/task/service/impl/WcsTaskServiceImpl.java

@@ -180,47 +180,13 @@ public class WcsTaskServiceImpl implements IWcsTaskService {
     @Transactional
     @Override
     public void callBackTaskComplete(WcsTask wcsTask) {
-        BaseLocationInfo bt = null;
-        BaseLocationInfo bf = null;
-
-        //设置目标库位为占用状态
-        if (!StringUtils.isEmpty(wcsTask.getLocationTo())) {
-            bt = baseLocationInfoService.selectBaseLocationInfoById(Long.parseLong(wcsTask.getLocationTo()));
-            if (bt != null) {
-                bt.setIsEmpty("N");
-                bt.setStockStatus("00");
-                baseLocationInfoService.updateBaseLocationInfo(bt);
-            }
-        }
-
-        // 释放起始库位
-        if (!StringUtils.isEmpty(wcsTask.getLocationFrom())) {
-            bf = baseLocationInfoService.selectBaseLocationInfoById(Long.parseLong(wcsTask.getLocationFrom()));
-            if (bf != null) {
-                bf.setIsEmpty("Y");
-                bf.setStockStatus("00");
-                baseLocationInfoService.updateBaseLocationInfo(bf);
-            }
-            baseLocationInfoService.updateLocationStockStatus(Long.parseLong(wcsTask.getLocationFrom()), "00");
-        }
-
-        //释放redis锁
-        if (!StringUtils.isEmpty(wcsTask.getExt8())) {
-            redisCache.unlockCacheObject(Long.parseLong(wcsTask.getExt8()));
-        }
-
 
         if (!StringUtils.isEmpty(wcsTask.getLocationFrom()) && !StringUtils.isEmpty(wcsTask.getLocationTo())) {
-            invLotLocIdMapper.updateInvLotLocIdLocationId(Long.parseLong(wcsTask.getLocationFrom()), Long.parseLong(wcsTask.getLocationTo()));
             //更新托盘绑定关系
             wmsBoxInfoService.updateLocationBind(Long.parseLong(wcsTask.getLocationFrom()), Long.parseLong(wcsTask.getLocationTo()), null);
         }
 
-        this.eventCallBack("543", wcsTask);
-
-        //修改任务状态
-        wcsTask.setState(2L);
-        wcsTaskMapper.updateWcsTask(wcsTask);
+//        this.eventCallBack("543", wcsTask);
     }
 
     @Transactional
@@ -272,6 +238,7 @@ public class WcsTaskServiceImpl implements IWcsTaskService {
 
     @Override
     public void eventCallBack(String code, WcsTask wcsTask) {
+        // Ext7流程配置id
         if (!StringUtils.isEmpty(wcsTask.getExt7())) {
             FlowConfigEvent flowConfigEvent = new FlowConfigEvent();
             flowConfigEvent.setEventCode(code);
@@ -349,6 +316,8 @@ public class WcsTaskServiceImpl implements IWcsTaskService {
                             if (!StringUtils.isEmpty(wcsTask.getExt8())) {
                                 redisCache.unlockCacheObject(Long.parseLong(wcsTask.getExt8()));
                             }
+                            // 任务完成回调
+                            callBackTaskComplete(wcsTask);
                         }
                         break;
                     case 3:
@@ -368,6 +337,8 @@ public class WcsTaskServiceImpl implements IWcsTaskService {
                         if (!StringUtils.isEmpty(wcsTask.getExt8())) {
                             redisCache.unlockCacheObject(Long.parseLong(wcsTask.getExt8()), wcsTask.getLocationFrom());
                         }
+                        //取货完成回调
+                        callBackPickup(wcsTask);
                         break;
                     case 5:
                         break;
@@ -383,10 +354,12 @@ public class WcsTaskServiceImpl implements IWcsTaskService {
                                     , Constant.WAREHOUSE_ID, updateBy);
                             // 将中间缓存位库存移动到终点
                             moveMiddleCacheToDestination(wcsTask);
-                            //释放redis锁
+                            // 释放redis锁
                             if (!StringUtils.isEmpty(wcsTask.getExt8())) {
                                 redisCache.unlockCacheObject(Long.parseLong(wcsTask.getExt8()));
                             }
+                            // 任务完成回调
+                            callBackTaskComplete(wcsTask);
                         }
                         break;
                     case 7://取消

+ 1 - 1
warewms-ams/src/main/resources/mapper/ams/InvLotLocIdMapper.xml

@@ -595,7 +595,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
          left join inv_lot_att att on inv.lotnum = att.lotnum
          left join base_sku sk on inv.sku = sk.sku
         where
-        att.lotatt12 = #{palletNo} and sk.sku_type <![CDATA[ <> ]]> #{skuType}
+        att.lotatt07 = #{palletNo} and sk.sku_type <![CDATA[ <> ]]> #{skuType}
     </select>
 
     <select id="selectInvLotLocIdBySkuLocationSort" resultMap="InvLotLocIdResult">

+ 4 - 3
warewms-ams/src/main/resources/mapper/docAsn/WmsDocAsnHeaderMapper.xml

@@ -3,7 +3,7 @@
 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.ruoyi.ams.asn.mapper.WmsDocAsnHeaderMapper">
-    
+
     <resultMap type="WmsDocAsnHeader" id="WmsDocAsnHeaderResult">
         <result property="asnNo"    column="asn_no"    />
         <result property="asnType"    column="asn_type"    />
@@ -431,11 +431,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </select>
 
     <select id="selectReceivedQtyByAsnNos" resultType="double">
-        select ifnull(sum(expected_qty),0) - ifnull(sum(received_qty),0) received_qty from wms_doc_asn_details
+        select ifnull(sum(expected_qty),0) - ifnull(sum(received_qty),0) received_qty
+        from wms_doc_asn_details
         where sku = #{sku} and expected_qty - received_qty > 0 and asn_no in
         <foreach item="item" index="index" collection="list" separator=",">
             (#{item})
         </foreach>
         group by sku
     </select>
-</mapper>
+</mapper>

+ 1 - 0
warewms-base/src/main/java/com/ruoyi/base/service/impl/CodeSkuRelationshipServiceImpl.java

@@ -127,6 +127,7 @@ public class CodeSkuRelationshipServiceImpl implements ICodeSkuRelationshipServi
 
     /**
      * 条码检测
+     * 输入条码号返回产品信息
      *
      * @param sn
      * @return