| src/main/java/com/zy/asrs/controller/OpenController.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/zy/asrs/entity/param/QueryTaskParam.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/zy/asrs/utils/Utils.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/main/java/com/zy/common/service/CommonService.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/main/java/com/zy/asrs/controller/OpenController.java
@@ -4,18 +4,15 @@ import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.baomidou.mybatisplus.plugins.Page; import com.core.annotations.AppAuth; import com.core.common.*; import com.core.exception.CoolException; import com.google.common.collect.Lists; import com.zy.asrs.entity.*; import com.zy.asrs.entity.param.*; import com.zy.asrs.service.LocDetlService; import com.zy.asrs.service.OpenService; import com.zy.asrs.service.WaitPakinService; import com.zy.asrs.service.WrkDetlService; import com.zy.asrs.service.WrkMastLogService; import com.zy.asrs.service.WrkMastService; import com.zy.asrs.mapper.ReportQueryMapper; import com.zy.asrs.service.*; import com.zy.common.model.DetlDto; import com.zy.common.model.LocDetlDto; import com.zy.common.model.enums.WorkNoType; @@ -26,6 +23,7 @@ import javax.naming.ldap.HasControls; import javax.servlet.http.HttpServletRequest; import java.text.SimpleDateFormat; import java.util.*; /** @@ -55,7 +53,11 @@ private WrkMastService wrkMastService; @Autowired private WrkMastLogService wrkMastLogService; @Autowired private MatService matService; @Autowired private ReportQueryMapper reportQueryMapper; // @PostMapping("/order/matSync/default/v1") //// @AppAuth(memo = "商品信息同步接口") // public synchronized R syncMatInfo(@RequestHeader(required = false) String appkey, @@ -538,5 +540,141 @@ } return openService.pakoutOrderPause(param); } /*************************************电视机程序***********************************************/ @GetMapping("/locDetl/statistics") public R locDetlStatistics(){ HashMap<String, Object> param = new HashMap<>(); Page<LocDetl> stockStatis = locDetlService.getStockStatis(toPage(1, 100, param, LocDetl.class)); for (LocDetl locDetl : stockStatis.getRecords()) { Mat mat = matService.selectByMatnr(locDetl.getMatnr()); if (mat != null) { locDetl.sync(mat); } } return R.ok(stockStatis); } @GetMapping("/line/charts") public R locIoLineCharts(){ Map<String,Object> map=new HashMap<String, Object>(); List<AxisBean> list = new ArrayList<AxisBean>(); List<WorkChartAxis> listChart = reportQueryMapper.getChartAxis(); if(listChart!=null) { ArrayList<Integer> data1 = new ArrayList<Integer>(); ArrayList<Integer> data2 = new ArrayList<Integer>(); SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd"); Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.DATE, -12); for(int i=0;i<12;i++) { boolean flag = true; calendar.add(Calendar.DATE, 1); String str = sf.format(calendar.getTime()); for(WorkChartAxis workChart : listChart) { if(str.equals(workChart.getYmd())) { data1.add(workChart.getInqty()); data2.add(workChart.getOutqty()); flag = false; break; } } if(flag) { data1.add(0); data2.add(0); } } AxisBean inqty = new AxisBean(); inqty.setName("入库数量"); Integer[] array1 = new Integer[data1.size()]; inqty.setData(data1.toArray(array1)); list.add(inqty); AxisBean outqty = new AxisBean(); outqty.setName("出库数量"); Integer[] array2 = new Integer[data2.size()]; outqty.setData(data2.toArray(array2)); list.add(outqty); } map.put("rows",list); return R.ok(map); } /** * 库存信息查询接口 */ @GetMapping("/queryLoc") public synchronized R queryLoc() { List<Map<String, Object>> pie = new ArrayList<>(); LocChartPie locUseRate = reportQueryMapper.getLocUseRate(); if (locUseRate != null) { Map<String, Object> map = new HashMap<>(); map.put("name", "在库"); map.put("value", locUseRate.getFqty()); pie.add(map); Map<String, Object> map1 = new HashMap<>(); map1.put("name", "空"); map1.put("value", locUseRate.getOqty()); pie.add(map1); Map<String, Object> map2 = new HashMap<>(); map2.put("name", "使用"); map2.put("value", locUseRate.getUqty()); pie.add(map2); Map<String, Object> map3 = new HashMap<>(); map3.put("name", "禁用"); map3.put("value", locUseRate.getXqty()); pie.add(map3); } // 总库位数 Integer total = (int) Arith.add(0, locUseRate.getFqty(), locUseRate.getOqty(), locUseRate.getUqty(), locUseRate.getXqty()); // 使用中 Integer used = locUseRate.getFqty() + locUseRate.getUqty(); // 库位使用率 double usedDivides = Arith.divides(3, used, total); double usedPr = Arith.multiplys(1, usedDivides, 100); return R.ok( Cools.add("pie", pie) .add("stockCount", locUseRate.getFqty()) .add("emptyCount", locUseRate.getOqty()) .add("disableCount", locUseRate.getXqty()) .add("total", total) .add("used", used) .add("usedPr", usedPr) ); } /** * 任务查询接口 */ @PostMapping("/queryTask") public synchronized R queryTask(@RequestBody QueryTaskParam param) { if (Cools.isEmpty(param)) { return R.parse(BaseRes.PARAM); } if (Cools.isEmpty(param.getTaskNo())) { return R.error("任务号[taskNo]不能为空"); } WrkMast wrkMast = wrkMastService.selectOne(new EntityWrapper<WrkMast>().eq("wrk_no", param.getTaskNo())); if (wrkMast == null) { return R.error("任务不存在"); } List<WrkDetl> wrkDetls = wrkDetlService.selectByWrkNo(Integer.valueOf(param.getTaskNo())); HashMap<String, Object> map = new HashMap<>(); map.put("taskNo", param.getTaskNo()); map.put("ioType", wrkMast.getIoType()); map.put("wrkDetls", wrkDetls); return R.ok().add(map); } } src/main/java/com/zy/asrs/entity/param/QueryTaskParam.java
New file @@ -0,0 +1,10 @@ package com.zy.asrs.entity.param; import lombok.Data; @Data public class QueryTaskParam { private String taskNo; } src/main/java/com/zy/asrs/utils/Utils.java
@@ -152,7 +152,9 @@ * 3. 若当前库区没有满足条件的空库位,再补充其他库区的堆垛机。 * 4. 当 {@code locType1 = 1} 时,先返回低库位堆垛机,再把同批堆垛机的高库位追加到后面。 * 5. 对不存在、故障、不可入以及无空库位的堆垛机直接剔除。 * 6. 当物料为 {@code emptyPallet} 时,按空板入库优先规则重新排序。 * * <p>这里是只读排序工具,不再写回 {@code asr_row_lastno.crn_qty}。 * {@code crn_qty} 在主数据里表示“堆垛机数量”,不能再被拿来当轮询游标,否则会把整仓配置写坏。 * * <p>返回结果中的每一项格式为: * {@code {crnNo: 堆垛机号, locType1: 库位高低类型}} @@ -321,21 +323,10 @@ if (areaRowLastno == null) { return new ArrayList<>(crnNos); } Integer startCrnNo = resolveAreaStartCrnNo(areaRowLastno, rowLastno); Integer endCrnNo = resolveAreaEndCrnNo(areaRowLastno, rowLastno); if (startCrnNo != null && endCrnNo != null && startCrnNo <= endCrnNo) { for (int crnNo = startCrnNo; crnNo <= endCrnNo; crnNo++) { addAreaCrnNo(crnNos, crnNo, 1, endCrnNo); } for (int crnNo = areaRowLastno.getsCrnNo(); crnNo <= startCrnNo; crnNo++) { addAreaCrnNo(crnNos, crnNo, 1, endCrnNo); } Integer nextCrnQty = startCrnNo + 1; if (areaRowLastno.geteCrnNo() != null && nextCrnQty > areaRowLastno.geteCrnNo()) { nextCrnQty = areaRowLastno.getsCrnNo() == null ? 1 : areaRowLastno.getsCrnNo(); } areaRowLastno.setCrnQty(nextCrnQty); SpringUtils.getBean(RowLastnoService.class).updateById(areaRowLastno); Integer startCrnNo = resolveAreaStartCrnNo(areaRowLastno); List<Integer> orderedCrnNos = getOrderedCrnNos(areaRowLastno, startCrnNo); if (!orderedCrnNos.isEmpty()) { crnNos.addAll(orderedCrnNos); } if (crnNos.isEmpty()) { @@ -362,34 +353,47 @@ return defaultRowLastno; } private static Integer resolveAreaStartCrnNo(RowLastno areaRowLastno, RowLastno defaultRowLastno) { if (areaRowLastno != null && areaRowLastno.getCrnQty() != null && areaRowLastno.getCrnQty() > 0) { return areaRowLastno.getCrnQty(); private static Integer resolveAreaStartCrnNo(RowLastno areaRowLastno) { if (areaRowLastno == null) { return null; } if (areaRowLastno != null && areaRowLastno.getsCrnNo() != null && areaRowLastno.getsCrnNo() > 0) { return areaRowLastno.getsCrnNo(); Integer startCrnNo = areaRowLastno.getsCrnNo(); Integer endCrnNo = areaRowLastno.geteCrnNo(); Integer currentRow = areaRowLastno.getCurrentRow(); Integer rowSpan = getCrnRowSpan(areaRowLastno.getTypeId()); if (startCrnNo == null || startCrnNo <= 0) { return 1; } if (defaultRowLastno != null && defaultRowLastno.getsCrnNo() != null && defaultRowLastno.getsCrnNo() > 0) { return defaultRowLastno.getsCrnNo(); if (endCrnNo == null || endCrnNo < startCrnNo || currentRow == null || rowSpan == null || rowSpan <= 0) { return startCrnNo; } return 1; int startRow = areaRowLastno.getsRow() == null ? 1 : areaRowLastno.getsRow(); int offset = Math.max(currentRow - startRow, 0) / rowSpan; int resolvedCrnNo = startCrnNo + offset; if (resolvedCrnNo < startCrnNo || resolvedCrnNo > endCrnNo) { return startCrnNo; } return resolvedCrnNo; } private static Integer resolveAreaEndCrnNo(RowLastno areaRowLastno, RowLastno defaultRowLastno) { if (areaRowLastno != null && areaRowLastno.geteCrnNo() != null && areaRowLastno.geteCrnNo() > 0) { return areaRowLastno.geteCrnNo(); private static List<Integer> getOrderedCrnNos(RowLastno rowLastno, Integer startCrnNo) { List<Integer> orderedCrnNos = new ArrayList<>(); if (rowLastno == null) { return orderedCrnNos; } return null; } private static void addAreaCrnNo(LinkedHashSet<Integer> crnNos, Integer crnNo, Integer startCrnNo, Integer endCrnNo) { if (crnNos == null || crnNo == null || startCrnNo == null || endCrnNo == null) { return; int start = rowLastno.getsCrnNo() == null ? 1 : rowLastno.getsCrnNo(); int end = rowLastno.geteCrnNo() == null ? start + ((rowLastno.getCrnQty() == null ? 1 : rowLastno.getCrnQty()) - 1) : rowLastno.geteCrnNo(); int first = startCrnNo == null ? start : startCrnNo; if (first < start || first > end) { first = start; } if (crnNo < startCrnNo || crnNo > endCrnNo) { return; for (int crnNo = first; crnNo <= end; crnNo++) { orderedCrnNos.add(crnNo); } crnNos.add(crnNo); for (int crnNo = start; crnNo < first; crnNo++) { orderedCrnNos.add(crnNo); } return orderedCrnNos; } private static List<Integer> getAllCrnNos(RowLastno rowLastno) { src/main/java/com/zy/common/service/CommonService.java
@@ -538,6 +538,30 @@ return orderedCrnNos; } /** * 优先按 s_crn_no/e_crn_no 反推真实堆垛机数量。 * * 之前有逻辑错误把 asr_row_lastno.crn_qty 当成轮询游标写回, * 导致“堆垛机数量”字段被污染。后续找位不能再直接信任 crn_qty, * 否则会少扫堆垛机,表现出来就是任务长期偏向某几台堆垛机。 */ private int resolveCrnCount(RowLastno rowLastno) { if (rowLastno == null) { return 0; } if (rowLastno.getsCrnNo() != null && rowLastno.geteCrnNo() != null && rowLastno.geteCrnNo() >= rowLastno.getsCrnNo()) { return rowLastno.geteCrnNo() - rowLastno.getsCrnNo() + 1; } if (rowLastno.getCrnQty() != null && rowLastno.getCrnQty() > 0) { return rowLastno.getCrnQty(); } Integer rowSpan = getCrnRowSpan(rowLastno.getTypeId()); if (rowSpan != null && rowSpan > 0 && rowLastno.getsRow() != null && rowLastno.geteRow() != null && rowLastno.geteRow() >= rowLastno.getsRow()) { return (rowLastno.geteRow() - rowLastno.getsRow() + 1 + rowSpan - 1) / rowSpan; } return 0; } private Integer getCrnStartRow(RowLastno rowLastno, Integer crnNo) { if (rowLastno == null || crnNo == null) { return null; @@ -729,6 +753,11 @@ * * 推荐排只对普通物料生效,空托盘已经切换成“按库区轮询堆垛机”的规则, * 因此这里会直接跳过空托盘请求,避免 row 参数把空托盘重新带回旧逻辑。 * * 另外,单排推荐不再作为“强绑定单台堆垛机”处理。 * 现场上游经常只传一个推荐排,例如 row=[1],如果这里直接短路命中, * 满板任务就会长期压在同一台堆垛机上。现在只有当推荐排能覆盖多台堆垛机时, * 才把它当作真正的优先候选集合。 */ private LocMast findRun2RecommendLoc(RowLastno rowLastno, RowLastnoType rowLastnoType, boolean emptyPalletRequest, List<Integer> recommendRows, LocTypeDto locTypeDto, Integer staDescId, @@ -738,7 +767,7 @@ return null; } List<Integer> recommendCrnNos = mapRowsToCrnNos(rowLastno, recommendRows); if (Cools.isEmpty(recommendCrnNos)) { if (Cools.isEmpty(recommendCrnNos) || recommendCrnNos.size() <= 1) { return null; } LocMast locMast = findRun2EmptyLocByCrnNos(rowLastno, rowLastnoType, recommendCrnNos, locTypeDto, @@ -791,11 +820,25 @@ * 普通物料命中库位后,沿用 run2 原有的全仓轮询游标推进方式。 */ private void advanceNormalRun2Cursor(RowLastno rowLastno, int curRow) { advanceNormalRun2Cursor(rowLastno, curRow, null, null); } /** * 普通物料游标优先按“本次真正可用的堆垛机集合”推进。 * * 这样即使库区定义里存在不存在的堆垛机,或者路径主数据只覆盖部分堆垛机, * 满板任务也会在真实可作业的堆垛机之间轮询,不会因为理论堆垛机号的空洞而长期回落到同一台。 */ private void advanceNormalRun2Cursor(RowLastno rowLastno, int curRow, List<Integer> runnableCrnNos, Integer selectedCrnNo) { if (rowLastno == null) { return; } int updateCurRow = curRow == 0 ? (rowLastno.getsRow() == null ? 1 : rowLastno.getsRow()) : curRow; updateCurRow = getNextRun2CurrentRow(rowLastno, updateCurRow); if (!Cools.isEmpty(runnableCrnNos) && selectedCrnNo != null) { updateCurRow = getNextRun2CurrentRow(rowLastno, runnableCrnNos, selectedCrnNo, updateCurRow); } else { updateCurRow = getNextRun2CurrentRow(rowLastno, updateCurRow); } rowLastno.setCurrentRow(updateCurRow); rowLastnoService.updateById(rowLastno); } @@ -1471,7 +1514,7 @@ } int sRow = rowLastno.getsRow(); int eRow = rowLastno.geteRow(); int crnNumber = rowLastno.getCrnQty(); int crnNumber = resolveCrnCount(rowLastno); // ===============>>>> 开始执行 @@ -1691,7 +1734,7 @@ if (Cools.isEmpty(rowLastnoType)) { throw new CoolException("数据异常,请联系管理员===》库位规则类型未知"); } int crnNumber = rowLastno.getCrnQty(); int crnNumber = resolveCrnCount(rowLastno); rowCount = crnNumber; curRow = rowLastno.getCurrentRow(); @@ -1701,6 +1744,7 @@ Run2AreaSearchResult emptyPalletAreaSearchResult = null; List<Integer> orderedCrnNos = getOrderedCrnNos(rowLastno, crnNo); List<Integer> orderedRunnableCrnNos = getOrderedRunnableRun2CrnNos(rowLastno, staDescId, sourceStaNo, orderedCrnNos); List<Integer> triedCrnNos = new ArrayList<>(); locMast = findRun2RecommendLoc(rowLastno, rowLastnoType, emptyPalletRequest, recommendRows, locTypeDto, staDescId, sourceStaNo, startupDto, preferredArea, triedCrnNos); @@ -1727,7 +1771,7 @@ if (emptyPalletRequest) { advanceEmptyPalletRun2Cursor(emptyPalletAreaSearchResult, locMast); } else { advanceNormalRun2Cursor(rowLastno, curRow); advanceNormalRun2Cursor(rowLastno, curRow, orderedRunnableCrnNos, locMast == null ? null : locMast.getCrnNo()); } if (Cools.isEmpty(locMast) || !locMast.getLocSts().equals("O")) { @@ -1789,7 +1833,7 @@ } int sRow = rowLastno.getsRow(); int eRow = rowLastno.geteRow(); int crnNumber = rowLastno.getCrnQty(); int crnNumber = resolveCrnCount(rowLastno); // ===============>>>> 开始执行 curRow = rowLastno.getCurrentRow();