0515周四

经过多天的努力,成功实现了两个表的关联查询并将其展示在列表页面。使用JSP标签库进行列表显示,通过覆盖父类的LIST方法完成控制层ACTION的编写,在sqlmap.xml中自定义SQL语句实现数据获取。

这么多天的实践加受鞭策,终于能看到一点小太阳了。。呵

今天终于能实现一个两表的关联查询,并实现其列表页面,由于JSP页面用的是一个标签(ec)来进行列表显示操作,比较好用,开始不知咋弄,下午终于能使上了,开心,

中间的控制层ACTION中的方法也实现的比较简单,直接覆盖父类的LIST方法(由于需求是两表关联后结果,所以得覆盖,不然 就不用此操作),然后在sqlmap.xml文件中添加select的sql语句,现在其它的都可工具生成了,就剩这sql语句得自个去拼了。。

晚上得回基地,论文导师来了,得回去受受教。。。周末就要答辩了。。。这两晚都多跑跑那系统,别到时上正场,焉了就惨了。。不是一般的惨哦。。。。得回到母校去再次校答辩,回来路费都得好几个“老人头”呢。。。

能省则省。。。。恩。

我思故我在。。。。

for (MrpListDTO order : list) { //需求日期 Date demandDate = order.getDemandDate(); String onlyDaily = order.getOnlyDaily(); String lockOrder = order.getLockOrder(); Date endDate = order.getEndDate(); order.setVersion(version); //历史工单不用排产, 时间已经在前面占用了, 这里不用处理, 除非是手工单 if (PpOrderLockStatus.LOCKED.getCode().equals(lockOrder) && !PpOrderTypeEnum.手工建单.getCode().equals(order.getType())) { continue; } orderStartDate = null; needOccupy = false; occupyTime = 0L; classMinute = 0; orderClassTypeMap.clear(); if (PpOrderTypeEnum.手工建单.getCode().equals(order.getType())) { orderStartDate = DateUtils.format(order.getStartTime(), DateUtils.YYYY_M_D); currentScheduleTime = order.getStartTimeV2() == null ? order.getStartTime() : order.getStartTimeV2(); } totalQty = BigDecimal.ZERO; addQty = BigDecimal.ZERO; actualClassNumber = BigDecimal.ZERO; originalQty = order.getQty(); totalTime = order.getTotalTime(); order.calculateTimeV3(); order.calculateTimeV4(); unitTime = order.getMinutesQty(); //计算实际班次 从当前日期到订单需求日期,根据日历信息 实际有多少个班 order.setActualClassNumber(actualClassNumber(order)); preChangeTime = order.getPreChangeTime(); List<PpCalendarDTO> availableDays = calendarMap.get(order.getLine()); if (availableDays.isEmpty()) { emptyCalendarList.add(order.getLine()); continue; } if (PpOrderTypeEnum.手工建单.getCode().equals(order.getType())) { /* * 判断是否有当天的出勤 * */ checkWorkDay(currentScheduleTime, availableDays, order.getLine()); } int len = occupyLists.size(); //availableDays 生产日历 for (int i = 0; i < availableDays.size(); i++) { day = availableDays.get(i); if (orderStartDate != null && !orderStartDate.equals(day.getDateTime())) { continue; } if (PpOrderTypeEnum.手工建单.getCode().equals(order.getType())) { orderStartDate = null; } //根据该产线的前一个工单对应的班次是否占用完 判断是否需要颠倒白晚班 if (lastClassMap.containsKey(order.getLine())) { if (lastClassMap.get(order.getLine())) { classList.sort((t1, t2) -> t2.getSort() - t1.getSort()); } else { classList.sort(Comparator.comparingInt(PpClassDTO::getSort)); } } else { classList.sort(Comparator.comparingInt(PpClassDTO::getSort)); } for (int shiftIndex = 0; shiftIndex < classList.size(); shiftIndex++) { shift = classList.get(shiftIndex); //如果是手工单,开工时间是手工指定的,需要在当天开工 首个班次必须要在指定的时间 if (PpOrderTypeEnum.手工建单.getCode().equals(order.getType()) && totalQty.compareTo(BigDecimal.ZERO) == 0) { if (!order.getClassName().equals(shift.getClassName())) continue; } //记录每个工单用了几种种类型的班次 if (!orderClassTypeMap.containsKey(shift.getClassName())) { orderClassTypeMap.put(shift.getClassName(), shift.getClassName()); classMinute += shift.getEffectiveTime(); } fillDate(day, shift); int availableTime = shift.getEffectiveTime(); int _availableTime = availableTime; //如果是手工单,开工时间可能是在班次的中间,此时需要去掉班次开工时间到指定的开工时间之间的时间 否则结束时间会溢出 if (PpOrderTypeEnum.手工建单.getCode().equals(order.getType()) && day.getDateTime().equals(DateUtils.format(order.getStartTime(), DateUtils.YYYY_M_D))) { /* * 手工前台给定的时间可能是晚班时间(超过了晚上12点那种) 此时需要特殊处理 * 手工单的实际开工时间需要特殊处理 * */ setHandOrderTime(order); availableTime = getEffectiveTime(shift, order.getStartTime()); //说明手工单是在班次的中间开工 那么该班次需要设为占用日期, needOccupy = true; order.setMiddle(true); } String occupyDate = day.getDateTime(); shiftKey = occupyDate + "_" + order.getLine() + "_" + shift.getClassName(); occupiedTime = occupiedTimeByShift .computeIfAbsent(shiftKey, k -> new HashMap<>()) .getOrDefault(shift.getClassName(), 0); // 计算停产期间影响的时间 int stopOverlapMinutes = calculateStopOverlap(shift.getBeginTime(), shift.getEndTime(), day.getDateTime()); if (!needOccupy) { remainingTime = availableTime - occupiedTime - stopOverlapMinutes; } else { remainingTime = Math.min(_availableTime - occupiedTime - stopOverlapMinutes, availableTime - stopOverlapMinutes); } if (remainingTime > 0) { int timeToAllocate = Math.min(remainingTime, order.getTotalTime().intValue()); if (preChangeTime.intValue() > 0) { timeToAllocate = Math.min(remainingTime, preChangeTime.intValue()); } remainingTime = remainingTime - timeToAllocate; //占用 BigDecimal augend; if (preChangeTime.compareTo(BigDecimal.ZERO) > 0) { augend = BigDecimal.ZERO; } else { augend = BigDecimal.valueOf(timeToAllocate).multiply(unitTime).setScale(0, RoundingMode.HALF_UP); if (augend.compareTo(originalQty.subtract(totalQty)) > 0) { //防止数量溢出 augend = originalQty.subtract(totalQty); } } occupyTime = occupyTime + timeToAllocate; addQty = BigDecimal.ZERO; // TMC工单不需要 if (!"2".equals(order.getType())) { // if (order.getOperation() == PpOrderOperationEnum.正常排程 && remainingTime > 0 && // BigDecimal.valueOf(occupyTime).compareTo(order.getTotalTime().add(order.getPreChangeTime())) >= 0) { // //工单本班次可以做完并且本班次还有剩余时间 // //ABS(当班剩余可用时间对应的产量)/生产批量<20% 时,将该班次排满(将20%时间的产量都加到当前的工单上,工单数量+20%产量) // addQty = order.getQty() // .divide(totalTime, 4, RoundingMode.HALF_UP) // .multiply(BigDecimal.valueOf(remainingTime)) // .setScale(4, RoundingMode.HALF_UP); // // if (addQty.divide(order.getQty(), 2, RoundingMode.HALF_UP).compareTo(assemblyPercent) > 0) { // addQty = BigDecimal.ZERO; // } else { // addQty = addQty.setScale(0, RoundingMode.HALF_UP); // timeToAllocate = timeToAllocate + remainingTime; // totalTime = totalTime.add(BigDecimal.valueOf(remainingTime)); // remainingTime = 0; // } // } } ppClassDTO = shift; Date shiftEndTime; if (order.getClassName() == null) { order.setClassName(shift.getClassName()); } //手工单的首个班次需要指定开工时间:目前只有手工单在排程时有首班次开工时间 if (currentScheduleTime == null) { currentScheduleTime = shift.getBeginTime(); } //判断开始时间是否在休息时间内 如果是 开始时间等于休息结束时间 currentScheduleTime = parseTimeByClassStop(ppClassDTO, currentScheduleTime); shiftEndTime = new Date(currentScheduleTime.getTime() + (timeToAllocate * 60000L)); if (order.getStartTime() == null || (totalQty.compareTo(BigDecimal.ZERO) <= 0 && PpOrderTypeEnum.手工建单.getCode().equals(order.getType()))) { //0515改动后 order.setStartTime(currentScheduleTime); } //班组内时间已经用完 //判断结束时间是否等于班次结束时间 如果不等于,则判断是否需要加上中间的休息时间 if (shiftEndTime.compareTo(ppClassDTO.getEndTime()) != 0) { shiftEndTime = parseTimeByClassStop(currentScheduleTime, shiftEndTime, ppClassDTO); } //班次完工时间 order.setEndTime(shiftEndTime); PpScheduleOccupyList occList = getOccList(order, timeToAllocate, shift.getClassName(), augend, occupyDate, currentScheduleTime); if (augend.compareTo(BigDecimal.ZERO) == 0) { occList.setShiftType(PpShiftTypeEnum.换型班次.getCode()); } else if (order.isClimb() && order.getClimQty() > 0) { occList.setShiftType(PpShiftTypeEnum.爬坡班次.getCode()); } else { occList.setShiftType(PpShiftTypeEnum.正常班次.getCode()); } List<PpScheduleOccupyList> _occList = null; Date shiftBeginTime; if (this.lineOccupyTimeMap.containsKey(order.getLine()) && this.lineOccupyTimeMap.get(order.getLine()).size() > 0) { //判断是否需要将一个班次拆分为多个 _occList = spiltOccupy(occList, shift); PpScheduleOccupyList occupyList = _occList.get(_occList.size() - 1); shiftBeginTime = occupyList.getPstartTime(); } else { shiftBeginTime = occList.getPstartTime(); } //获取爬坡阶梯数据,如果存在爬坡阶梯数据并且:1.当前班次的开工时间晚于爬坡阶梯的开始时间 && 2.已爬坡班次数小于需要爬坡的班次数;则从该班次开始爬坡 //返回需要爬坡的班次以及oee、ct数据 if (order.getOeeCtData() == null) { order.setOeeCtData(getClimeData(order, shiftBeginTime)); if (order.getOeeCtData() != null) { /** * 需要爬坡 * */ //去掉已经生产的产量 order.setQty(order.getQty().subtract(totalQty)); //用新的oee和ct计算剩余时间 order.setOee(order.getOeeCtData().oee.toPlainString()); order.setCt(order.getOeeCtData().ct.toPlainString()); order.calculateTime(); //更新单位分钟内生产的数量 unitTime = order.getQty().divide(order.getTotalTime(), 4, RoundingMode.HALF_UP); shiftIndex--; continue; } } if (this.lineOccupyTimeMap.containsKey(order.getLine()) && this.lineOccupyTimeMap.get(order.getLine()).size() > 0) { //判断是否需要将一个班次拆分为多个 _occList = spiltOccupy(occList, shift); PpScheduleOccupyList occupyList = _occList.get(_occList.size() - 1); shiftBeginTime = occupyList.getPstartTime(); /* * 最后一个班次加上 20% 的产量 * */ occupyList.setAddQty(occupyList.getQty().add(addQty)); shiftEndTime = occupyList.getPfinishedTime(); if (totalQty.compareTo(BigDecimal.ZERO) <= 0) { order.setStartTime(_occList.get(0).getPstartTime()); } //班次完工时间 order.setEndTime(shiftEndTime); this.occupyLists.addAll(_occList); } else { shiftBeginTime = occList.getPstartTime(); this.occupyLists.add(occList); } occupiedTimeByShift.get(shiftKey).put(shift.getClassName(), occupiedTime + timeToAllocate); this.lineOccupyTimeMap.putIfAbsent(order.getLine(), new ArrayList<>()); if (_occList != null) { this.lineOccupyTimeMap.get(order.getLine()).addAll(buildPpClassRemoveTime(_occList)); } else { this.lineOccupyTimeMap.get(order.getLine()).add(buildPpClassRemoveTime(occList)); } totalQty = totalQty.add(augend); //优先消耗掉换型时间 if (preChangeTime.intValue() <= 0) { order.setTotalTime(order.getTotalTime().subtract(new BigDecimal(timeToAllocate))); // // TMC工单不需要 // if (!"2".equals(order.getType())) { //// 工单本班次可以做完并且本班次还有剩余时间, ABS(当班剩余可用时间对应的产量)/生产批量<20% 时,将工单后续数量舍去 // if (order.getOperation() == PpOrderOperationEnum.正常排程 && // (order.getTotalTime().multiply(unitTime).setScale(6, RoundingMode.HALF_UP)) // .divide(BigDecimalUtils.getDecimal(order.getPbatch()), 4, RoundingMode.HALF_UP) // .compareTo(assemblyPercent) < 0) { // // order.setTotalTime(BigDecimal.ZERO); // totalTime = totalTime.subtract(order.getTotalTime()); // } // } } else { preChangeTime = preChangeTime.subtract(new BigDecimal(timeToAllocate)); if (remainingTime > 0) { i--; break; } } currentScheduleTime = null; if (order.isClimb() && order.getClimQty() > 0) { //爬坡班次数-1 order.setClimQty(order.getClimQty() - 1); order.getOeeCtData().climeData.setClimedQty(order.getOeeCtData().climeData.getClimedQty().add(BigDecimal.ONE)); //添加爬坡阶梯和工单班次数对照记录 if (order.getOeeCtData().climeData.getOrderQtyMap().containsKey(order.getOrderNo())) { order.getOeeCtData().climeData.getOrderQtyMap().put(order.getOrderNo(), order.getOeeCtData().climeData.getOrderQtyMap().get(order.getOrderNo()).add(BigDecimal.ONE)); } else { order.getOeeCtData().climeData.getOrderQtyMap().put(order.getOrderNo(), BigDecimal.ONE); } if (order.getClimQty() <= 0) { //重新计算工单工时 //去掉已经生产的产量 order.setQty(originalQty.subtract(totalQty)); //用新的oee和ct计算剩余时间 order.setOee(order.getOeeCtData().oeeOrigin); order.setCt(order.getOeeCtData().ctOrigin); order.calculateTime(); if (order.getTotalTime().compareTo(BigDecimal.ZERO) <= 0) { //爬坡完成 工单也完成了 break; } //更新单位分钟内生产的数量 unitTime = order.getQty().divide(order.getTotalTime(), 4, RoundingMode.HALF_UP); } } if (order.getTotalTime().compareTo(BigDecimal.ZERO) <= 0) { break; } } } if (order.getTotalTime().compareTo(BigDecimal.ZERO) <= 0) { order.setQty(totalQty); order.setAddQty(order.getQty().add(addQty)); } if (occupyLists.size() > len) { //判断该产线下个工单是否需要颠倒白晚班次 extracted(order, lastClassMap, ppClassDTO, remainingTime, lineClassFlag, day); len = occupyLists.size(); } if (order.getTotalTime().compareTo(BigDecimal.ZERO) <= 0) { break; } } if (order.getEndTime() == null) { //日历没维护 throw new ServiceException(String.format("请先维护%s区域%s产线%s的生产日历", order.getArea(), order.getLine(), getMsg(availableDays.get(availableDays.size() - 1).getDateTime()))); } if (DateUtils.format(order.getEndTime(), DateUtils.YYYY_MM_DD).compareTo(DateUtils.format(demandDate, DateUtils.YYYY_MM_DD)) > 0) { //延期 order.setDelay("1"); } if (order.getActualClassNumber().compareTo(actualClassNumber) < 0) { //爆产 order.setOverflow("1"); } //实际排班班次 order.setTotalTime(getTotalTime(occupyLists, order.getOrderNo())); order.setActualClassNumber(BigDecimal.valueOf(occupyTime).divide(BigDecimal.valueOf(classMinute).divide(BigDecimal.valueOf(orderClassTypeMap.size())), 6, RoundingMode.HALF_UP)); order.setCreateTime(now); order.setCreateBy(username); order.setTimeDesc(getTimeDesc(order.getTotalTime())); //手工单自动锁定 if (PpOrderTypeEnum.手工建单.getCode().equals(order.getType())) { autoLockOrderList.add(buildLockOrder(order)); } //工单数量不能改 // order.setQty(originalQty); } 日历类public class PpCalendarDTO { private Long id; private String dateTime;//yyyy-MM-dd private String line;} 1. onlyDaily="2"的数据通常会先排,="1"的通常后排, 这个已经处理好了 2. 日历类已升序 3. onlyDaily="1"的数据排的时候要注意, 因为数据都是一条条紧跟着排的, 有可能上一条的结束时间就是下一条的开始时间, 但是有新规: onlyDaily="1"的数据不能默认跟着="2"的数据排. 因为他们的数据通常demandDate会比较靠后, 不能提前太多生产: a. onlyDaily="1"的数据按照demandDate, 最多提前到demandDate所在周的周一, 如果有多条公用周一, 那就接着排, 例如, 第一条onlyDaily="1"排在周一, 那第二条就跟着第一条的结束时间排, 这个其实源代码逻辑就有; b. 如果onlyDaily="2"的数据排的最后一条结束时间与第一条="1"的数据在同一周, 那="1"的数据也不用提前到周一了, 就跟着="2"的排; c. ="1"的数据还是要看前一条数据结束时间是否和当条demandDate在同一周, 如果是, 那就不用提前到周一, 就跟着前一条的结束时间排 d. 其它代码别动.别改
最新发布
11-11
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值