| | |
| | | import com.stylefeng.guns.core.util.SinataUtil; |
| | | import com.stylefeng.guns.core.util.ToolUtil; |
| | | import com.stylefeng.guns.modular.system.model.*; |
| | | import com.stylefeng.guns.modular.system.dao.LineShiftDriverMapper; |
| | | import com.stylefeng.guns.modular.system.service.*; |
| | | import com.stylefeng.guns.modular.system.util.ResultUtil; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | |
| | | |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.ArrayList; |
| | | import java.util.Calendar; |
| | | import java.util.Date; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.math.BigDecimal; |
| | |
| | | |
| | | @Autowired |
| | | private ITLineCompanyService itLineCompanyService; |
| | | |
| | | @Autowired |
| | | private LineShiftDriverMapper lineShiftDriverMapper; |
| | | |
| | | @Autowired |
| | | private ITDriverService tDriverService; |
| | | |
| | | /** |
| | | * 跳转到跨城站点管理首页 |
| | |
| | | lineCompany.setCompanyId(jsonObject.getInteger("companyId")); |
| | | lineCompany.setInsertTime(new Date()); |
| | | lineCompany.setInsertUserId(ShiroKit.getUser().getId()); |
| | | lineCompany.setAutoPlan(2); |
| | | itLineCompanyService.insert(lineCompany); |
| | | } |
| | | } |
| | | return SUCCESS_TIP; |
| | | } |
| | | |
| | | /** |
| | | * 查询线路已分配企业 |
| | | */ |
| | | @RequestMapping(value = "/lineCompanyList") |
| | | @ResponseBody |
| | | public Object lineCompanyList(Integer lineId) { |
| | | if (lineId == null) { |
| | | return ResultUtil.error("线路ID不能为空"); |
| | | } |
| | | return ResultUtil.success(tLineService.getLineCompanyList(lineId)); |
| | | } |
| | | |
| | | /** |
| | | * 排班管理页面 |
| | | */ |
| | | @RequestMapping(value = "/schedulePage") |
| | | public String schedulePage(Integer lineId, Integer companyId, Model model) { |
| | | TLine line = tLineService.selectById(lineId); |
| | | TCompany company = itCompanyService.selectById(companyId); |
| | | TLineCompany lineCompany = itLineCompanyService.selectOne(new EntityWrapper<TLineCompany>() |
| | | .eq("lineId", lineId).eq("companyId", companyId)); |
| | | model.addAttribute("lineId", lineId); |
| | | model.addAttribute("companyId", companyId); |
| | | model.addAttribute("lineName", line == null ? "" : line.getName()); |
| | | model.addAttribute("companyName", company == null ? "" : company.getName()); |
| | | model.addAttribute("autoPlan", lineCompany == null || lineCompany.getAutoPlan() == null ? 2 : lineCompany.getAutoPlan()); |
| | | return PREFIX + "tLine_schedule.html"; |
| | | } |
| | | |
| | | /** |
| | | * 排班管理-月份数据 |
| | | */ |
| | | @RequestMapping(value = "/schedule/month") |
| | | @ResponseBody |
| | | public Object scheduleMonth(Integer lineId, Integer companyId, String month) { |
| | | try { |
| | | TLineCompany lineCompany = checkLineCompany(lineId, companyId); |
| | | if (lineCompany == null) { |
| | | return ResultUtil.error("线路未关联该企业"); |
| | | } |
| | | if (SinataUtil.isEmpty(month)) { |
| | | month = new SimpleDateFormat("yyyy-MM").format(new Date()); |
| | | } |
| | | SimpleDateFormat monthSdf = new SimpleDateFormat("yyyy-MM"); |
| | | Date monthDate = monthSdf.parse(month); |
| | | Calendar cal = Calendar.getInstance(); |
| | | cal.setTime(monthDate); |
| | | cal.set(Calendar.DAY_OF_MONTH, 1); |
| | | String monthStart = new SimpleDateFormat("yyyy-MM-dd").format(cal.getTime()); |
| | | int maxDay = cal.getActualMaximum(Calendar.DAY_OF_MONTH); |
| | | cal.set(Calendar.DAY_OF_MONTH, maxDay); |
| | | String monthEnd = new SimpleDateFormat("yyyy-MM-dd").format(cal.getTime()); |
| | | |
| | | Integer companyType = getCompanyType(companyId); |
| | | List<Map<String, Object>> stats = lineShiftDriverMapper.getMonthScheduleStats(lineId, monthStart, monthEnd, companyId, companyType); |
| | | Map<String, Integer> dayAssignMap = new HashMap<>(); |
| | | for (Map<String, Object> stat : stats) { |
| | | dayAssignMap.put(String.valueOf(stat.get("dayStr")), Integer.parseInt(String.valueOf(stat.get("assignNum")))); |
| | | } |
| | | List<TLineShift> shifts = itLineShiftService.selectList(new EntityWrapper<TLineShift>().eq("lineId", lineId).ne("state", 3)); |
| | | int totalNeed = 0; |
| | | for (TLineShift shift : shifts) { |
| | | totalNeed += (shift.getCarNum() == null ? 0 : shift.getCarNum()); |
| | | } |
| | | |
| | | List<Map<String, Object>> dayList = new ArrayList<>(); |
| | | cal.setTime(monthDate); |
| | | cal.set(Calendar.DAY_OF_MONTH, 1); |
| | | for (int i = 1; i <= maxDay; i++) { |
| | | cal.set(Calendar.DAY_OF_MONTH, i); |
| | | String dayStr = new SimpleDateFormat("yyyy-MM-dd").format(cal.getTime()); |
| | | int assignNum = dayAssignMap.get(dayStr) == null ? 0 : dayAssignMap.get(dayStr); |
| | | Map<String, Object> obj = new HashMap<>(); |
| | | obj.put("day", dayStr); |
| | | obj.put("assignNum", assignNum); |
| | | obj.put("totalNeed", totalNeed); |
| | | if (totalNeed <= 0) { |
| | | obj.put("status", 0); |
| | | obj.put("statusText", "无班次"); |
| | | } else if (assignNum >= totalNeed) { |
| | | obj.put("status", 1); |
| | | obj.put("statusText", "已排班"); |
| | | } else { |
| | | obj.put("status", 2); |
| | | obj.put("statusText", "未排满"); |
| | | } |
| | | dayList.add(obj); |
| | | } |
| | | Map<String, Object> result = new HashMap<>(); |
| | | result.put("month", month); |
| | | result.put("totalNeed", totalNeed); |
| | | result.put("days", dayList); |
| | | return ResultUtil.success(result); |
| | | } catch (Exception ex) { |
| | | ex.printStackTrace(); |
| | | return ResultUtil.runErr(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 排班管理-某天班次详情 |
| | | */ |
| | | @RequestMapping(value = "/schedule/dayDetail") |
| | | @ResponseBody |
| | | public Object scheduleDayDetail(Integer lineId, Integer companyId, String day) { |
| | | try { |
| | | TLineCompany lineCompany = checkLineCompany(lineId, companyId); |
| | | if (lineCompany == null) { |
| | | return ResultUtil.error("线路未关联该企业"); |
| | | } |
| | | Integer companyType = getCompanyType(companyId); |
| | | List<Map<String, Object>> shiftList = lineShiftDriverMapper.getDayShiftSchedule(lineId, day, companyId, companyType); |
| | | for (Map<String, Object> shift : shiftList) { |
| | | Integer lineShiftId = Integer.valueOf(String.valueOf(shift.get("lineShiftId"))); |
| | | List<Map<String, Object>> drivers = lineShiftDriverMapper.getDayShiftDrivers(lineShiftId, day, companyId, companyType); |
| | | int carNum = shift.get("carNum") == null ? 0 : Integer.parseInt(String.valueOf(shift.get("carNum"))); |
| | | int assignNum = shift.get("assignNum") == null ? 0 : Integer.parseInt(String.valueOf(shift.get("assignNum"))); |
| | | shift.put("drivers", drivers); |
| | | shift.put("remainNum", Math.max(carNum - assignNum, 0)); |
| | | shift.put("canAdd", assignNum < carNum ? 1 : 0); |
| | | } |
| | | return ResultUtil.success(shiftList); |
| | | } catch (Exception ex) { |
| | | ex.printStackTrace(); |
| | | return ResultUtil.runErr(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 排班管理-可添加司机 |
| | | */ |
| | | @RequestMapping(value = "/schedule/drivers") |
| | | @ResponseBody |
| | | public Object scheduleDrivers(Integer lineId, Integer companyId, Integer lineShiftId, String day) { |
| | | try { |
| | | TLineCompany lineCompany = checkLineCompany(lineId, companyId); |
| | | if (lineCompany == null) { |
| | | return ResultUtil.error("线路未关联该企业"); |
| | | } |
| | | Integer companyType = getCompanyType(companyId); |
| | | return ResultUtil.success(lineShiftDriverMapper.getAvailableDrivers(lineId, lineShiftId, day, companyId, companyType)); |
| | | } catch (Exception ex) { |
| | | ex.printStackTrace(); |
| | | return ResultUtil.runErr(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 排班管理-新增排班 |
| | | */ |
| | | @RequestMapping(value = "/schedule/add") |
| | | @ResponseBody |
| | | public Object scheduleAdd(Integer lineId, Integer companyId, Integer lineShiftId, String day, @RequestParam String driverIds) { |
| | | try { |
| | | TLineCompany lineCompany = checkLineCompany(lineId, companyId); |
| | | if (lineCompany == null) { |
| | | return ResultUtil.error("线路未关联该企业"); |
| | | } |
| | | TLineShift shift = itLineShiftService.selectById(lineShiftId); |
| | | if (shift == null || shift.getState() == 3 || !shift.getLineId().equals(lineId)) { |
| | | return ResultUtil.error("班次不存在"); |
| | | } |
| | | Date dayDate = parseDay(day); |
| | | Integer companyType = getCompanyType(companyId); |
| | | List<Map<String, Object>> currentDrivers = lineShiftDriverMapper.getDayShiftDrivers(lineShiftId, day, companyId, companyType); |
| | | int currentAssignNum = currentDrivers == null ? 0 : currentDrivers.size(); |
| | | int carNum = shift.getCarNum() == null ? 0 : shift.getCarNum(); |
| | | if (currentAssignNum >= carNum) { |
| | | return ResultUtil.error("当前班次已排满"); |
| | | } |
| | | |
| | | List<Integer> driverIdList = parseIdList(driverIds); |
| | | if (driverIdList.size() <= 0) { |
| | | return ResultUtil.error("请选择司机"); |
| | | } |
| | | List<Map<String, Object>> availableDrivers = lineShiftDriverMapper.getAvailableDrivers(lineId, lineShiftId, day, companyId, companyType); |
| | | Map<Integer, Integer> seatMap = new HashMap<>(); |
| | | for (Map<String, Object> driver : availableDrivers) { |
| | | Integer driverId = Integer.valueOf(String.valueOf(driver.get("driverId"))); |
| | | Integer seatNum = driver.get("seatNum") == null ? 5 : Integer.valueOf(String.valueOf(driver.get("seatNum"))); |
| | | seatMap.put(driverId, seatNum); |
| | | } |
| | | List<Integer> validDriverIds = new ArrayList<>(); |
| | | for (Integer driverId : driverIdList) { |
| | | if (seatMap.containsKey(driverId)) { |
| | | validDriverIds.add(driverId); |
| | | } |
| | | } |
| | | if (validDriverIds.size() <= 0) { |
| | | return ResultUtil.error("没有可添加的司机"); |
| | | } |
| | | if (currentAssignNum + validDriverIds.size() > carNum) { |
| | | return ResultUtil.error("可排班人数不足,当前班次最多还能添加" + (carNum - currentAssignNum) + "名司机"); |
| | | } |
| | | |
| | | for (Integer driverId : validDriverIds) { |
| | | Integer count = lineShiftDriverMapper.countExistsSchedule(lineShiftId, driverId, day); |
| | | if (count != null && count > 0) { |
| | | continue; |
| | | } |
| | | int seatNum = seatMap.get(driverId) == null ? 5 : seatMap.get(driverId); |
| | | if (seatNum <= 0) { |
| | | seatNum = 5; |
| | | } |
| | | LineShiftDriver record = new LineShiftDriver(); |
| | | record.setLineShiftId(lineShiftId); |
| | | record.setDriverId(driverId); |
| | | record.setDay(dayDate); |
| | | record.setTotalSeat(seatNum); |
| | | record.setLaveSeat(seatNum); |
| | | record.setLaveSeatNumber(buildSeatNoStr(seatNum)); |
| | | record.setInserTime(new Date()); |
| | | record.setAssignType(2); |
| | | lineShiftDriverMapper.insert(record); |
| | | } |
| | | return ResultUtil.success(); |
| | | } catch (Exception ex) { |
| | | ex.printStackTrace(); |
| | | return ResultUtil.runErr(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 排班管理-删除手动排班 |
| | | */ |
| | | @RequestMapping(value = "/schedule/delete") |
| | | @ResponseBody |
| | | public Object scheduleDelete(Integer scheduleId, Integer lineId, Integer companyId) { |
| | | try { |
| | | TLineCompany lineCompany = checkLineCompany(lineId, companyId); |
| | | if (lineCompany == null) { |
| | | return ResultUtil.error("线路未关联该企业"); |
| | | } |
| | | LineShiftDriver record = lineShiftDriverMapper.selectById(scheduleId); |
| | | if (record == null) { |
| | | return ResultUtil.error("排班记录不存在"); |
| | | } |
| | | if (record.getAssignType() == null || record.getAssignType() != 2) { |
| | | return ResultUtil.error("仅支持删除手动排班记录"); |
| | | } |
| | | TLineShift shift = itLineShiftService.selectById(record.getLineShiftId()); |
| | | if (shift == null || !shift.getLineId().equals(lineId)) { |
| | | return ResultUtil.error("排班记录线路不匹配"); |
| | | } |
| | | TDriver driver = tDriverService.selectById(record.getDriverId()); |
| | | if (driver == null || !checkDriverBelongCompany(driver, companyId)) { |
| | | return ResultUtil.error("司机企业信息不匹配"); |
| | | } |
| | | lineShiftDriverMapper.deleteById(scheduleId); |
| | | return ResultUtil.success(); |
| | | } catch (Exception ex) { |
| | | ex.printStackTrace(); |
| | | return ResultUtil.runErr(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 排班管理-复制排班 |
| | | */ |
| | | @RequestMapping(value = "/schedule/copy") |
| | | @ResponseBody |
| | | public Object scheduleCopy(Integer lineId, Integer companyId, String sourceStart, String sourceEnd, String targetStart) { |
| | | try { |
| | | TLineCompany lineCompany = checkLineCompany(lineId, companyId); |
| | | if (lineCompany == null) { |
| | | return ResultUtil.error("线路未关联该企业"); |
| | | } |
| | | Date sourceStartDate = parseDay(sourceStart); |
| | | Date sourceEndDate = parseDay(sourceEnd); |
| | | Date targetStartDate = parseDay(targetStart); |
| | | if (sourceEndDate.before(sourceStartDate)) { |
| | | return ResultUtil.error("复制结束日期不能早于开始日期"); |
| | | } |
| | | Integer companyType = getCompanyType(companyId); |
| | | List<LineShiftDriver> sourceList = lineShiftDriverMapper.getManualSchedulesForCopy(lineId, sourceStart, sourceEnd, companyId, companyType); |
| | | int addNum = 0; |
| | | int skipNum = 0; |
| | | for (LineShiftDriver source : sourceList) { |
| | | int diff = getDayDiff(sourceStartDate, source.getDay()); |
| | | Date targetDay = addDays(targetStartDate, diff); |
| | | String targetDayStr = formatDay(targetDay); |
| | | Integer count = lineShiftDriverMapper.countExistsSchedule(source.getLineShiftId(), source.getDriverId(), targetDayStr); |
| | | if (count != null && count > 0) { |
| | | skipNum++; |
| | | continue; |
| | | } |
| | | LineShiftDriver target = new LineShiftDriver(); |
| | | target.setLineShiftId(source.getLineShiftId()); |
| | | target.setDriverId(source.getDriverId()); |
| | | target.setDay(targetDay); |
| | | target.setLaveSeat(source.getLaveSeat()); |
| | | target.setLaveSeatNumber(source.getLaveSeatNumber()); |
| | | target.setTotalSeat(source.getTotalSeat()); |
| | | target.setInserTime(new Date()); |
| | | target.setAssignType(2); |
| | | lineShiftDriverMapper.insert(target); |
| | | addNum++; |
| | | } |
| | | Map<String, Object> result = new HashMap<>(); |
| | | result.put("addNum", addNum); |
| | | result.put("skipNum", skipNum); |
| | | return ResultUtil.success(result); |
| | | } catch (Exception ex) { |
| | | ex.printStackTrace(); |
| | | return ResultUtil.runErr(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 排班管理-保存智能排班开关 |
| | | */ |
| | | @RequestMapping(value = "/schedule/autoPlan") |
| | | @ResponseBody |
| | | public Object scheduleAutoPlan(Integer lineId, Integer companyId, Integer autoPlan) { |
| | | if (autoPlan == null || (autoPlan != 1 && autoPlan != 2)) { |
| | | return ResultUtil.error("智能排班参数错误"); |
| | | } |
| | | TLineCompany lineCompany = checkLineCompany(lineId, companyId); |
| | | if (lineCompany == null) { |
| | | return ResultUtil.error("线路未关联该企业"); |
| | | } |
| | | lineCompany.setAutoPlan(autoPlan); |
| | | itLineCompanyService.updateById(lineCompany); |
| | | return ResultUtil.success(); |
| | | } |
| | | /** |
| | | * 修改跨城站点管理 |
| | |
| | | return ResultUtil.success(); |
| | | } |
| | | |
| | | private TLineCompany checkLineCompany(Integer lineId, Integer companyId) { |
| | | if (lineId == null || companyId == null) { |
| | | return null; |
| | | } |
| | | return itLineCompanyService.selectOne(new EntityWrapper<TLineCompany>().eq("lineId", lineId).eq("companyId", companyId)); |
| | | } |
| | | |
| | | private Integer getCompanyType(Integer companyId) { |
| | | TCompany company = itCompanyService.selectById(companyId); |
| | | return company == null ? null : company.getType(); |
| | | } |
| | | |
| | | private boolean checkDriverBelongCompany(TDriver driver, Integer companyId) { |
| | | if (driver == null || companyId == null) { |
| | | return false; |
| | | } |
| | | Integer companyType = getCompanyType(companyId); |
| | | if (companyType == null) { |
| | | return false; |
| | | } |
| | | if (companyType == 2) { |
| | | return driver.getCompanyId() != null && driver.getCompanyId().intValue() == companyId.intValue(); |
| | | } |
| | | if (companyType == 3) { |
| | | return driver.getFranchiseeId() != null && driver.getFranchiseeId().intValue() == companyId.intValue(); |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | private Date parseDay(String day) throws Exception { |
| | | return new SimpleDateFormat("yyyy-MM-dd").parse(day); |
| | | } |
| | | |
| | | private String formatDay(Date day) { |
| | | return new SimpleDateFormat("yyyy-MM-dd").format(day); |
| | | } |
| | | |
| | | private int getDayDiff(Date start, Date end) { |
| | | long oneDay = 24L * 60L * 60L * 1000L; |
| | | long startTime = start.getTime() / oneDay; |
| | | long endTime = end.getTime() / oneDay; |
| | | return (int) (endTime - startTime); |
| | | } |
| | | |
| | | private Date addDays(Date date, int days) { |
| | | Calendar cal = Calendar.getInstance(); |
| | | cal.setTime(date); |
| | | cal.add(Calendar.DAY_OF_MONTH, days); |
| | | return cal.getTime(); |
| | | } |
| | | |
| | | private String buildSeatNoStr(int seatNum) { |
| | | StringBuilder builder = new StringBuilder(); |
| | | for (int i = 1; i <= seatNum; i++) { |
| | | if (i > 1) { |
| | | builder.append(","); |
| | | } |
| | | builder.append(i); |
| | | } |
| | | return builder.toString(); |
| | | } |
| | | |
| | | private List<Integer> parseIdList(String ids) { |
| | | List<Integer> list = new ArrayList<>(); |
| | | if (SinataUtil.isEmpty(ids)) { |
| | | return list; |
| | | } |
| | | try { |
| | | if (ids.startsWith("[")) { |
| | | JSONArray array = JSON.parseArray(ids); |
| | | for (int i = 0; i < array.size(); i++) { |
| | | Integer id = array.getInteger(i); |
| | | if (id != null && !list.contains(id)) { |
| | | list.add(id); |
| | | } |
| | | } |
| | | } else { |
| | | String[] arr = ids.split(","); |
| | | for (String s : arr) { |
| | | if (SinataUtil.isNotEmpty(s)) { |
| | | Integer id = Integer.valueOf(s.trim()); |
| | | if (!list.contains(id)) { |
| | | list.add(id); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } catch (Exception ex) { |
| | | ex.printStackTrace(); |
| | | } |
| | | return list; |
| | | } |
| | | |
| | | } |