自动化立体仓库 - WMS系统
pang.jiabao
2024-07-06 0e8aae27274c1b1b7a283ba73963af78417202c3
冠鸿接口对接
20个文件已修改
6个文件已添加
1368 ■■■■ 已修改文件
src/main/java/com/zy/asrs/controller/MobileController.java 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/OpenController.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/OutController.java 222 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/WrkMast.java 25 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/param/CrnExecuteParam.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/param/GhjtApiParam.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/param/GwmsGenerateInventoryDto.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/param/ZwmsOutLocWorkDto.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/LocMastMapper.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/LocMastService.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/MobileService.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/OpenService.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/LocMastServiceImpl.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/MobileServiceImpl.java 32 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/OpenServiceImpl.java 394 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/WorkServiceImpl.java 59 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/GhjtScheduler.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/WorkMastScheduler.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/handler/GhjtHandler.java 139 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/handler/WorkLogHandler.java 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/task/handler/WorkMastHandler.java 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/utils/Utils.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/service/CommonService.java 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/LocMastMapper.xml 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/OrderDetlMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/static/js/order/out.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/MobileController.java
@@ -2,8 +2,6 @@
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.core.annotations.AppAuth;
import com.core.annotations.ManagerAuth;
import com.core.common.BaseRes;
import com.core.common.Cools;
@@ -20,9 +18,7 @@
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.List;
/**
 * 移动端接口控制器
@@ -547,4 +543,15 @@
        return R.ok("出库成功");
    }
    @PostMapping("/ckfh/auth")
    @ManagerAuth(memo = "出库复核确认")
    public synchronized R pakoutFhqr(@RequestBody GhjtApiParam param) {
        // 根据工作号确认复核
        if(Cools.isEmpty(param) || Cools.isEmpty(param.getWorkNo()) || Cools.isEmpty(param.getCheck())){
            return R.parse(BaseRes.PARAM);
        }
        mobileService.pakoutFhqr(param.getWorkNo(), param.getCheck());
        return R.ok("复核确认成功");
    }
}
src/main/java/com/zy/asrs/controller/OpenController.java
@@ -2,11 +2,11 @@
import com.alibaba.fastjson.JSON;
import com.core.annotations.AppAuth;
import com.core.common.*;
import com.core.common.Cools;
import com.core.common.R;
import com.core.exception.CoolException;
import com.zy.asrs.entity.param.*;
import com.zy.asrs.service.OpenService;
import com.zy.common.model.DetlDto;
import com.zy.common.web.BaseController;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@@ -14,8 +14,6 @@
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
 * Created by vincent on 2022/4/8
@@ -149,6 +147,61 @@
        }
    }
    @PostMapping("/scrk")
    @AppAuth(memo = "GWMS调用生成入库工作档")
    public synchronized R gwmsGenerateInventory(@RequestHeader(required = false) String appkey,
                                      @RequestBody GwmsGenerateInventoryDto param,
                                      HttpServletRequest request) {
        auth(appkey, param, request);
        return R.ok(openService.gwmsGenerateInventory(param));
    }
    @PostMapping("/zxrk")
    @AppAuth(memo = "GWCS到达堆垛机入库站点请求ZWCS执行")
    public synchronized R crnExecute(@RequestHeader(required = false) String appkey,
                                                @RequestBody CrnExecuteParam param,
                                                HttpServletRequest request) {
        auth(appkey, param, request);
        return R.ok(openService.crnExecute(param));
    }
    @PostMapping("/ckrw")
    @AppAuth(memo = "ZWMS接收MES下发出库任务")
    public synchronized R zwmsOutLocWork(@RequestHeader(required = false) String appkey,
                                     @RequestBody ZwmsOutLocWorkDto param,
                                     HttpServletRequest request) {
        auth(appkey, param, request);
        return R.ok(openService.zwmsOutLocWork(param));
    }
    @PostMapping("/ckjgsb")
    @AppAuth(memo = "货物到达出库口以后,上报出库结果")
    public synchronized R outLocResultReport(@RequestHeader(required = false) String appkey,
                                         @RequestBody GhjtApiParam param,
                                         HttpServletRequest request) {
        auth(appkey, param, request);
        return R.ok(openService.outLocResultReport(param));
    }
    @PostMapping("/cpjck")
    @AppAuth(memo = "拆盘机出库接口")
    public synchronized R emptyOutLoc(@RequestHeader(required = false) String appkey,
                                             @RequestBody GhjtApiParam param,
                                             HttpServletRequest request) {
        auth(appkey, param, request);
        return R.ok(openService.emptyOutLoc(param));
    }
//    @PostMapping("/cpjck")
//    @AppAuth(memo = "物料信息获取")
//    public synchronized R emptyOutLoc(@RequestHeader(required = false) String appkey,
//                                      @RequestBody GhjtApiParam param,
//                                      HttpServletRequest request) {
//        auth(appkey, param, request);
//        return R.ok(openService.emptyOutLoc(param));
//    }
    /*public static void main(String[] args) {
        // 1
        System.out.println("======================================");
src/main/java/com/zy/asrs/controller/OutController.java
@@ -1,14 +1,11 @@
package com.zy.asrs.controller;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.core.annotations.ManagerAuth;
import com.core.common.*;
import com.core.exception.CoolException;
import com.zy.asrs.entity.*;
import com.zy.asrs.entity.param.StockOutParam;
import com.zy.asrs.service.*;
import com.zy.asrs.service.impl.WorkServiceImpl;
import com.zy.asrs.utils.OutboundAllocationUtil;
import com.zy.common.model.DetlDto;
import com.zy.common.model.LocDto;
import com.zy.common.model.TaskDto;
import com.zy.common.web.BaseController;
@@ -65,46 +62,65 @@
        }
        List<OrderDetl> orderDetls = orderDetlService.selectBatchIds(ids);
        List<LocDto> locDtos = new ArrayList<>();
        for (OrderDetl orderDetl : orderDetls) {
            if (orderDetl.getAnfme()-orderDetl.getWorkQty()-orderDetl.getQty()==0.0){
                continue;
            }
            LocDto locDto = new LocDto(orderDetl.getManu(), orderDetl.getMatnr(), orderDetl.getMaktx(),orderDetl.getModel(),orderDetl.getSpecs(),
                    orderDetl.getBatch(),orderDetl.getBrand(),orderDetl.getBarcode(), orderDetl.getOrderNo(),orderDetl.getAnfme());
            locDto.setOrderDetlId(orderDetl.getId());
            locDto.setTkType(orderDetl.getTkType());
            locDtos.add(locDto);
        }
//        Set<String> exist = new HashSet<>();
//        for (OrderDetl orderDetl : orderDetls) {
//            double issued = Optional.of(orderDetl.getAnfme() - orderDetl.getWorkQty()).orElse(0.0D);
//            if (issued <= 0.0D) { continue; }
//            if (orderDetl.getAnfme()-orderDetl.getWorkQty()-orderDetl.getQty()==0.0){
//                continue;
//            }
//            LocDto locDto = new LocDto(orderDetl.getManu(), orderDetl.getMatnr(), orderDetl.getMaktx(),orderDetl.getModel(),orderDetl.getSpecs(),
//                    orderDetl.getBatch(),orderDetl.getBrand(),orderDetl.getBarcode(), orderDetl.getOrderNo(),orderDetl.getAnfme());
//            locDto.setOrderDetlId(orderDetl.getId());
//            locDto.setTkType(orderDetl.getTkType());
//            locDtos.add(locDto);
//        }
        Set<String> exist = new HashSet<>();
        for (OrderDetl orderDetl : orderDetls) {
            double issued = Optional.of(orderDetl.getAnfme() - orderDetl.getWorkQty()).orElse(0.0D);
            if (issued <= 0.0D) { continue; }
//            List<LocDetl> locDetls = locDetlService.queryStock(orderDetl.getMatnr(), orderDetl.getBatch(), null, exist);
//            for (LocDetl locDetl : locDetls) {
//                if (issued > 0) {
            List<LocDetl> locDetls = locDetlService.selectList(new EntityWrapper<LocDetl>().eq("batch",orderDetl.getBatch()).eq("model",orderDetl.getModel()));
            for (LocDetl locDetl : locDetls) {
                if (issued > 0) {
                    LocDto locDto = new LocDto(orderDetl.getManu(), orderDetl.getMatnr(), orderDetl.getMaktx(),orderDetl.getModel(),orderDetl.getSpecs(),
                    orderDetl.getBatch(),orderDetl.getBrand(),orderDetl.getBarcode(), orderDetl.getOrderNo(),orderDetl.getAnfme());
//                    LocDto locDto = new LocDto(locDetl.getLocNo(), locDetl.getMatnr(), locDetl.getMaktx(), locDetl.getBatch(), orderDetl.getOrderNo(),
//                            issued >= locDetl.getAnfme() ? locDetl.getAnfme() : issued);
//                    List<Integer> staNos = staDescService.queryOutStaNosByLocNo(locDetl.getLocNo(), issued >= locDetl.getAnfme() ? 101 : 103);
//                    locDto.setStaNos(staNos);
//                    locDtos.add(locDto);
//                    exist.add(locDetl.getLocNo());
//                    // 剩余待出数量递减
//                    issued = issued - locDetl.getAnfme();
//                } else {
//                    break;
//                }
//            }
//            if (issued > 0) {
//                LocDto locDto = new LocDto(null, orderDetl.getMatnr(), orderDetl.getMaktx(), orderDetl.getBatch(), orderDetl.getOrderNo(), issued);
//                locDto.setLack(Boolean.TRUE);
//                locDtos.add(locDto);
//            }
//        }
                    List<Integer> staNos = staDescService.queryOutStaNosByLocNo(locDetl.getLocNo(), issued >= locDetl.getAnfme() ? 101 : 103);
                    locDto.setLocNo(locDetl.getLocNo());
//                    wrkDetl.setMatnr(roll.getSpecs()); // 规格
//                    wrkDetl.setMaktx(roll.getSpecs()); //规格
                    locDto.setBatch(locDetl.getBatch()); // 箱号
                    locDto.setModel(locDetl.getModel()); // 卷号
                    locDto.setBrand(""); // 木箱类型
                    locDto.setOrigin(locDetl.getOrigin()); // 木箱在托盘位置
                    locDto.setWeight(locDetl.getWeight()); // 净重
                    locDto.setVolume(locDetl.getVolume()); // 毛重
                    locDto.setPrice(locDetl.getPrice());
                    locDto.setSpecs(locDetl.getSpecs());
                    locDto.setZpallet(locDetl.getZpallet());
                    locDto.setStaNos(staNos);
                    locDto.setOrderDetlId(orderDetl.getId());
                    locDtos.add(locDto);
                    exist.add(locDetl.getLocNo());
                    // 剩余待出数量递减
                    issued = issued - locDetl.getAnfme();
                } else {
                    break;
                }
            }
            if (issued > 0) {
                LocDto locDto = new LocDto(null, orderDetl.getMatnr(), orderDetl.getMaktx(), orderDetl.getBatch(), orderDetl.getOrderNo(), issued);
                locDto.setLack(Boolean.TRUE);
                locDtos.add(locDto);
            }
        }
        return R.ok().add(locDtos);
    }
@@ -134,75 +150,75 @@
    @PostMapping("/out/pakout/auth")
    @ManagerAuth(memo = "订单出库")
    public synchronized R pakout(@RequestBody List<LocDto> locDtos) throws InterruptedException {
        StockOutParam param = new StockOutParam();
        ArrayList<StockOutParam.LocDetl> locDetls = new ArrayList<>();
        for (LocDto locDto:locDtos){
            StockOutParam.LocDetl locDetl = new StockOutParam.LocDetl();
            locDetl.setBrand(locDto.getBrand());
            locDetl.setLocNo(locDto.getLocNo());
            locDetl.setAnfme(locDto.getAnfme());
            locDetl.setMatnr(locDto.getMatnr());
            locDetl.setBatch(locDto.getBatch());
            locDetl.setModel(locDto.getModel());
            locDetl.setSpecs(locDto.getSpecs());
            locDetl.setZpallet(locDto.getZpallet());
            param.setOrderNo(locDto.getOrderNo());
            locDetls.add(locDetl);
        }
        param.setLocDetls(locDetls);
        List<StockOutParam> stockOutParams = OutboundAllocationUtil.OutboundClassification(param);
        for (StockOutParam stockOutParam : stockOutParams){
            workService.startupFullTakeStore(stockOutParam, getUserId());
        }
        for (LocDto locDto:locDtos){
            OrderDetl orderDetl = orderDetlService.selectById(locDto.getOrderDetlId());
            orderDetl.setWorkQty(locDto.getAnfme());
            orderDetlService.updateById(orderDetl);
        }
        Order order = orderService.selectByNo(param.getOrderNo());
        order.setSettle(2L);
        orderService.updateById(order);
//        if (Cools.isEmpty(locDtos)) {
//            return R.parse(BaseRes.PARAM);
//        StockOutParam param = new StockOutParam();
//        ArrayList<StockOutParam.LocDetl> locDetls = new ArrayList<>();
//        for (LocDto locDto:locDtos){
//            StockOutParam.LocDetl locDetl = new StockOutParam.LocDetl();
//            locDetl.setBrand(locDto.getBrand());
//            locDetl.setLocNo(locDto.getLocNo());
//            locDetl.setAnfme(locDto.getAnfme());
//            locDetl.setMatnr(locDto.getMatnr());
//            locDetl.setBatch(locDto.getBatch());
//            locDetl.setModel(locDto.getModel());
//            locDetl.setSpecs(locDto.getSpecs());
//            locDetl.setZpallet(locDto.getZpallet());
//
//            param.setOrderNo(locDto.getOrderNo());
//
//            locDetls.add(locDetl);
//        }
//        boolean lack = true;
//        for (LocDto locDto : locDtos) {
//            if (!locDto.isLack()) {
//                lack = false;
//                break;
//            }
//        }
//        if (lack) {
//            return R.error("库存不足");
//        param.setLocDetls(locDetls);
//
//        List<StockOutParam> stockOutParams = OutboundAllocationUtil.OutboundClassification(param);
//        for (StockOutParam stockOutParam : stockOutParams){
//            workService.startupFullTakeStore(stockOutParam, getUserId());
//        }
//
//        Thread.sleep(1000L);
//        for (LocDto locDto:locDtos){
//            OrderDetl orderDetl = orderDetlService.selectById(locDto.getOrderDetlId());
//            orderDetl.setWorkQty(locDto.getAnfme());
//            orderDetlService.updateById(orderDetl);
//        }
//
//        List<TaskDto> taskDtos = new ArrayList<>();
//        // 根据 (库位 & 出库站) 分组; 理想状态:一组为一次出库任务
//        for (LocDto locDto : locDtos) {
//            if (locDto.isLack()) { continue; }
//            TaskDto taskDto = new TaskDto(locDto.getLocNo(), locDto.getStaNo(), locDto);
//            if (TaskDto.has(taskDtos, taskDto)) {
//                TaskDto dto = TaskDto.find(taskDtos, taskDto);
//                assert dto != null;
//                dto.getLocDtos().addAll(taskDto.getLocDtos());
//            } else {
//                taskDtos.add(taskDto);
//            }
//        }
//        // -----------------------------------------------------------------------------------------------
//        for (TaskDto taskDto : taskDtos) {
//            BasDevp staNo = basDevpService.checkSiteStatus(taskDto.getStaNo());
//            workService.stockOut(staNo, taskDto, getUserId());
//        }
//        Order order = orderService.selectByNo(param.getOrderNo());
//        order.setSettle(2L);
//        orderService.updateById(order);
        if (Cools.isEmpty(locDtos)) {
            return R.parse(BaseRes.PARAM);
        }
        boolean lack = true;
        for (LocDto locDto : locDtos) {
            if (!locDto.isLack()) {
                lack = false;
                break;
            }
        }
        if (lack) {
            return R.error("库存不足");
        }
        Thread.sleep(1000L);
        List<TaskDto> taskDtos = new ArrayList<>();
        // 根据 (库位 & 出库站) 分组; 理想状态:一组为一次出库任务
        for (LocDto locDto : locDtos) {
            if (locDto.isLack()) { continue; }
            TaskDto taskDto = new TaskDto(locDto.getLocNo(), locDto.getStaNo(), locDto);
            if (TaskDto.has(taskDtos, taskDto)) {
                TaskDto dto = TaskDto.find(taskDtos, taskDto);
                assert dto != null;
                dto.getLocDtos().addAll(taskDto.getLocDtos());
            } else {
                taskDtos.add(taskDto);
            }
        }
        // -----------------------------------------------------------------------------------------------
        for (TaskDto taskDto : taskDtos) {
            BasDevp staNo = basDevpService.checkSiteStatus(taskDto.getStaNo());
            workService.stockOut(staNo, taskDto, getUserId());
        }
        return R.ok();
    }
src/main/java/com/zy/asrs/entity/WrkMast.java
@@ -378,21 +378,22 @@
    }
    public String getStaNo$(){
        BasDevpService service = SpringUtils.getBean(BasDevpService.class);
        BasDevp basDevp = service.selectById(this.staNo);
        if (!Cools.isEmpty(basDevp)){
            return String.valueOf(basDevp.getDevNo());
        }
        return null;
//        BasDevpService service = SpringUtils.getBean(BasDevpService.class);
//        BasDevp basDevp = service.selectById(this.staNo);
//        if (!Cools.isEmpty(basDevp)){
//            return String.valueOf(basDevp.getDevNo());
//        }
        return String.valueOf(this.staNo);
    }
    public String getSourceStaNo$(){
        BasDevpService service = SpringUtils.getBean(BasDevpService.class);
        BasDevp basDevp = service.selectById(this.sourceStaNo);
        if (!Cools.isEmpty(basDevp)){
            return String.valueOf(basDevp.getDevNo());
        }
        return null;
//        BasDevpService service = SpringUtils.getBean(BasDevpService.class);
//        BasDevp basDevp = service.selectById(this.sourceStaNo);
//        if (!Cools.isEmpty(basDevp)){
//            return String.valueOf(basDevp.getDevNo());
//        }
        return String.valueOf(this.sourceStaNo);
    }
    public String getSourceLocNo$(){
src/main/java/com/zy/asrs/entity/param/CrnExecuteParam.java
New file
@@ -0,0 +1,14 @@
package com.zy.asrs.entity.param;
import lombok.Data;
/**
 * @author pang.jiabao
 * @description
 * @createDate 2024/7/2 18:40
 */
@Data
public class CrnExecuteParam {
    private Integer workNo;
    private Integer staNo;
}
src/main/java/com/zy/asrs/entity/param/GhjtApiParam.java
New file
@@ -0,0 +1,20 @@
package com.zy.asrs.entity.param;
import lombok.Data;
/**
 * @author pang.jiabao
 * @description 冠鸿江铜接口交互统一入参dto
 * @createDate 2024/7/3 9:45
 */
@Data
public class GhjtApiParam {
    private Integer workNo; // 工作号
    private Integer outLocResult; // 出库结果上报 1.完成,其他异常
    private Integer staNo;
    private Integer check; // 复核确认标识,1.确认,其他异常
}
src/main/java/com/zy/asrs/entity/param/GwmsGenerateInventoryDto.java
New file
@@ -0,0 +1,32 @@
package com.zy.asrs.entity.param;
import lombok.Data;
import java.util.List;
@Data
public class GwmsGenerateInventoryDto {
    private String barcode;//    托盘码
    private Integer palletizingNo;// 码垛位编号
    private List<MatList> matList; // 木箱集合
    @Data
    public static class MatList{
        private String boxPos; // 箱子位置
        private String packageGroupNo; // 包装组号
        private List<Rolls> rolls; // 卷集合
    }
    @Data
    public static class Rolls{
        private String rollNo; // 卷号
        private String boxNo; // 箱号
        private String specs; //规格
        private Double length; //长度
        private Integer splices; //接头 个
        private Double netWeight; // 净重
        private Double grossWeight; // 毛重
    }
}
src/main/java/com/zy/asrs/entity/param/ZwmsOutLocWorkDto.java
New file
@@ -0,0 +1,28 @@
package com.zy.asrs.entity.param;
import lombok.Data;
import java.util.List;
/**
 * @author pang.jiabao
 * @description 出库订单
 * @createDate 2024/7/2 19:17
 */
@Data
public class ZwmsOutLocWorkDto {
    private String orderNo; // 订单号
    private String orderType; // 订单类型
    private List<Rolls> matDetails;
    @Data
    public static class Rolls{
        private String rollNo; // 卷号
        private String boxNo; // 箱号
        private String specs; // 规格
    }
}
src/main/java/com/zy/asrs/mapper/LocMastMapper.java
@@ -12,6 +12,15 @@
@Mapper
@Repository
public interface LocMastMapper extends BaseMapper<LocMast> {
    /**
     * 搜索指定区域可用库位
     */
    List<LocMast> selectAreaEmpty(Short locType1);
    /**
     * 根据库位号搜索库位
     */
    LocMast selectByLoc(String locNo);
    LocMast queryFreeLocMast(@Param("row") Integer row, @Param("locType1") Short locType1);
src/main/java/com/zy/asrs/service/LocMastService.java
@@ -7,6 +7,12 @@
import java.util.List;
public interface LocMastService extends IService<LocMast> {
    LocMast selectByLoc(String locNo);
    /**
     * 搜索指定区域可用库位
     */
    List<LocMast> selectAreaEmpty(Short locType1);
    /**
     * 检索可用库位
@@ -28,6 +34,10 @@
    Boolean checkEmptyCount(LocMast locMast);
    /**
     * 查询空库位数量
     */
    Boolean checkEmptyCount(LocMast locMast, int quaOfBlank);
    /**
     * 当前库存明细是否为整托
     */
    Boolean checkWhole(List<LocDetl> locDetls);
src/main/java/com/zy/asrs/service/MobileService.java
@@ -43,4 +43,9 @@
    void stockOut(OrderDetl orderDetl, BasDevp staNo, LocDetl locDetl,
                  Double curOutQty, Integer ioType, Long userId, Date now);
    /**
     * 出库复核确认
     */
    void pakoutFhqr(Integer workNo, Integer check);
}
src/main/java/com/zy/asrs/service/OpenService.java
@@ -1,5 +1,6 @@
package com.zy.asrs.service;
import com.core.common.R;
import com.zy.asrs.entity.param.*;
import com.zy.asrs.entity.result.OpenOrderCompeteResult;
import com.zy.asrs.entity.result.StockVo;
@@ -59,4 +60,29 @@
    void cs2();
    /**
     * GWMS请求ZWMS生成入库任务
     * @return 目标信息
     */
    R gwmsGenerateInventory(GwmsGenerateInventoryDto param);
    /**
     *GWMS到达目标站点请求ZWCS执行入库
     */
    String crnExecute(CrnExecuteParam param);
    /**
     * ZWMS接收MES下发出库任务
     */
    String zwmsOutLocWork(ZwmsOutLocWorkDto param);
    /**
     * 货物到达出库口以后,上报出库结果
     */
    String outLocResultReport(GhjtApiParam param);
    /**
     * 拆盘机出库接口(空托盘出库)
     */
    String emptyOutLoc(GhjtApiParam param);
}
src/main/java/com/zy/asrs/service/impl/LocMastServiceImpl.java
@@ -22,7 +22,14 @@
    public LocMast queryFreeLocMast(Integer row, Short locType1) {
        return this.baseMapper.queryFreeLocMast(row, locType1);
    }
    @Override
    public List<LocMast> selectAreaEmpty(Short locType1) {
        return this.baseMapper.selectAreaEmpty(locType1);
    }
    @Override
    public LocMast selectByLoc(String locNo) {
        return this.baseMapper.selectByLoc(locNo);
    }
    @Override
    public List<String> queryGroupEmptyStock(String sourceLocNo) {
        if (Cools.isEmpty(sourceLocNo)) {
@@ -44,6 +51,14 @@
    }
    @Override
    public Boolean checkEmptyCount(LocMast locMast, int quaOfBlank) {
        if (locMast == null) {
            return false;
        }
        return this.baseMapper.selectEmptyLocCount(locMast.getLocType1(), locMast.getCrnNo()) > quaOfBlank;
    }
    @Override
    public Boolean checkWhole(List<LocDetl> locDetls) {
        return null;
    }
src/main/java/com/zy/asrs/service/impl/MobileServiceImpl.java
@@ -4,29 +4,26 @@
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.core.common.*;
import com.core.common.BaseRes;
import com.core.common.Cools;
import com.core.common.DateUtils;
import com.core.common.SnowflakeIdWorker;
import com.core.exception.CoolException;
import com.zy.asrs.entity.*;
import com.zy.asrs.entity.param.*;
import com.zy.asrs.mapper.ManLocDetlMapper;
import com.zy.asrs.service.*;
import com.zy.asrs.task.core.ReturnT;
import com.zy.asrs.utils.MatUtils;
import com.zy.asrs.utils.PostMesDataUtils;
import com.zy.common.CodeRes;
import com.zy.common.constant.MesConstant;
import com.zy.common.entity.Parameter;
import com.zy.common.model.DetlDto;
import com.zy.common.model.LocTypeDto;
import com.zy.common.model.MesCombParam;
import com.zy.common.model.StartupDto;
import com.zy.common.model.enums.WorkNoType;
import com.zy.common.service.CommonService;
import com.zy.common.utils.HttpHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -1167,6 +1164,27 @@
    @Override
    @Transactional
    public void pakoutFhqr(Integer workNo, Integer check) {
         // 获取工作档
        WrkMast wrkMast = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("wrk_no", workNo));
        if (wrkMast == null) {
            throw new CoolException("工作档不存在:" + workNo);
        }
        if (wrkMast.getWrkSts() != 20) {
            throw new CoolException("工作档当前状态异常:" + workNo + ",状态:" + wrkMast.getWrkSts());
        }
        if (check == 1) {
            // 复核确认,更新状态为15出库完成更新
            wrkMast.setWrkSts(14L);
            wrkMastService.updateById(wrkMast);
        }
    }
    @Override
    @Transactional
    public List<Map<String, Object>> boxTypeComb() {
        EntityWrapper<BasBoxType> wrapper = new EntityWrapper<>();
        List<Map<String, Object>> result = new ArrayList<>();
src/main/java/com/zy/asrs/service/impl/OpenServiceImpl.java
@@ -1,7 +1,7 @@
package com.zy.asrs.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.core.common.Cools;
import com.core.common.DateUtils;
import com.core.common.R;
@@ -13,25 +13,21 @@
import com.zy.asrs.entity.result.StockVo;
import com.zy.asrs.mapper.TagMapper;
import com.zy.asrs.service.*;
import com.zy.asrs.task.core.ReturnT;
import com.zy.asrs.utils.MatUtils;
import com.zy.asrs.utils.PostMesDataUtils;
import com.zy.common.constant.MesConstant;
import com.zy.common.model.DetlDto;
import com.zy.common.model.LocTypeDto;
import com.zy.common.model.StartupDto;
import com.zy.common.model.enums.WorkNoType;
import com.zy.common.service.CommonService;
import com.zy.common.utils.HttpHandler;
import com.zy.common.utils.NodeUtils;
import com.zy.common.web.WcsController;
import com.zy.common.web.param.SearchLocParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.*;
/**
 * Created by vincent on 2022/4/9
@@ -981,6 +977,388 @@
    }
    @Override
    @Transactional
    public R gwmsGenerateInventory(GwmsGenerateInventoryDto param) {
        if (Cools.isEmpty(param)) {
            throw new CoolException("请求参数有误:" + param);
        }
        int zpalletCount = locDetlService.selectCount(new EntityWrapper<LocDetl>().eq("zpallet", param.getBarcode()));
        if (zpalletCount > 0) {
            throw new CoolException("库存托盘码已存在:" + param.getBarcode());
        }
        int barcodeCount = wrkMastService.selectCount(new EntityWrapper<WrkMast>().eq("barcode", param.getBarcode()));
        if (barcodeCount > 0) {
            throw new CoolException("工作档已存在该托盘码:" + param.getBarcode());
        }
        LocTypeDto locTypeDto = new LocTypeDto();
        locTypeDto.setLocType1((short)1);
        // 根据源站点寻找库位
//        StartupDto dto = commonService.getLocNo(1, 1, param.getPalletizingNo(), null,null,null, locTypeDto);
        StartupDto dto = commonService.getLocNo(1, param.getPalletizingNo(), locTypeDto);
        // 返回GWCS目标信息
        pushStaNoToGwcs(param.getPalletizingNo(),dto.getStaNo(),dto.getWorkNo());
        int workNo = dto.getWorkNo();
        Date now = new Date();
        // 生成工作档
        WrkMast wrkMast = new WrkMast();
        wrkMast.setWrkNo(workNo);
        wrkMast.setIoTime(new Date());
        wrkMast.setWrkSts(1L); // 工作状态:设备上走
        wrkMast.setIoType(1); // 入出库状态:1.入库
        wrkMast.setIoPri(13D); // 优先级
        wrkMast.setCrnNo(dto.getCrnNo());
        wrkMast.setSourceStaNo(param.getPalletizingNo());
        wrkMast.setStaNo(dto.getStaNo());
        wrkMast.setLocNo(dto.getLocNo());
        wrkMast.setBarcode(param.getBarcode()); // 托盘码
        wrkMast.setFullPlt("Y"); // 满板:Y
        wrkMast.setPicking("N"); // 拣料
        wrkMast.setExitMk("N"); // 退出
        wrkMast.setEmptyMk("N"); // 空板
        wrkMast.setLinkMis("Y");
        wrkMast.setCtnType(1); // 容器类型
        // 操作人员数据
        wrkMast.setAppeTime(now);
        wrkMast.setModiTime(now);
        boolean res = wrkMastService.insert(wrkMast);
        if (!res) {
            throw new CoolException("保存工作档失败");
        }
        List<GwmsGenerateInventoryDto.MatList> matList = param.getMatList();
        for (GwmsGenerateInventoryDto.MatList obj :matList) {
            WrkDetl wrkDetl = new WrkDetl();
            wrkDetl.setWrkNo(wrkMast.getWrkNo());
            obj.getRolls().forEach(roll -> {
                Mat mat = matService.selectByMatnr(roll.getSpecs());
                if (mat == null) {
                    mat = new Mat();
                    mat.setTagId(6L);
                    mat.setMatnr(roll.getSpecs());
                    mat.setMaktx(roll.getSpecs());
                    mat.setSpecs(roll.getSpecs());
                    mat.setStatus(1);
                    mat.setCreateTime(now);
                    mat.setUpdateTime(now);
                    if (!matService.insert(mat)) {
                        throw new CoolException("物料导入失败!");
                    }
                }
                wrkDetl.setWrkNo(wrkMast.getWrkNo());
                wrkDetl.setMatnr(roll.getSpecs()); // 规格
                wrkDetl.setMaktx(roll.getSpecs()); //规格
                wrkDetl.setBatch(roll.getBoxNo()); // 箱号
                wrkDetl.setModel(roll.getRollNo()); // 卷号
                wrkDetl.setBrand(""); // 木箱类型
                wrkDetl.setZpallet(param.getBarcode()); // 托盘吗
                wrkDetl.setOrigin(obj.getBoxPos()); // 木箱在托盘位置
                wrkDetl.setWeight(roll.getNetWeight()); // 净重
                wrkDetl.setVolume(roll.getGrossWeight()); // 毛重
                wrkDetl.setPrice(roll.getLength());
                wrkDetl.setSpecs(String.valueOf(roll.getSplices()));
                wrkDetl.setAnfme(1.0);
                wrkDetl.setIoTime(now);
                wrkDetl.setAppeTime(now);
                wrkDetl.setModiTime(now);
                if (!wrkDetlService.insert(wrkDetl)) {
                    throw new CoolException("保存工作明细失败");
                }
            });
        }
        // 更新目标库位状态
        LocMast locMast = locMastService.selectById(dto.getLocNo());
        if (locMast.getLocSts().equals("O")){
            locMast.setLocSts("S"); // S.入库预约
            locMast.setModiTime(now);
            if (!locMastService.updateById(locMast)){
                throw new CoolException("改变库位状态失败");
            }
        } else {
            throw new CoolException(dto.getLocNo()+"目标库位已被占用");
        }
        return null;
    }
    @Override
    @Transactional
    public String crnExecute(CrnExecuteParam param) {
        if (Cools.isEmpty(param.getStaNo(),param.getWorkNo())){
            throw new CoolException("参数不能为空:" + param);
        }
        WrkMast wrkMast = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("wrk_no", param.getWorkNo()));
        if (wrkMast == null) {
            throw new CoolException("不存在该工作号:" + param.getWorkNo());
        }
        wrkMast.setWrkSts(2L);
        wrkMastService.updateById(wrkMast);
        return "请求成功";
    }
    @Override
    @Transactional
    public String zwmsOutLocWork(ZwmsOutLocWorkDto param) {
        Order order = orderService.selectByNo(param.getOrderNo());
        if (!Cools.isEmpty(order)) {
            throw new CoolException(param.getOrderNo() + "单据已存在,请勿重复提交");
        }
        DocType docType = docTypeService.selectOrAdd(param.getOrderType(), Boolean.FALSE);
        Date now = new Date();
        // 单据主档
        order = new Order(
                String.valueOf(snowflakeIdWorker.nextId()),    // 编号[非空]
                param.getOrderNo(),    // 订单编号
                DateUtils.convert(now),    // 单据日期
                docType.getDocId(),    // 单据类型
                null,    // 项目编号
                null,    //
                null,    // 调拨项目编号
                null,    // 初始票据号
                null,    // 票据号
                null,    // 客户编号
                null,    // 客户
                null,    // 联系方式
                null,    // 操作人员
                null,    // 合计金额
                null,    // 优惠率
                null,    // 优惠金额
                null,    // 销售或采购费用合计
                null,    // 实付金额
                null,    // 付款类型
                null,    // 业务员
                null,    // 结算天数
                null,    // 邮费支付类型
                null,    // 邮费
                null,    // 付款时间
                null,    // 发货时间
                null,    // 物流名称
                null,    // 物流单号
                1L,    // 订单状态
                1,    // 状态
                9527L,    // 添加人员
                now,    // 添加时间
                9527L,    // 修改人员
                now,    // 修改时间
                null    // 备注
        );
        if (!orderService.insert(order)) {
            throw new CoolException("生成单据主档失败,请联系管理员");
        }
        // 单据明细档
        List<DetlDto> list = new ArrayList<>();
        List<ZwmsOutLocWorkDto.Rolls> orderDetails = param.getMatDetails();
        for (ZwmsOutLocWorkDto.Rolls detail : orderDetails) {
            DetlDto dto = new DetlDto(detail.getRollNo(), detail.getBoxNo(), 1.0);
            dto.setOrderNo(detail.getSpecs());
            if (DetlDto.has(list, dto)) {
                DetlDto detlDto = DetlDto.find(list, dto.getMatnr(), dto.getBatch());
                assert detlDto != null;
                detlDto.setAnfme(detlDto.getAnfme() + 1);
            } else {
                list.add(dto);
            }
        }
        for (DetlDto detlDto : list) {
//            Mat mat = matService.selectByMatnr(detlDto.getMatnr());
            OrderDetl orderDetl = new OrderDetl();
//            if (Cools.isEmpty(mat)) {
//                throw new CoolException(detlDto.getMatnr() + "编号商品检索失败,请先添加商品");
//            } else {
//                orderDetl.sync(mat);
//            }
            orderDetl.setBatch(detlDto.getBatch() == null ? "" : detlDto.getBatch());
            orderDetl.setModel(detlDto.getMatnr());
            orderDetl.setMatnr(detlDto.getOrderNo());
            orderDetl.setMaktx(detlDto.getOrderNo());
            orderDetl.setAnfme(detlDto.getAnfme());
            orderDetl.setOrderId(order.getId());
            orderDetl.setOrderNo(order.getOrderNo());
            orderDetl.setCreateBy(9527L);
            orderDetl.setCreateTime(now);
            orderDetl.setUpdateBy(9527L);
            orderDetl.setUpdateTime(now);
            orderDetl.setStatus(1);
            orderDetl.setQty(0.0D);
            if (!orderDetlService.insert(orderDetl)) {
                throw new CoolException("生成单据明细失败,请联系管理员");
            }
        }
        return null;
    }
    @Override
    @Transactional
    public String outLocResultReport(GhjtApiParam param) {
        if (Cools.isEmpty(param.getOutLocResult(),param.getWorkNo())) {
            throw new CoolException("入参不能为空:" + param);
        }
        WrkMast wrkMast = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("wrk_no", param.getWorkNo()));
        if (wrkMast == null) {
            throw new CoolException("该工作档不存在,任务号:" + param.getWorkNo());
        } else if(wrkMast.getWrkSts() != 2) {
            throw new CoolException("工作档当前状态不符合,任务号:" + param.getWorkNo() + ",工作档状态:" + wrkMast.getWrkSts());
        }
        // 到达出库口确认为1,更新工作档状态为57.出库完成
        if (param.getOutLocResult() == 1) {
            wrkMast.setWrkSts(20L);
            // 空托盘到位直接更新工作档状态为14.已出库未确认,空托无需复核确认
            if (wrkMast.getIoType() == 110) {
                wrkMast.setWrkSts(14L);
            }
            wrkMastService.updateById(wrkMast);
        }
        return "出库结果上报成功";
    }
    @Override
    @Transactional
    public String emptyOutLoc(GhjtApiParam param) {
//        3102/3009/3008/3006/3003/3002→3047/3112
        // 寻找空托盘库位,先找浅库位
        List<LocMast> locMasts;
            locMasts = locMastService.selectList(new EntityWrapper<LocMast>().eq("loc_sts","D")
                    .orderAsc(Arrays.asList("row1","lev1","bay1")).in("row1",3,4,6,7,10,11,14,15,18,19,22,23));
            if (locMasts.isEmpty()) {
                locMasts = locMastService.selectList(new EntityWrapper<LocMast>().eq("loc_sts","D")
                        .orderAsc(Arrays.asList("row1","lev1","bay1")).in("row1",1,4,5,8,9,12,13,16,17,20,21,24));
            }
        if (locMasts.isEmpty()) {
            throw new CoolException("没有找到空托盘,站点:" + param.getStaNo());
        }
        // 取第一个空库位
        LocMast locMast = locMasts.get(0);
        // 获取工作路径
        StaDesc staDesc = staDescService.selectOne(new EntityWrapper<StaDesc>().eq("type_no", 110).eq("stn_no",
                param.getStaNo()).eq("crn_no", locMast.getCrnNo()));
        if (staDesc == null) {
            throw new CoolException("路径不存在");
        }
        //2.生成空托盘出库工作档
        Date now = new Date();
        WrkMast wrkMast = new WrkMast();
        wrkMast.setWrkNo(commonService.getWorkNo(WorkNoType.PAKOUT.type));
        wrkMast.setIoTime(now);
        wrkMast.setWrkSts(11L); // 工作状态:11.生成出库ID
        wrkMast.setIoType(110); // 入出库状态: 110.空板出库
        wrkMast.setIoPri(10D);
        wrkMast.setSourceStaNo(staDesc.getCrnStn()); // 源站
        wrkMast.setStaNo(staDesc.getStnNo()); // 目标站
        wrkMast.setCrnNo(locMast.getCrnNo());
        wrkMast.setSourceLocNo(locMast.getLocNo()); // 源库位
        wrkMast.setFullPlt("N"); // 满板:Y
        wrkMast.setPicking("N"); // 拣料
        wrkMast.setExitMk("N"); // 退出
        wrkMast.setEmptyMk("Y"); // 空板
        wrkMast.setLinkMis("N");
        wrkMast.setAppeUser(9999L);
        wrkMast.setAppeTime(now);
        wrkMast.setModiUser(9999L);
        wrkMast.setModiTime(now);
        if (!wrkMastService.insert(wrkMast)) {
            throw new CoolException("保存工作档失败");
        }
        // 3.更新库位状态 D.空板 -> R.出库预约
        if (locMast.getLocSts().equals("D")) {
            locMast.setLocSts("R");
            locMast.setModiUser(9999L);
            locMast.setModiTime(now);
            if (!locMastService.updateById(locMast)) {
                throw new CoolException("更新库位状态失败");
            }
        }
        return "出库成功";
    }
    @Autowired
    private ApiLogService apiLogService;
    private void pushStaNoToGwcs(Integer palletizingNo, Integer staNo, Integer workNo) {
        boolean success = false;
        // 获取请求头
        Map<String, Object> headers = getHeaders();
        // 构造请求体
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("workNo", workNo);
        jsonObject.put("staNo", staNo);
        jsonObject.put("sourceStaNo", palletizingNo);
        String body = jsonObject.toJSONString();
        String response = "";
        try {
            response = new HttpHandler.Builder()
                    .setUri(MesConstant.URL)
                    .setPath(MesConstant.PAKIN_URL)
                    .setHeaders(headers)
                    .setJson(body)
                    .build()
                    .doPost();
            if (!Cools.isEmpty(response)) {
                success = true;
//                // 修改订单状态 4.完成 ===>> 6.已上报
//                if (!orderService.updateSettle(order.getId(), 6L, null)) {
//                    throw new CoolException("服务器内部错误,请联系管理员");
//                }
            } else {
                log.error("zmws推送入库码头站点接口失败!!!url:{};request:{};response:{}", MesConstant.URL + MesConstant.PAKIN_URL, body, response);
                throw new CoolException("上报mes系统失败");
            }
        } catch (Exception e) {
            log.error("入库请求接口失败:{}", e.getMessage());
//            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//            return FAIL.setMsg(e.getMessage());
        } finally {
            try {
                // 保存接口日志
                apiLogService.save(
                        "入库",
                        MesConstant.URL + MesConstant.PAKIN_URL,
                        null,
                        "127.0.0.1",
                        jsonObject.toJSONString(),
                        response,
                        success
                );
            } catch (Exception e) {
                log.error("", e);
            }
        }
    }
    Map<String, Object> getHeaders(){
        Map<String,Object> headers = new HashMap<>();
        headers.put("digi-type","sync ");
        headers.put("digi-protocol","raw");
        headers.put("digi-datakey"," XCommon.ImportData");
        return headers;
    }
    private void descSta(Integer staNo,Integer crnNo){
//        int[] typeNos =new int[]{1,10,53,101,103,110};
        int[] typeNos =new int[]{10,110};
src/main/java/com/zy/asrs/service/impl/WorkServiceImpl.java
@@ -13,7 +13,6 @@
import com.zy.asrs.entity.param.LocDetlAdjustParam;
import com.zy.asrs.entity.param.StockOutParam;
import com.zy.asrs.service.*;
import com.zy.asrs.utils.OutboundAllocationUtil;
import com.zy.asrs.utils.Utils;
import com.zy.common.model.*;
import com.zy.common.model.enums.IoWorkType;
@@ -28,7 +27,6 @@
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
 * Created by vincent on 2020/6/11
@@ -403,7 +401,48 @@
        LocMast locMast = locMastService.selectById(taskDto.getLocNo());
        // 获取路径
        int ioType = taskDto.isAll() ? 101 : 103;
        StaDesc staDesc = staDescService.queryCrnStnAuto(ioType, locMast.getCrnNo(), staNo.getDevNo());
//        StaDesc staDesc = staDescService.queryCrnStnAuto(ioType, locMast.getCrnNo(), staNo.getDevNo());
        // 根据库位排号+出库站点,获取出库源站点
        int row = Integer.parseInt(locMast.getLocNo().substring(0, 2));
        int souresStaNo = 0;
        if (taskDto.getStaNo() < 3000) { // 二楼
            switch (row) {
                case 1: case 2: case 3:
                case 4: souresStaNo = 2062; break;
                case 5: case 6: case 7:
                case 8: souresStaNo = 2065; break;
                case 9: case 10: case 11:
                case 12: souresStaNo = 2068; break;
                case 13: case 14: case 15:
                case 16: souresStaNo = 2070; break;
                case 17: case 18: case 19:
                case 20: souresStaNo = 2073; break;
                case 21: case 22: case 23:
                case 24: souresStaNo = 2076; break;
                default:
            }
        } else { // 一楼
            switch (row) {
                case 1: case 2: case 3:
                case 4: souresStaNo = 3002; break;
                case 5: case 6: case 7:
                case 8: souresStaNo = 3003; break;
                case 9: case 10: case 11:
                case 12: souresStaNo = 3006; break;
                case 13: case 14: case 15:
                case 16: souresStaNo = 3008; break;
                case 17: case 18: case 19:
                case 20: souresStaNo = 3009; break;
                case 21: case 22: case 23:
                case 24: souresStaNo = 3012; break;
                default:
            }
        }
        if (souresStaNo == 0) {
            throw new CoolException("源站点转换异常:" + row);
        }
        // 生成工作号
        int workNo = commonService.getWorkNo(WorkNoType.getWorkNoType(ioType));
        // 生成工作档
@@ -414,8 +453,8 @@
        wrkMast.setIoType(ioType); // 入出库状态
        wrkMast.setIoPri(13D); // 优先级:13
        wrkMast.setCrnNo(locMast.getCrnNo());
        wrkMast.setSourceStaNo(staDesc.getCrnStn()); // 源站
        wrkMast.setStaNo(staDesc.getStnNo()); // 目标站
        wrkMast.setSourceStaNo(souresStaNo); // 源站
        wrkMast.setStaNo(taskDto.getStaNo()); // 目标站
        wrkMast.setSourceLocNo(taskDto.getLocNo()); // 源库位
        wrkMast.setFullPlt("Y"); // 满板:Y
        wrkMast.setPicking("N"); // 拣料
@@ -438,9 +477,17 @@
                orderDetl = orderDetlService.selectItem(locDto.getOrderNo(), locDto.getMatnr(), null);
            }
            WrkDetl wrkDetl = new WrkDetl();
            wrkDetl.sync(orderDetl);
//            wrkDetl.sync(orderDetl);
            wrkDetl.setZpallet(wrkMast.getBarcode());
            wrkDetl.setIoTime(now);
            wrkDetl.setMatnr(locDto.getMatnr());
            wrkDetl.setMaktx(locDto.getMaktx());
            wrkDetl.setWeight(locDto.getWeight()); // 净重
            wrkDetl.setVolume(locDto.getVolume()); // 毛重
            wrkDetl.setOrigin(locDto.getOrigin()); // 木箱在托盘位置
            wrkDetl.setPrice(locDto.getPrice());
            wrkDetl.setSpecs(locDto.getSpecs());
            wrkDetl.setModel(locDto.getModel());
            wrkDetl.setWrkNo(workNo);
            wrkDetl.setBatch(locDto.getBatch());
            wrkDetl.setOrderNo(locDto.getOrderNo());
src/main/java/com/zy/asrs/task/GhjtScheduler.java
New file
@@ -0,0 +1,60 @@
package com.zy.asrs.task;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.zy.asrs.entity.Order;
import com.zy.asrs.entity.WrkMast;
import com.zy.asrs.mapper.OrderMapper;
import com.zy.asrs.mapper.WrkMastMapper;
import com.zy.asrs.task.handler.GhjtHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
/**
 * @author pang.jiabao
 * @description 冠鸿江铜相关定时任务
 * @createDate 2024/7/3 9:07
 */
@Slf4j
@Component
public class GhjtScheduler {
    @Resource
    private GhjtHandler ghjtHandler;
    @Resource
    private WrkMastMapper wrkMastMapper;
    @Resource
    private OrderMapper orderMapper;
    // 下发出库任务给GWCS(从出库码头到出库口)
//    @Scheduled(cron = "0/2 * * * * ? ")
    public void ckrwPushGwcs() {
        // 查询状态为13的工作档
        List<WrkMast> wrkMasts = wrkMastMapper.selectList(new EntityWrapper<WrkMast>().eq("io_type", 101).eq("wrk_sts", 13));
        for (WrkMast wrkMast : wrkMasts) {
            try {
                ghjtHandler.startCkrwPushGwcs(wrkMast);
            } catch (Exception e) {
                log.error("下发出库任务给GWCS(从出库码头到出库口)失败,异常信息:" + e);
            }
        }
    }
    // 出库订单完成则上报MES
//    @Scheduled(cron = "0/4 * * * * ? ")
    public void OutBoundCompleteReport() {
        // 查询订单状态为4.已完成
        List<Order> orders = orderMapper.selectComplete();
        for (Order order : orders) {
            try {
                ghjtHandler.OutBoundCompleteReport(order);
            } catch (Exception e) {
                log.error("出库订单完成则上报MES失败,异常信息:" + e);
            }
        }
    }
}
src/main/java/com/zy/asrs/task/WorkMastScheduler.java
@@ -40,11 +40,11 @@
        }
        for (WrkMast wrkMast : wrkMasts) {
            try{
                if (wrkMast.getIoType().equals(101)){
                    if (Cools.isEmpty(wrkMast.getSheetNo()) || !wrkMast.getSheetNo().equals("3")){
                        continue;
                    }
                }
//                if (wrkMast.getIoType().equals(101)){
//                    if (Cools.isEmpty(wrkMast.getSheetNo()) || !wrkMast.getSheetNo().equals("3")){
//                        continue;
//                    }
//                }
                ReturnT<String> returnT = workMastHandler.start(wrkMast);
                if (!returnT.isSuccess()) {
                    wrkMast.setUpdMk("X");
src/main/java/com/zy/asrs/task/handler/GhjtHandler.java
New file
@@ -0,0 +1,139 @@
package com.zy.asrs.task.handler;
import com.alibaba.fastjson.JSONObject;
import com.core.common.Cools;
import com.core.exception.CoolException;
import com.zy.asrs.entity.Order;
import com.zy.asrs.entity.WrkMast;
import com.zy.asrs.mapper.WrkMastMapper;
import com.zy.asrs.service.ApiLogService;
import com.zy.common.constant.MesConstant;
import com.zy.common.utils.HttpHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
/**
 * @author pang.jiabao
 * @description 冠鸿江铜定时任务实现
 * @createDate 2024/7/3 9:09
 */
@Slf4j
@Service
public class GhjtHandler {
    @Autowired
    private ApiLogService apiLogService;
    @Resource
    private WrkMastMapper wrkMastMapper;
    @Transactional
    public void startCkrwPushGwcs(WrkMast wrkMast) {
        // 获取请求头
        Map<String, Object> headers = new HashMap<>();
        headers.put("digi-type", "sync ");
        headers.put("digi-protocol", "raw");
        headers.put("digi-datakey", " XCommon.ImportData");
        // 构造请求体
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("workNo", wrkMast.getWrkNo());
        jsonObject.put("staNo", wrkMast.getStaNo());
        jsonObject.put("sourceStaNo", wrkMast.getSourceStaNo());
        String body = jsonObject.toJSONString();
        boolean success = false;
        String response = "";
        try {
            response = new HttpHandler.Builder()
                    .setUri(MesConstant.URL)
                    .setPath(MesConstant.PAKIN_URL)
                    .setHeaders(headers)
                    .setJson(body)
                    .build()
                    .doPost();
            if (!Cools.isEmpty(response)) {
                wrkMast.setWrkSts(2L); // 更新为设备上走
                wrkMastMapper.updateById(wrkMast);
                success = true;
            } else {
                log.error("请求接口失败!!!url:{};request:{};response:{}", MesConstant.URL + MesConstant.PAKIN_URL, body, response);
                throw new CoolException("下发出库任务给GWCS(从出库码头到出库口)失败");
            }
        } catch (Exception e) {
            log.error("下发出库任务给GWCS(从出库码头到出库口)异常,工作号:{},{}", wrkMast.getWrkNo(), e.getMessage());
        } finally {
            try {
                // 保存接口日志
                apiLogService.save(
                        "从出库码头到出库口",
                        MesConstant.URL + MesConstant.PAKIN_URL,
                        null,
                        "127.0.0.1",
                        jsonObject.toJSONString(),
                        response,
                        success
                );
            } catch (Exception e) {
                log.error("接口日志保存异常", e);
            }
        }
    }
    @Transactional
    public void OutBoundCompleteReport(Order order) {
        // 获取请求头
        Map<String, Object> headers = new HashMap<>();
        headers.put("digi-type", "sync ");
        headers.put("digi-protocol", "raw");
        // 构造请求体
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("orderNo", order.getOrderNo());
        jsonObject.put("complete", 1); // 订单完成为1,其他...
        String body = jsonObject.toJSONString();
        boolean success = false;
        String response = "";
        try {
            response = new HttpHandler.Builder()
                    .setUri(MesConstant.URL)
                    .setPath(MesConstant.PAKIN_URL)
                    .setHeaders(headers)
                    .setJson(body)
                    .build()
                    .doPost();
            if (!Cools.isEmpty(response)) {
                success = true;
            } else {
                log.error("请求接口失败!!!url:{};request:{};response:{}", MesConstant.URL + MesConstant.PAKIN_URL, body, response);
                throw new CoolException("下发出库任务给GWCS(从出库码头到出库口)失败");
            }
        } catch (Exception e) {
            log.error("出库订单完成上报MES异常,工作号:{},{}", order.getOrderNo(), e.getMessage());
        } finally {
            try {
                // 保存接口日志
                apiLogService.save(
                        "出库订单完成上报MES",
                        MesConstant.URL + MesConstant.PAKIN_URL,
                        null,
                        "127.0.0.1",
                        jsonObject.toJSONString(),
                        response,
                        success
                );
            } catch (Exception e) {
                log.error("接口日志保存异常", e);
            }
        }
    }
}
src/main/java/com/zy/asrs/task/handler/WorkLogHandler.java
@@ -62,18 +62,18 @@
                // 全板入库
                if (wrkMast.getIoType() == 1) {
                    // 入库通知单
                    if (!Cools.isEmpty(wrkMast.getBarcode())) {
                        // 保存入库通知档历史档
                        if (!waitPakinLogService.save(wrkMast.getBarcode())) {
//                            exceptionHandle("保存入库通知档历史档[workNo={0}]失败", wrkMast.getWrkNo());
                            log.error("保存入库通知档历史档[workNo={"+wrkMast.getWrkNo()+"}]失败");
                        }
                        // 删除入库通知档
                        if (!waitPakinService.delete(new EntityWrapper<WaitPakin>().eq("zpallet", wrkMast.getBarcode()))) {
//                            exceptionHandle("删除入库通知档[workNo={0}]失败", wrkMast.getWrkNo());
                            log.error("删除入库通知档[workNo={"+wrkMast.getWrkNo()+"}]失败");
                        }
                    }
//                    if (!Cools.isEmpty(wrkMast.getBarcode())) {
//                        // 保存入库通知档历史档
//                        if (!waitPakinLogService.save(wrkMast.getBarcode())) {
////                            exceptionHandle("保存入库通知档历史档[workNo={0}]失败", wrkMast.getWrkNo());
//                            log.error("保存入库通知档历史档[workNo={"+wrkMast.getWrkNo()+"}]失败");
//                        }
//                        // 删除入库通知档
//                        if (!waitPakinService.delete(new EntityWrapper<WaitPakin>().eq("zpallet", wrkMast.getBarcode()))) {
////                            exceptionHandle("删除入库通知档[workNo={0}]失败", wrkMast.getWrkNo());
//                            log.error("删除入库通知档[workNo={"+wrkMast.getWrkNo()+"}]失败");
//                        }
//                    }
//                    // 手动入库生成单据 【 上报三方平台 】
//                    if (!Cools.isEmpty(wrkDetls)) {
//                        if (!orderService.saveHandlerOrder(Boolean.TRUE, wrkMast, wrkDetls)) {
src/main/java/com/zy/asrs/task/handler/WorkMastHandler.java
@@ -355,13 +355,20 @@
                    }
                    for (WrkDetl wrkDetl : wrkDetls101) {
                        // 更新订单完成数量
                        OrderDetl orderDetl = orderDetlService.selectItem(wrkDetl.getOrderNo(), wrkDetl.getMatnr(), wrkDetl.getBatch());
                        if (orderDetl==null){
                            orderDetl = orderDetlService.selectItem(wrkDetl.getOrderNo(), wrkDetl.getMatnr(), null);
                        }
//                        OrderDetl orderDetl = orderDetlService.selectItem(wrkDetl.getOrderNo(), wrkDetl.getMatnr(), wrkDetl.getBatch());
//                        if (orderDetl==null){
//                            orderDetl = orderDetlService.selectItem(wrkDetl.getOrderNo(), wrkDetl.getMatnr(), null);
//                        }
                        // 箱号+卷号
                        OrderDetl orderDetl = orderDetlService.selectOne(new EntityWrapper<OrderDetl>().eq("batch",wrkDetl.getBatch())
                                .eq("model",wrkDetl.getModel()));
                        try {
                            if(!Cools.isEmpty(orderDetl)){
                                if(!orderDetlService.increaseQtyByOrderNo(wrkDetl.getOrderNo(), wrkDetl.getMatnr(),
                                // 更新订单完成数量
//                                orderDetlService.update(null,new EntityWrapper<OrderDetl>().eq("order_no",orderDetl.getOrderNo())
//                                        .eq("batch",orderDetl.getBatch()).eq("model", orderDetl.getModel()));
                                if(!orderDetlService.increaseQtyByOrderNo(wrkDetl.getOrderNo(), orderDetl.getModel(),
                                        orderDetl.getBatch(),wrkDetl.getAnfme())){
//                                    exceptionHandle("全板出库 ===>> 更新订单完成数量失败;[workNo={0}],[locNo={1}]",
//                                            wrkMast.getWrkNo(), wrkMast.getLocNo());
src/main/java/com/zy/asrs/utils/Utils.java
@@ -4,11 +4,12 @@
import com.core.common.Cools;
import com.core.exception.CoolException;
import com.zy.asrs.entity.LocMast;
import com.zy.common.model.LocDetlDto;
import com.zy.common.properties.SlaveProperties;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
@@ -38,6 +39,34 @@
            return msgBuilder.toString();
        }
    }
    public static final List<Integer> FIRST_GROUP_ROW_LIST = new ArrayList<Integer>() {{
        add(1);add(2);
    }};
    public static final List<Integer> SECOND_GROUP_ROW_LIST = new ArrayList<Integer>() {{
        add(3);add(4);
    }};
    public static List<String> getGroupLocNo(String locNo, Boolean pakIn) {
        int row = getRow(locNo);
        List<String> result = new ArrayList<>();
        if (FIRST_GROUP_ROW_LIST.contains(row)) {
            for (Integer groupRow : FIRST_GROUP_ROW_LIST) {
                result.add(zerofill(String.valueOf(groupRow), 2) + locNo.substring(2));
            }
        } else if (SECOND_GROUP_ROW_LIST.contains(row)) {
            List<Integer> clone = Arrays.asList(new Integer[SECOND_GROUP_ROW_LIST.size()]);
            Collections.copy(clone, SECOND_GROUP_ROW_LIST);
            Collections.reverse(clone);
            for (Integer integer : clone) {
                result.add(zerofill(String.valueOf(integer), 2) + locNo.substring(2));
            }
        }
        if (!pakIn) {
            //出库,反转数据
            Collections.reverse(result);
        }
        return result;
    }
    /**
     * 判断是否为深库位
src/main/java/com/zy/common/service/CommonService.java
@@ -3,16 +3,13 @@
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.core.common.Arith;
import com.core.common.Cools;
import com.core.exception.CoolException;
import com.zy.asrs.entity.*;
import com.zy.asrs.entity.result.KeyValueVo;
import com.zy.asrs.service.*;
import com.zy.asrs.utils.Utils;
import com.zy.asrs.utils.VersionUtils;
import com.zy.common.model.LocTypeDto;
import com.zy.common.model.Shelves;
import com.zy.common.model.StartupDto;
import com.zy.common.properties.SlaveProperties;
import lombok.extern.slf4j.Slf4j;
@@ -20,10 +17,6 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
/**
@@ -123,10 +116,103 @@
    }
    /**
     * 双深找库位
     */
    @Transactional
    public StartupDto getLocNo(Integer staDescId, Integer sourceStaNo,LocTypeDto locTypeDto) {
        // 目标库位
        LocMast locMast;
//        // 搜索空托
//        locMast = getLocNoStep4(staDescId, sourceStaNo);
//        if (locMast != null) {
//            //找到库位,返回dto
//            return getLocNoStep6(staDescId, sourceStaNo, locMast);//返回dto
//        }
        //搜索整个空库位组
        locMast = getLocNoStepSingle(locTypeDto);
        if (locMast != null) {
            //找到库位,返回dto
            return getLocNoStep6(staDescId, sourceStaNo, locMast);//返回dto
        }
       //找不到库位,抛出异常
        throw new CoolException("没有空库位");
    }
    // 搜索单品(整个库位组)
    private LocMast getLocNoStepSingle(LocTypeDto locTypeDto) {
        LocMast locMast = null;
        //单品
        List<LocMast> locMasts = locMastService.selectAreaEmpty(locTypeDto.getLocType1());//搜索货物
        for (LocMast mast : locMasts) {
            List<String> groupLoc = Utils.getGroupLocNo(mast.getLocNo(), true);
//            if (!locMastService.checkAllLocEmpty(groupLoc)) {
//                continue;
//            }
            LocMast tmp = null;
            for (String loc : groupLoc) {
                LocMast locMast1 = locMastService.selectByLoc(loc);
                if (locMast1 == null) {
                    continue;
                }
                if (!locMast1.getLocSts().equals("O")) {
                    continue;
                }
                tmp = locMast1;
                break;
            }
            //预留空库位
            if (tmp != null && locMastService.checkEmptyCount(mast, 10)) {
                locMast = tmp;
                break;
            }
        }
        return locMast;
    }
    //返回dto
    private StartupDto getLocNoStep6(Integer staDescId, Integer sourceStaNo, LocMast locMast) {
        StartupDto startupDto = new StartupDto();
        // 获取目标站
        Wrapper<StaDesc> wrapper = new EntityWrapper<StaDesc>()
                .eq("type_no", staDescId)
                .eq("stn_no", sourceStaNo)
                .eq("crn_no",locMast.getCrnNo());
        StaDesc staDesc = staDescService.selectOne(wrapper);
        if (Cools.isEmpty(staDesc)) {
            log.error("入库路径不存在, staDescId={}, sourceStaNo={}", staDescId, sourceStaNo);
            throw new CoolException("入库路径不存在");
        }
        // 检测目标站
        BasDevp staNo = basDevpService.selectById(staDesc.getCrnStn());
        if (!staNo.getAutoing().equals("Y")) {
            throw new CoolException("目标站" + staDesc.getCrnStn() + "不可用");
        }
        // 生成工作号
        int workNo = getWorkNo(0);
        // 返回dto
        startupDto.setWorkNo(workNo);
        startupDto.setSourceStaNo(sourceStaNo);
        startupDto.setStaNo(staNo.getDevNo());
        startupDto.setLocNo(locMast.getLocNo());
        startupDto.setCrnNo(locMast.getCrnNo());
        return startupDto;
    }
    /**
     * 检索库位号
     *
     * @param whsType     类型 1:双深式货架
     * @param staDescId   路径ID
     * @param staDescId   入库类型
     * @param sourceStaNo 源站
     * @param matnr       物料号集合
     * @return locNo 检索到的库位号
src/main/resources/mapper/LocMastMapper.xml
@@ -36,7 +36,12 @@
        <result column="ctn_no" property="ctnNo" />
    </resultMap>
    <select id="selectAreaEmpty" resultMap="BaseResultMap">
        select * from asr_loc_mast
        where loc_sts in ('O')
          and loc_type1 = #{locType1}
        ORDER BY lev1,bay1,row1
    </select>
    <select id="queryFreeLocMast" resultMap="BaseResultMap">
        select top 1 *
        from asr_loc_mast
@@ -47,7 +52,10 @@
        </if>
        order by loc_sts desc ,lev1 asc,bay1 asc
    </select>
    <select id="selectByLoc" resultMap="BaseResultMap">
        select * from asr_loc_mast
        where loc_no = #{locNo}
    </select>
    <select id="queryShallowLocFMast" resultMap="BaseResultMap">
        select * from asr_loc_mast
        where 1=1
src/main/resources/mapper/OrderDetlMapper.xml
@@ -175,7 +175,7 @@
        set qty = qty + #{qty}
        where 1=1
        and order_no = #{orderNo}
        and matnr = #{matnr}
        and model = #{matnr}
        <choose>
            <when test="batch != null and batch != ''">
                and batch = #{batch}
src/main/webapp/static/js/order/out.js
@@ -168,7 +168,7 @@
                                    {field: 'anfme', title: '数量', align: 'center', width: 90, style: 'font-weight: bold'},
                                    {field: 'count', title: '数量', align: 'center', width: 90, style: 'font-weight: bold'},
                                    {field: 'locNo', title: '货位', align: 'center', width: 100, templet: '#locNoTpl'},
                                    // {field: 'staNos', align: 'center', title: '出库站', merge: ['locNo'], templet: '#tbBasicTbStaNos'},
                                    {field: 'staNos', align: 'center', title: '出库站', merge: ['locNo'], templet: '#tbBasicTbStaNos'},
                                    // {type: 'checkbox', merge: ['locNo']},
                                ]],
                                done: function (res) {