自动化立体仓库 - WMS系统
src/main/java/com/zy/asrs/controller/OpenController.java
@@ -25,6 +25,7 @@
import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
 * Created by vincent on 2022/4/8
@@ -49,6 +50,8 @@
    private WaitPakinService waitPakinService;
    @Autowired
    private WrkDetlService wrkDetlService;
    @Autowired
    private WrkDetlLogService wrkDetlLogService;
    @Autowired
    private WrkMastService wrkMastService;
    @Autowired
@@ -123,6 +126,23 @@
                                             HttpServletRequest request) {
        auth(appkey, param, request);
        return R.ok().add(openService.pakinOrderComplete(param));
    }
    /**
     * 托盘入库历史记录重报ERP
     */
    @PostMapping("/order/pakin/erp/report/v1")
//    @AppAuth(memo = "入库历史重报ERP")
    public synchronized R reportPakinHistoryToErp(@RequestBody(required = false) List<String> barcodes) {
//        auth(appkey, barcodes, request);
        if (Cools.isEmpty(barcodes)) {
            return R.parse(BaseRes.PARAM);
        }
        try {
            return openService.reportPakinHistoryToErp(barcodes);
        } catch (Exception e) {
            return R.error(e.getMessage());
        }
    }
@@ -439,8 +459,7 @@
    }
    /**
     * 组托信息下发
     * return
     * 7.3 组托信息下发
     */
    @PostMapping("/comb/auth")
    public synchronized R comb(@RequestBody ArrayList<MesToCombParam> param, HttpServletRequest request) {
@@ -487,9 +506,8 @@
    }
    /**
     * 出库通知单
     * 7.11 出库通知单(传递有序无序规则)
     */
    @PostMapping("/outOrder")
    public synchronized R outOrder(@RequestBody ArrayList<OutTaskParam> params, HttpServletRequest request) {
        if (Cools.isEmpty(params)) {
@@ -497,32 +515,51 @@
        }
        log.info("[outOrder] cache: {}", JSON.toJSONString(params));
        request.setAttribute("cache", params);
        Set<String> orderIds = new LinkedHashSet<>();
        Map<String, List<OutTaskParam>> linesByBatch = new LinkedHashMap<>();
        for (OutTaskParam outTaskParam : params) {
            if (Cools.isEmpty(outTaskParam) || Cools.isEmpty(outTaskParam.getOrderId())) {
                return R.error("出库单号不能为空");
            }
            orderIds.add(outTaskParam.getOrderId());
            if (Cools.isEmpty(outTaskParam.getBatchSeq())) {
                outTaskParam.setBatchSeq(outTaskParam.getOrderId());
            }
            if (Cools.isEmpty(outTaskParam.getStationId())) {
                return R.error("托盘「" + outTaskParam.getPalletId() + "」出库口编码不能为空");
            }
            linesByBatch.computeIfAbsent(outTaskParam.getBatchSeq(), k -> new ArrayList<>()).add(outTaskParam);
        }
        Map<String, List<OutTaskParam>> linesByOrder = new LinkedHashMap<>();
        for (OutTaskParam outTaskParam : params) {
            linesByOrder.computeIfAbsent(outTaskParam.getOrderId(), k -> new ArrayList<>()).add(outTaskParam);
        }
        for (Map.Entry<String, List<OutTaskParam>> entry : linesByOrder.entrySet()) {
            String oid = entry.getKey();
        for (Map.Entry<String, List<OutTaskParam>> entry : linesByBatch.entrySet()) {
            List<OutTaskParam> lines = entry.getValue();
            List<Integer> seqs = new ArrayList<>(lines.size());
            OutTaskParam head = lines.get(0);
            String oid = head.getOrderId();
            String batchSeq = head.getBatchSeq();
            boolean hasZero = false;
            boolean hasPositive = false;
            List<Integer> orderedSeqs = new ArrayList<>(lines.size());
            for (OutTaskParam line : lines) {
                if (line.getSeq() == null) {
                    return R.error("出库单「" + oid + "」序号不能为空");
                    return R.error("出库单「" + oid + "」批次「" + batchSeq + "」序号不能为空");
                }
                seqs.add(line.getSeq());
                if (line.getSeq() < 0) {
                    return R.error("出库单「" + oid + "」批次「" + batchSeq + "」序号不能小于0");
                }
                if (line.getSeq() == 0) {
                    hasZero = true;
                } else {
                    hasPositive = true;
                    orderedSeqs.add(line.getSeq());
                }
            }
            Collections.sort(seqs);
            for (int i = 0; i < seqs.size(); i++) {
                if (!String.valueOf(seqs.get(i)).equals(String.valueOf(i + 1))) {
                    return R.error("出库单「" + oid + "」序号不连贯");
            if (hasZero && hasPositive) {
                return R.error("出库单「" + oid + "」批次「" + batchSeq + "」序号不能混用无序和有序");
            }
            if (!hasZero) {
                Collections.sort(orderedSeqs);
                for (int i = 0; i < orderedSeqs.size(); i++) {
                    if (!Objects.equals(orderedSeqs.get(i), i + 1)) {
                        return R.error("出库单「" + oid + "」批次「" + batchSeq + "」序号不连贯");
                    }
                }
            }
        }
@@ -589,6 +626,36 @@
    }
    /**
     * 7.9 出库异常变动上报
     */
    @PostMapping("/order/pakout/abnormal/report/v1")
    public synchronized R outOrderAbnormalReport(@RequestBody OutOrderAbnormalReportParam param, HttpServletRequest request) {
        if (request != null) {
            log.info("[outOrderAbnormalReport] cache: {}", param == null ? "null" : JSON.toJSONString(param));
            request.setAttribute("cache", param);
        }
        if (Cools.isEmpty(param) || Cools.isEmpty(param.getPalletId())) {
            return R.error("palletId不能为空");
        }
        return openService.outOrderAbnormalReport(param);
    }
    /**
     * 7.10 出库异常变动处理
     */
    @PostMapping("/order/pakout/abnormal/handle/v1")
    public synchronized R outOrderAbnormalHandle(@RequestBody OutOrderAbnormalHandleParam param, HttpServletRequest request) {
        if (request != null) {
            log.info("[outOrderAbnormalHandle] cache: {}", param == null ? "null" : JSON.toJSONString(param));
            request.setAttribute("cache", param);
        }
        if (Cools.isEmpty(param) || Cools.isEmpty(param.getPalletId())) {
            return R.error("palletId不能为空");
        }
        return openService.outOrderAbnormalHandle(param);
    }
    /**
     * pause out order
     */
    @PostMapping("/order/pakout/pause/default/v1")
@@ -601,6 +668,10 @@
            return R.error("orderNo is empty");
        }
        return openService.pakoutOrderPause(param);
    }
    private String buildOutOrderBatchKey(OutTaskParam param) {
        return param.getOrderId() + "#" + param.getBatchSeq();
    }
@@ -651,12 +722,12 @@
                }
            }
            AxisBean inqty = new AxisBean();
            inqty.setName("入库数量");
            inqty.setName("入库托盘数");
            Integer[] array1 = new Integer[data1.size()];
            inqty.setData(data1.toArray(array1));
            list.add(inqty);
            AxisBean outqty = new AxisBean();
            outqty.setName("出库数量");
            outqty.setName("出库TU");
            Integer[] array2 = new Integer[data2.size()];
            outqty.setData(data2.toArray(array2));
            list.add(outqty);
@@ -666,7 +737,7 @@
    }
    /**
     * 近24小时入出库折线(横轴小时),与按日 {@link #locIoLineCharts()} 数据口径不同,供电视机「作业效率」使用
     * 入出库按小时折线:横轴为「当前整点起向前共 12 小时」滚动窗口,与库表 ymd(yyyy-MM-dd HH)对齐
     */
    @GetMapping("/line/charts/hourly")
    public R locIoLineChartsHourly() {
@@ -682,17 +753,17 @@
        ArrayList<Integer> data2 = new ArrayList<>();
        List<String> categories = new ArrayList<>();
        final int n = 12;
        SimpleDateFormat sfKey = new SimpleDateFormat("yyyy-MM-dd HH");
        SimpleDateFormat sfLabel = new SimpleDateFormat("HH:00");
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        calendar.add(Calendar.HOUR_OF_DAY, -23);
        calendar.add(Calendar.HOUR_OF_DAY, -(n - 1));
        for (int i = 0; i < 24; i++) {
        for (int i = 0; i < n; i++) {
            String key = sfKey.format(calendar.getTime());
            categories.add(sfLabel.format(calendar.getTime()));
            categories.add(String.valueOf(calendar.get(Calendar.HOUR_OF_DAY)));
            int inV = 0;
            int outV = 0;
@@ -709,13 +780,13 @@
        }
        AxisBean inqty = new AxisBean();
        inqty.setName("入库数量");
        inqty.setName("入库托盘数");
        Integer[] array1 = new Integer[data1.size()];
        inqty.setData(data1.toArray(array1));
        list.add(inqty);
        AxisBean outqty = new AxisBean();
        outqty.setName("出库数量");
        outqty.setName("出库TU");
        Integer[] array2 = new Integer[data2.size()];
        outqty.setData(data2.toArray(array2));
        list.add(outqty);
@@ -795,12 +866,130 @@
        }
        List<WrkDetl> wrkDetls = wrkDetlService.selectByWrkNo(Integer.valueOf(param.getTaskNo()));
        String costTime = resolveCostTime(wrkMast, wrkDetls);
        HashMap<String, Object> map = new HashMap<>();
        map.put("taskNo", param.getTaskNo());
        map.put("ioType", wrkMast.getIoType());
        map.put("costTime", costTime);
        map.put("wrkDetls", wrkDetls);
        return R.ok().add(map);
    }
    private String resolveCostTime(WrkMast wrkMast, List<WrkDetl> wrkDetls) {
        Date createTime = resolveOrderCreateTime(resolveOrderNo(wrkMast, wrkDetls));
        if (createTime == null) {
            createTime = resolveTaskCreateTime(wrkMast);
        }
        if (createTime == null) {
            return "0";
        }
        long minutes = TimeUnit.MILLISECONDS.toMinutes(System.currentTimeMillis() - createTime.getTime());
        if (minutes < 0L) {
            minutes = 0L;
        }
        return String.valueOf(minutes);
    }
    private String resolveOrderNo(WrkMast wrkMast, List<WrkDetl> wrkDetls) {
        if (wrkMast != null && !Cools.isEmpty(wrkMast.getUserNo())) {
            return wrkMast.getUserNo();
        }
        if (Cools.isEmpty(wrkDetls)) {
            return null;
        }
        for (WrkDetl wrkDetl : wrkDetls) {
            if (wrkDetl != null && !Cools.isEmpty(wrkDetl.getOrderNo())) {
                return wrkDetl.getOrderNo();
            }
        }
        return null;
    }
    private Date resolveOrderCreateTime(String orderNo) {
        if (Cools.isEmpty(orderNo)) {
            return null;
        }
        Date historyCreateTime = minDate(
                minCreateTime(wrkMastLogService.selectList(new EntityWrapper<WrkMastLog>().eq("user_no", orderNo))),
                minCreateTime(wrkDetlLogService.selectList(new EntityWrapper<WrkDetlLog>().eq("order_no", orderNo)))
        );
        if (historyCreateTime != null) {
            return historyCreateTime;
        }
        return minDate(
                minCreateTime(wrkMastService.selectList(new EntityWrapper<WrkMast>().eq("user_no", orderNo))),
                minCreateTime(wrkDetlService.selectList(new EntityWrapper<WrkDetl>().eq("order_no", orderNo)))
        );
    }
    private Date minDate(Date first, Date second) {
        if (first == null) {
            return second;
        }
        if (second == null) {
            return first;
        }
        return first.before(second) ? first : second;
    }
    private Date resolveTaskCreateTime(WrkMast wrkMast) {
        if (wrkMast == null) {
            return null;
        }
        return firstDate(wrkMast.getAppeTime(), wrkMast.getIoTime(), wrkMast.getModiTime());
    }
    private Date firstDate(Date... dates) {
        if (dates == null || dates.length == 0) {
            return null;
        }
        for (Date date : dates) {
            if (date != null) {
                return date;
            }
        }
        return null;
    }
    private Date minCreateTime(List<?> list) {
        if (Cools.isEmpty(list)) {
            return null;
        }
        Date min = null;
        for (Object item : list) {
            Date createTime = resolveCreateTime(item);
            if (createTime == null) {
                continue;
            }
            if (min == null || createTime.before(min)) {
                min = createTime;
            }
        }
        return min;
    }
    private Date resolveCreateTime(Object item) {
        if (item instanceof WrkMast) {
            WrkMast wrkMast = (WrkMast) item;
            return firstDate(wrkMast.getAppeTime(), wrkMast.getIoTime(), wrkMast.getModiTime());
        }
        if (item instanceof WrkMastLog) {
            WrkMastLog wrkMastLog = (WrkMastLog) item;
            return firstDate(wrkMastLog.getAppeTime(), wrkMastLog.getIoTime(), wrkMastLog.getModiTime());
        }
        if (item instanceof WrkDetl) {
            WrkDetl wrkDetl = (WrkDetl) item;
            return firstDate(wrkDetl.getAppeTime(), wrkDetl.getIoTime(), wrkDetl.getModiTime());
        }
        if (item instanceof WrkDetlLog) {
            WrkDetlLog wrkDetlLog = (WrkDetlLog) item;
            return firstDate(wrkDetlLog.getAppeTime(), wrkDetlLog.getIoTime(), wrkDetlLog.getModiTime());
        }
        return null;
    }
}