| | |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.*; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | /** |
| | | * Created by vincent on 2022/4/8 |
| | |
| | | private static final boolean auth = true; |
| | | private static final String sign_arm_order = "|s|LABEL_"; |
| | | private static final String sign_arm_sku = "|sku|LABEL_"; |
| | | private static final long MILLIS_PER_MINUTE = 60L * 1000L; |
| | | public static final ArrayList<String> APP_KEY_LIST = new ArrayList<String>() {{ |
| | | add("ea1f0459efc02a79f046f982767939ae"); |
| | | }}; |
| | |
| | | private WaitPakinService waitPakinService; |
| | | @Autowired |
| | | private WrkDetlService wrkDetlService; |
| | | @Autowired |
| | | private WrkDetlLogService wrkDetlLogService; |
| | | @Autowired |
| | | private WrkMastService wrkMastService; |
| | | @Autowired |
| | |
| | | @PostMapping("/arm/task/v1") |
| | | @AppAuth(memo = "分拣线上报接收") |
| | | public synchronized R TaskArmReport(@RequestHeader(required = false) String appkey, |
| | | @RequestBody TaskArmReportParam param, |
| | | HttpServletRequest request) { |
| | | @RequestBody TaskArmReportParam param, |
| | | HttpServletRequest request) { |
| | | auth(appkey, param, request); |
| | | if (Cools.isEmpty(param)) { |
| | | return R.parse(BaseRes.PARAM); |
| | |
| | | @PostMapping("/arm/task/cycle_result") |
| | | @AppAuth(memo = "单码完成") |
| | | public synchronized R TaskArmCycleResult(@RequestHeader(required = false) String appkey, |
| | | @RequestBody TaskArmCycleResultParam param, |
| | | HttpServletRequest request) { |
| | | @RequestBody TaskArmCycleResultParam param, |
| | | HttpServletRequest request) { |
| | | auth(appkey, param, request); |
| | | if (Cools.isEmpty(param)) { |
| | | return R.parse(BaseRes.PARAM); |
| | |
| | | @PostMapping("/arm/task/workspace_status") |
| | | @AppAuth(memo = "托盘完成") |
| | | public synchronized R TaskArmWorkspaceStatus(@RequestHeader(required = false) String appkey, |
| | | @RequestBody TaskArmWorkspaceStatusParam param, |
| | | HttpServletRequest request) { |
| | | @RequestBody TaskArmWorkspaceStatusParam param, |
| | | HttpServletRequest request) { |
| | | auth(appkey, param, request); |
| | | if (Cools.isEmpty(param)) { |
| | | return R.parse(BaseRes.PARAM); |
| | |
| | | @PostMapping("/arm/task/loc_status") |
| | | // @AppAuth(memo = "托盘就绪状态查询") |
| | | public synchronized R TaskArmLocStatus(@RequestHeader(required = false) String appkey, |
| | | @RequestBody ArmOKParam param, |
| | | HttpServletRequest request) { |
| | | @RequestBody ArmOKParam param, |
| | | HttpServletRequest request) { |
| | | auth(appkey, param, request); |
| | | if (Cools.isEmpty(param)) { |
| | | return R.parse(BaseRes.PARAM); |
| | |
| | | @PostMapping("/armAbnormalOperation") |
| | | // @AppAuth(memo = "异常上报") |
| | | public synchronized R ArmAbnormalOperation(@RequestHeader(required = false) String appkey, |
| | | @RequestBody TaskArmErrorParam param, |
| | | HttpServletRequest request) { |
| | | @RequestBody TaskArmErrorParam param, |
| | | HttpServletRequest request) { |
| | | auth(appkey, param, request); |
| | | if (Cools.isEmpty(param.getArm_no())) { |
| | | return R.error("机械臂编号[Arm_no]不能为空"); |
| | |
| | | int countWrk = wrkDetlService.selectCount(new EntityWrapper<WrkDetl>().eq("zpallet", mesToCombParam.getPalletId())); |
| | | int countwait = waitPakinService.selectCount(new EntityWrapper<WaitPakin>().eq("zpallet",mesToCombParam.getPalletId()).eq("io_status", "Y")); |
| | | if (countLoc > 0 || countWrk > 0 || countwait > 0) { |
| | | return R.error(mesToCombParam.getPalletId()+"-工作档/库存条码数据已存在,无法删除"); |
| | | return R.error(mesToCombParam.getPalletId()+"-工作档/库存条码数据已存在,无法删除"); |
| | | } |
| | | waitPakinService.delete(new EntityWrapper<WaitPakin>().eq("zpallet",mesToCombParam.getPalletId())); |
| | | boo = true; |
| | |
| | | } |
| | | |
| | | /** |
| | | * 7.11 出库通知单(传递有序无序规则) |
| | | * 7.11 出库通知单(传递有序无序规则)。 |
| | | * |
| | | * ERP 出库通知统一先落出库订单,不再由接口线程直接创建 WrkMast/WrkDetl。 |
| | | * |
| | | * 关键规则: |
| | | * 1. orderId 作为出库订单号落到 man_order_pakout.order_no。 |
| | | * 2. stationId > 600 时必须传 entryWmsCode,后续按 entryWmsCode 作为进仓编号分批生成任务。 |
| | | * 3. stationId <= 600 时允许 entryWmsCode 为空,后续生成任务时使用 orderId 作为批次键。 |
| | | * 4. 建单阶段只校验库存和满库位,不锁库位、不改 loc_sts,真正占库仍由定时生成任务时处理。 |
| | | * |
| | | * 为什么这里不再直接调用 outOrderBatch: |
| | | * - 直接建 WrkMast 会马上把库位从 F 改为 R,ERP 重发、人工中止、WCS 取消后的补偿都很难统一。 |
| | | * - 先落订单明细后,未生成任务的明细可以删除重下发;已生成任务的明细由取消逻辑回滚 work_qty。 |
| | | * - 低站点和高站点走同一条订单链路后,pakoutOrderPause/execute 才能同时控制“未生成”和“已生成”的任务。 |
| | | */ |
| | | @PostMapping("/outOrder") |
| | | public synchronized R outOrder(@RequestBody ArrayList<OutTaskParam> params, HttpServletRequest request) { |
| | |
| | | } |
| | | log.info("[outOrder] cache: {}", JSON.toJSONString(params)); |
| | | request.setAttribute("cache", params); |
| | | Map<String, List<OutTaskParam>> linesByBatch = new LinkedHashMap<>(); |
| | | |
| | | // 统一做有序/无序校验的分组。 |
| | | // |
| | | // 注意:这里的分组 key 不是 ERP 原始 batchSeq,而是“未来生成 WrkMast.batchSeq 的值”。 |
| | | // 这样可以在接口入口就校验最终任务批次里的 seq 是否连续,避免订单已经落库后定时器才失败。 |
| | | // |
| | | // 批次键规则: |
| | | // - 高站点按 orderId + entryWmsCode; |
| | | // - 低站点按 orderId + orderId。 |
| | | Map<String, List<OutTaskParam>> linesByValidateKey = new LinkedHashMap<>(); |
| | | for (OutTaskParam outTaskParam : params) { |
| | | if (Cools.isEmpty(outTaskParam) || Cools.isEmpty(outTaskParam.getOrderId())) { |
| | | return R.error("出库单号不能为空"); |
| | | } |
| | | if (Cools.isEmpty(outTaskParam.getBatchSeq())) { |
| | | // batchSeq 仍保存 ERP 字段;未传时用 orderId 补齐,便于明细追溯。 |
| | | // 低站点真正生成任务时不使用该字段作为批次键,而是固定使用 orderId。 |
| | | outTaskParam.setBatchSeq(outTaskParam.getOrderId()); |
| | | } |
| | | if (Cools.isEmpty(outTaskParam.getStationId())) { |
| | | return R.error("托盘「" + outTaskParam.getPalletId() + "」出库口编码不能为空"); |
| | | } |
| | | linesByBatch.computeIfAbsent(outTaskParam.getBatchSeq(), k -> new ArrayList<>()).add(outTaskParam); |
| | | Integer stationId; |
| | | try { |
| | | stationId = Integer.valueOf(outTaskParam.getStationId()); |
| | | } catch (NumberFormatException ex) { |
| | | return R.error("托盘「" + outTaskParam.getPalletId() + "」出库口编码格式错误:" + outTaskParam.getStationId()); |
| | | } |
| | | if (stationId > 600) { |
| | | // 高站点任务必须带进仓编号;这是定时生成任务时的批次边界, |
| | | // 也是 OutboundBatchSeqReleaseGuard 判断能否放行下一进仓编号的依据。 |
| | | // 低站点不做该限制,低站点没有进仓编号时会统一使用 orderId 作为批次键。 |
| | | if (Cools.isEmpty(outTaskParam.getEntryWmsCode())) { |
| | | return R.error("托盘「" + outTaskParam.getPalletId() + "」进仓编号不能为空"); |
| | | } |
| | | } |
| | | linesByValidateKey.computeIfAbsent(buildOutOrderValidateKey(outTaskParam), k -> new ArrayList<>()).add(outTaskParam); |
| | | } |
| | | |
| | | for (Map.Entry<String, List<OutTaskParam>> entry : linesByBatch.entrySet()) { |
| | | // 仍保留原接口的有序/无序规则: |
| | | // - seq=0 表示无序,同批次所有明细都必须为 0; |
| | | // - seq>0 表示有序,同批次必须从 1 开始连续; |
| | | // - seq=0 和 seq>0 不能混用。 |
| | | // |
| | | // 所有明细虽然暂不生成任务,也要在建单前保证同一任务批次内的明细顺序合法, |
| | | // 否则后续定时生成任务时才失败会更难追溯到 ERP 原始请求。 |
| | | for (Map.Entry<String, List<OutTaskParam>> entry : linesByValidateKey.entrySet()) { |
| | | List<OutTaskParam> lines = entry.getValue(); |
| | | OutTaskParam head = lines.get(0); |
| | | String oid = head.getOrderId(); |
| | | String batchSeq = head.getBatchSeq(); |
| | | String batchSeq = resolveOutOrderTaskBatchKey(head); |
| | | boolean hasZero = false; |
| | | boolean hasPositive = false; |
| | | List<Integer> orderedSeqs = new ArrayList<>(lines.size()); |
| | |
| | | } |
| | | } |
| | | |
| | | // 重新按校验分组顺序展开,保证重复托盘、库存、库位校验与上面的批次校验看到同一批数据。 |
| | | List<OutTaskParam> groupedParams = new ArrayList<>(params.size()); |
| | | for (List<OutTaskParam> lines : linesByValidateKey.values()) { |
| | | groupedParams.addAll(lines); |
| | | } |
| | | |
| | | Set<String> seenPallet = new LinkedHashSet<>(); |
| | | for (OutTaskParam outTaskParam : params) { |
| | | for (OutTaskParam outTaskParam : groupedParams) { |
| | | String pid = outTaskParam.getPalletId(); |
| | | String palletKey = pid == null ? "" : pid; |
| | | if (!seenPallet.add(palletKey)) { |
| | |
| | | // } |
| | | // } |
| | | |
| | | // 订单化后仍必须确认托盘有库存且当前库位为满库位。 |
| | | // |
| | | // 这里只做准入校验,不在 controller 层提前锁库位: |
| | | // - 如果这里提前改 loc_sts,会造成“订单未执行但库存已被占用”; |
| | | // - 真正锁库位必须和 WrkMast/WrkDetl 创建在同一个事务里完成,所以仍由 outOrderBatch 处理。 |
| | | List<OutTaskParam> missingStock = Lists.newArrayList(); |
| | | List<OutTaskParam> missingLoc = Lists.newArrayList(); |
| | | for (OutTaskParam outTaskParam : params) { |
| | | for (OutTaskParam outTaskParam : groupedParams) { |
| | | int countLoc = locDetlService.selectCount(new EntityWrapper<LocDetl>().eq("zpallet", outTaskParam.getPalletId())); |
| | | if (countLoc == 0) { |
| | | missingStock.add(outTaskParam); |
| | |
| | | } |
| | | return R.error("没有找到托盘码对应库位:" + String.join(",", badPalletIds)).add(missingLoc); |
| | | } |
| | | |
| | | return openService.outOrderBatch(params); |
| | | // ERP /outOrder 默认创建可执行订单: |
| | | // - status=1:定时器允许扫描并生成任务; |
| | | // - 生成任务后服务层会立即把 wrk_sts=11 的任务置为 pdcType=Y; |
| | | // - 因此 ERP 侧仍保持“通知后自动出库”的体验,只是任务生成从接口线程转移到了订单调度链路。 |
| | | return openService.outOrderCreatePakoutOrder(groupedParams, true); |
| | | } |
| | | |
| | | /** |
| | |
| | | return openService.pakoutOrderPause(param); |
| | | } |
| | | |
| | | private String buildOutOrderBatchKey(OutTaskParam param) { |
| | | return param.getOrderId() + "#" + param.getBatchSeq(); |
| | | /** |
| | | * 公开执行接口。 |
| | | * |
| | | * IoT/MQTT 等非 ERP 入口会先创建 status=0 的出库订单,只有调用该接口后才允许生成任务和下发。 |
| | | * 该接口只支持 execute=1;中止仍走 /order/pakout/pause/default/v1 的 execute=2。 |
| | | */ |
| | | @PostMapping("/order/pakout/execute/default/v1") |
| | | public synchronized R pakoutOrderExecute(@RequestBody OpenOrderPakoutExecuteParam param, HttpServletRequest request) { |
| | | if (request != null) { |
| | | log.info("[pakoutOrderExecute] cache: {}", param == null ? "null" : JSON.toJSONString(param)); |
| | | request.setAttribute("cache", param); |
| | | } |
| | | if (Cools.isEmpty(param) || Cools.isEmpty(param.getOrderId())) { |
| | | return R.error("orderNo is empty"); |
| | | } |
| | | return openService.pakoutOrderExecute(param); |
| | | } |
| | | |
| | | private String buildOutOrderValidateKey(OutTaskParam param) { |
| | | return param.getOrderId() + "#" + resolveOutOrderTaskBatchKey(param); |
| | | } |
| | | |
| | | /** |
| | | * 计算 /outOrder 入口的最终任务批次键。 |
| | | * |
| | | * 这个值必须和 OpenServiceImpl.resolvePakoutTaskBatchSeq 保持一致: |
| | | * - 高站点:entryWmsCode; |
| | | * - 低站点:orderId。 |
| | | * |
| | | * 入口校验和后续生成任务使用同一口径,才能保证 seq 校验、批次守卫和 WCS 下发批次一致。 |
| | | */ |
| | | private String resolveOutOrderTaskBatchKey(OutTaskParam param) { |
| | | if (param != null && isPendingOutOrderStation(param.getStationId()) && !Cools.isEmpty(param.getEntryWmsCode())) { |
| | | return param.getEntryWmsCode(); |
| | | } |
| | | return param == null ? null : param.getOrderId(); |
| | | } |
| | | |
| | | private boolean isPendingOutOrderStation(String stationId) { |
| | | try { |
| | | return Integer.valueOf(stationId) > 600; |
| | | } catch (Exception ignored) { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 推荐出库站点 |
| | | */ |
| | | @PostMapping("/pakoutStaNo") |
| | | public synchronized R pakoutStaNo(@RequestBody List<String> barcodes) { |
| | | String StaNo = "1,2,3,4,5"; |
| | | return R.ok().add(StaNo); |
| | | } |
| | | |
| | | |
| | | /*************************************电视机程序***********************************************/ |
| | | |
| | | @GetMapping("/locDetl/statistics") |
| | | public R locDetlStatistics(){ |
| | | public synchronized R locDetlStatistics(){ |
| | | HashMap<String, Object> param = new HashMap<>(); |
| | | Page<LocDetl> stockStatis = locDetlService.getStockStatis(toPage(1, 100, param, LocDetl.class)); |
| | | for (LocDetl locDetl : stockStatis.getRecords()) { |
| | |
| | | } |
| | | |
| | | @GetMapping("/line/charts") |
| | | public R locIoLineCharts(){ |
| | | public synchronized R locIoLineCharts(){ |
| | | Map<String,Object> map=new HashMap<String, Object>(); |
| | | List<AxisBean> list = new ArrayList<AxisBean>(); |
| | | |
| | |
| | | |
| | | SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd"); |
| | | Calendar calendar = Calendar.getInstance(); |
| | | calendar.add(Calendar.DATE, -12); |
| | | for(int i=0;i<12;i++) { |
| | | calendar.add(Calendar.DATE, -7); |
| | | for(int i=0;i<7;i++) { |
| | | boolean flag = true; |
| | | calendar.add(Calendar.DATE, 1); |
| | | String str = sf.format(calendar.getTime()); |
| | |
| | | |
| | | AxisBean cube5 = new AxisBean(); |
| | | cube5.setName("入库体积"); |
| | | AxisBean cube15 = new AxisBean(); |
| | | cube15.setName("出库体积"); |
| | | List<WorkCubeTotalAxis> workCubeTotalAxes = reportQueryMapper.getCubeTotal(); |
| | | List<WorkCubeTotalAxis> workCubeTotalAxes = reportQueryMapper.getInboundCubeTotal(); |
| | | Map<String, WorkCubeTotalAxis> cubeMap = new HashMap<String, WorkCubeTotalAxis>(); |
| | | if (workCubeTotalAxes != null) { |
| | | for (WorkCubeTotalAxis w : workCubeTotalAxes) { |
| | |
| | | } |
| | | } |
| | | ArrayList<Number> data4 = new ArrayList<Number>(); |
| | | ArrayList<Number> data5 = new ArrayList<Number>(); |
| | | SimpleDateFormat sfCube = new SimpleDateFormat("yyyy-MM-dd"); |
| | | Calendar calendarCube = Calendar.getInstance(); |
| | | calendarCube.add(Calendar.DATE, -12); |
| | | for (int i = 0; i < 12; i++) { |
| | | calendarCube.add(Calendar.DATE, -7); |
| | | for (int i = 0; i < 7; i++) { |
| | | calendarCube.add(Calendar.DATE, 1); |
| | | String str = sfCube.format(calendarCube.getTime()); |
| | | WorkCubeTotalAxis cubeAxis = cubeMap.get(str); |
| | | data4.add(cubeAxis == null || cubeAxis.getCube5Total() == null ? 0 : cubeAxis.getCube5Total()); |
| | | data5.add(cubeAxis == null || cubeAxis.getCube15Total() == null ? 0 : cubeAxis.getCube15Total()); |
| | | } |
| | | Number[] array4 = new Number[data4.size()]; |
| | | cube5.setData(data4.toArray(array4)); |
| | | list.add(cube5); |
| | | Number[] array5 = new Number[data5.size()]; |
| | | cube15.setData(data5.toArray(array5)); |
| | | list.add(cube15); |
| | | |
| | | } |
| | | map.put("rows",list); |
| | | return R.ok(map); |
| | |
| | | * 入出库按小时折线:横轴为「当前整点起向前共 12 小时」滚动窗口,与库表 ymd(yyyy-MM-dd HH)对齐 |
| | | */ |
| | | @GetMapping("/line/charts/hourly") |
| | | public R locIoLineChartsHourly() { |
| | | public synchronized R locIoLineChartsHourly() { |
| | | Map<String, Object> map = new HashMap<>(); |
| | | List<AxisBean> list = new ArrayList<>(); |
| | | |
| | |
| | | ArrayList<Integer> data2 = new ArrayList<>(); |
| | | ArrayList<Double> data3 = new ArrayList<>(); |
| | | ArrayList<Double> data4 = new ArrayList<>(); |
| | | ArrayList<Double> data5 = new ArrayList<>(); |
| | | List<String> categories = new ArrayList<>(); |
| | | |
| | | final int n = 12; |
| | |
| | | int outV = 0; |
| | | double inC = 0; |
| | | double outC = 0; |
| | | double outD = 0; |
| | | for (WorkChartAxis w : listChart) { |
| | | if (w.getYmd() != null && key.equals(w.getYmd().trim())) { |
| | | inV = w.getInqty(); |
| | | outV = w.getOutqty(); |
| | | inC = w.getCube_inqty(); |
| | | outC = w.getCube_outqty(); |
| | | inC = w.getCubeInqty(); |
| | | outC = w.getCubeOutqty(); |
| | | outD = w.getOutTeu(); |
| | | break; |
| | | } |
| | | } |
| | | data1.add(inV); |
| | | data2.add(outV); |
| | | data3.add(inC); |
| | | data4.add(outC); |
| | | data5.add(outD); |
| | | calendar.add(Calendar.HOUR_OF_DAY, 1); |
| | | } |
| | | |
| | |
| | | outqty.setData(data2.toArray(array2)); |
| | | list.add(outqty); |
| | | |
| | | AxisBean cubeInqty = new AxisBean(); |
| | | cubeInqty.setName("入库体积"); |
| | | Integer[] array3 = new Integer[data3.size()]; |
| | | cubeInqty.setData(data3.toArray(array3)); |
| | | list.add(cubeInqty); |
| | | if (data3.size() >0) { |
| | | AxisBean cubeInqty = new AxisBean(); |
| | | cubeInqty.setName("入库体积"); |
| | | Double [] array3 = new Double[data3.size()]; |
| | | cubeInqty.setData(data3.toArray(array3)); |
| | | list.add(cubeInqty); |
| | | } |
| | | |
| | | AxisBean cubeOutqty = new AxisBean(); |
| | | cubeOutqty.setName("出库体积"); |
| | | Integer[] array4 = new Integer[data4.size()]; |
| | | cubeOutqty.setData(data4.toArray(array4)); |
| | | list.add(cubeOutqty); |
| | | if (data4.size() >0) { |
| | | AxisBean cubeOutqty = new AxisBean(); |
| | | cubeOutqty.setName("出库体积"); |
| | | Double[] array4 = new Double[data4.size()]; |
| | | cubeOutqty.setData(data4.toArray(array4)); |
| | | list.add(cubeOutqty); |
| | | } |
| | | |
| | | if (data5.size() >0) { |
| | | AxisBean cubeOutqty = new AxisBean(); |
| | | cubeOutqty.setName("出库TEU"); |
| | | Double[] array5 = new Double[data4.size()]; |
| | | cubeOutqty.setData(data5.toArray(array5)); |
| | | list.add(cubeOutqty); |
| | | } |
| | | |
| | | |
| | | map.put("categories", categories); |
| | | map.put("rows", list); |
| | |
| | | |
| | | // 总库位数 |
| | | Integer total1 = (int) Arith.add(0, locUseRate.getFqty(), locUseRate.getOqty(), locUseRate.getUqty(), locUseRate.getXqty()); |
| | | Integer total = total1>40000?40000:total1; |
| | | Integer total = total1>40000?6528:total1; |
| | | // 使用中 |
| | | Integer used = locUseRate.getFqty() + locUseRate.getUqty(); |
| | | // 库位使用率 |
| | |
| | | Integer count = 0; |
| | | String supp = ""; |
| | | //该订单累计入出库件数 |
| | | List<WrkMast> orderNo = wrkMastService.selectList(new EntityWrapper<WrkMast>().eq("user_no", wrkMast.getUserNo())); |
| | | List<WrkMastLog> userNo = wrkMastLogService.selectList(new EntityWrapper<WrkMastLog>().eq("user_no", wrkMast.getUserNo()).eq("wrk_sts",15L)); |
| | | Integer ioType = wrkMast.getIoType(); |
| | | Integer suppCount = 0; |
| | | Integer sum = 0; |
| | | if (ioType != null && ioType < 100) { |
| | | if (orderNo != null && orderNo.size() > 0) { |
| | | count = orderNo.size(); |
| | | } |
| | | if (userNo != null && userNo.size() > 0) { |
| | | count = userNo.size()+count+1; |
| | | } |
| | | supp = count + ""; |
| | | supp = String.valueOf(resolveInboundSupp(wrkMast)); |
| | | map.put("supp", supp); |
| | | }else { |
| | | if (userNo != null && userNo.size() > 0) { |
| | | count = userNo.size()+1; |
| | | String[] split = wrkDetls.get(0).getSupp().split("/"); |
| | | if (split != null && split.length > 0) { |
| | | sum = Integer.valueOf(split[split.length - 1]); |
| | | }else { |
| | | sum = Integer.valueOf(wrkDetls.get(0).getSupp()); |
| | | } |
| | | supp = count + ""; |
| | | List<WrkMast> userNo = wrkMastService.selectList(new EntityWrapper<WrkMast>().eq("user_no", wrkMast.getUserNo()).in("wrk_sts",11,12,21,22,25)); |
| | | suppCount = sum - userNo.size(); |
| | | map.put("supp", suppCount + "/" + sum); |
| | | } |
| | | map.put("supp", supp); |
| | | |
| | | //耗时 |
| | | String costTime = resolveCostTime(wrkMast, wrkDetls); |
| | | map.put("costTime", costTime); |
| | | Long costTime = resolveCostTime(wrkMast); |
| | | map.put("costTime", String.valueOf(costTime)); |
| | | |
| | | return R.ok().add(map); |
| | | } |
| | | |
| | | private String resolveCostTime(WrkMast wrkMast, List<WrkDetl> wrkDetls) { |
| | | Long resolveCostTime(WrkMast wrkMast) { |
| | | return resolveCostTime(wrkMast, new Date()); |
| | | } |
| | | |
| | | Long resolveCostTime(WrkMast wrkMast, Date now) { |
| | | if (wrkMast == null || wrkMast.getIoType() == null) { |
| | | return "0"; |
| | | return 0L; |
| | | } |
| | | |
| | | Date createTime; |
| | | if (wrkMast.getIoType() < 100) { |
| | | createTime = resolveInboundTaskCreateTime(wrkMast, wrkDetls); |
| | | } else { |
| | | 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 Date resolveInboundTaskCreateTime(WrkMast wrkMast, List<WrkDetl> wrkDetls) { |
| | | if (wrkMast == null) { |
| | | return null; |
| | | } |
| | | |
| | | if (!Cools.isEmpty(wrkMast.getUserNo())) { |
| | | Date userNoCreateTime = resolveUserNoCreateTime(wrkMast.getUserNo()); |
| | | if (userNoCreateTime != null) { |
| | | return userNoCreateTime; |
| | | if (Cools.isEmpty(wrkMast.getTrainNo())) { |
| | | return 0L; |
| | | } |
| | | return minutesBetween(wrkMastService.firstInboundCreateTimeByTrainNo(wrkMast.getTrainNo()), resolveTaskCreateTime(wrkMast)); |
| | | } |
| | | |
| | | String orderNo = resolveOrderNo(wrkMast, wrkDetls); |
| | | if (Cools.isEmpty(orderNo)) { |
| | | return null; |
| | | } |
| | | return resolveOrderCreateTime(orderNo); |
| | | return minutesBetween(resolveTaskCreateTime(wrkMast), now); |
| | | } |
| | | |
| | | private Date resolveUserNoCreateTime(String userNo) { |
| | | if (Cools.isEmpty(userNo)) { |
| | | return null; |
| | | int resolveInboundSupp(WrkMast wrkMast) { |
| | | if (wrkMast == null || wrkMast.getIoType() == null || wrkMast.getIoType() >= 100 || Cools.isEmpty(wrkMast.getTrainNo())) { |
| | | return 0; |
| | | } |
| | | return minDate( |
| | | minCreateTime(wrkMastService.selectList(new EntityWrapper<WrkMast>().eq("user_no", userNo))), |
| | | minCreateTime(wrkMastLogService.selectList(new EntityWrapper<WrkMastLog>().eq("user_no", userNo))) |
| | | ); |
| | | } |
| | | |
| | | 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))) |
| | | ); |
| | | Date currentCreateTime = minDate( |
| | | minCreateTime(wrkMastService.selectList(new EntityWrapper<WrkMast>().eq("user_no", orderNo))), |
| | | minCreateTime(wrkDetlService.selectList(new EntityWrapper<WrkDetl>().eq("order_no", orderNo))) |
| | | ); |
| | | return minDate(historyCreateTime, currentCreateTime); |
| | | } |
| | | |
| | | private Date minDate(Date first, Date second) { |
| | | if (first == null) { |
| | | return second; |
| | | } |
| | | if (second == null) { |
| | | return first; |
| | | } |
| | | return first.before(second) ? first : second; |
| | | return wrkMastService.finishedInboundPalletCountByTrainNo(wrkMast.getTrainNo()); |
| | | } |
| | | |
| | | private Date resolveTaskCreateTime(WrkMast wrkMast) { |
| | | if (wrkMast == null) { |
| | | return null; |
| | | } |
| | | return minDate(minDate(wrkMast.getAppeTime(), wrkMast.getIoTime()), wrkMast.getModiTime()); |
| | | return wrkMast.getAppeTime() == null ? wrkMast.getIoTime() : wrkMast.getAppeTime(); |
| | | } |
| | | |
| | | private Date minCreateTime(List<?> list) { |
| | | if (Cools.isEmpty(list)) { |
| | | return null; |
| | | private Long minutesBetween(Date startTime, Date endTime) { |
| | | if (startTime == null || endTime == null) { |
| | | return 0L; |
| | | } |
| | | Date min = null; |
| | | for (Object item : list) { |
| | | Date createTime = resolveCreateTime(item); |
| | | if (createTime == null) { |
| | | continue; |
| | | } |
| | | if (min == null || createTime.before(min)) { |
| | | min = createTime; |
| | | } |
| | | long diff = endTime.getTime() - startTime.getTime(); |
| | | if (diff <= 0) { |
| | | return 0L; |
| | | } |
| | | return min; |
| | | } |
| | | |
| | | private Date resolveCreateTime(Object item) { |
| | | if (item instanceof WrkMast) { |
| | | WrkMast wrkMast = (WrkMast) item; |
| | | return minDate(minDate(wrkMast.getAppeTime(), wrkMast.getIoTime()), wrkMast.getModiTime()); |
| | | } |
| | | if (item instanceof WrkMastLog) { |
| | | WrkMastLog wrkMastLog = (WrkMastLog) item; |
| | | return minDate(minDate(wrkMastLog.getAppeTime(), wrkMastLog.getIoTime()), wrkMastLog.getModiTime()); |
| | | } |
| | | if (item instanceof WrkDetl) { |
| | | WrkDetl wrkDetl = (WrkDetl) item; |
| | | return minDate(minDate(wrkDetl.getAppeTime(), wrkDetl.getIoTime()), wrkDetl.getModiTime()); |
| | | } |
| | | if (item instanceof WrkDetlLog) { |
| | | WrkDetlLog wrkDetlLog = (WrkDetlLog) item; |
| | | return minDate(minDate(wrkDetlLog.getAppeTime(), wrkDetlLog.getIoTime()), wrkDetlLog.getModiTime()); |
| | | } |
| | | return null; |
| | | return diff / MILLIS_PER_MINUTE; |
| | | } |
| | | } |
| | | |