package com.huaxia.imes.service; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.huaxia.comm.domain.imes.MesLine; import com.huaxia.imes.mapper.MesLineMapper; import com.huaxia.imes.pojo.MesLineBO; import com.huaxia.imes.pojo.MesLineVO; import com.ruoyi.common.annotation.DataSource; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.enums.DataSourceType; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.StringUtils; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.Assert; import java.math.BigDecimal; import java.math.RoundingMode; import java.time.*; import java.time.format.DateTimeFormatter; import java.time.format.TextStyle; import java.time.temporal.TemporalAdjusters; import java.util.*; /** * @author zx * @since 2024年10月29日 */ @Service @Transactional(rollbackFor = Exception.class) @Slf4j @AllArgsConstructor @DataSource(DataSourceType.SLAVE) public class MesLineService extends ServiceImpl implements IService { private MesLineMapper mesLineMapper; /** * 分页查询 * * @param bo * @return */ public IPage queryList(MesLineBO bo, int pageNum, int pageSize) { int offset = (pageNum - 1) * pageSize; Map params = new HashMap<>(); params.put("boy", bo); params.put("offset", offset); params.put("pageSize", pageSize); // 获取总记录数 int total = mesLineMapper.countByParams(params); //开始分页查询 List records = mesLineMapper.queryListPage(params); // 创建并返回 Page 对象 return new Page(pageNum, pageSize, total).setRecords(records); } /** * 新增数据 * * @param boy */ public void add(MesLine boy) { //校验数据 this.check(boy); //判断创建时间是否为空 if (boy.getCreateTime() == null) { boy.setCreateTime(new Date()); } else { // 转换为 Instant 进行比较,避免时区问题 Instant createInstant = boy.getCreateTime().toInstant(); Instant nowInstant = Instant.now(); Assert.isTrue(!createInstant.isAfter(nowInstant), "500-创建时间不能大于当前时间"); } //通过产线名称和创建如期去查询产线数据是否存在 LambdaQueryWrapper wr = new LambdaQueryWrapper<>(); wr.eq(MesLine::getLineName, boy.getLineName()); wr.eq(MesLine::getCreateTime, boy.getCreateTime()); //序列化时间格式 年月日 String format = boy.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate().toString(); long aLong = this.count(wr); Assert.isTrue(aLong == 0, String.format("500-产线%s-%s已存在", boy.getLineName(), format)); //获取登录人信息 boy.setCreateBy(SecurityUtils.getUsername()); this.save(boy); } /** * 修改数据 * * @param boy */ public void edit(MesLine boy) { //检验数据 this.check(boy); //判断一下时间 Assert.isTrue(boy.getCreateTime() != null, "500-时间不能为空"); // 转换为 Instant 进行比较,避免时区问题 Instant createInstant = boy.getCreateTime().toInstant(); Instant nowInstant = Instant.now(); Assert.isTrue(!createInstant.isAfter(nowInstant), "500-生产时间不能大于当前时间"); boy.setUpdateTime(new Date()) .setUpdateBy(SecurityUtils.getUsername()); this.updateById(boy); } /** * 新增数据时校验数据 * * @param boy */ private void check(MesLine boy) { Assert.isTrue(StringUtils.isNotBlank(boy.getLineName()), "500-产线名称不能为空"); Assert.isTrue(boy.getCurrentQty() != null && BigDecimal.valueOf(boy.getCurrentQty()).compareTo(BigDecimal.ZERO) > 0, "500-当日产量必须大于0"); } /** * 删除数据 * * @param ids */ public void delete(Long[] ids) { //遍历id匹配数据 for (Long id : ids) { MesLine mesLine = mesLineMapper.selectById(id); Assert.isTrue(mesLine != null, "500-数据不存在"); mesLineMapper.deleteById(id); } } /** * 按天来统计数据 * * @return */ public R>>> countDay() { //获取当前时间 LocalDate now = LocalDate.now(); // 计算本周的星期一 LocalDate mondayOfWeek = now.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)); // 计算本周的星期天 LocalDate sundayOfWeek = now.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY)); //获取星期一致星期天的数据 LambdaQueryWrapper wr = new LambdaQueryWrapper<>(); wr.between(MesLine::getCreateTime, mondayOfWeek, sundayOfWeek); List boy = mesLineMapper.selectList(wr); //格式 key:产线名称 value:星期几 key:产量 value:数量 Map>> newMap = new LinkedHashMap<>(); // 初始化Map中的键,并设置默认值为0 for (DayOfWeek dayOfWeek : DayOfWeek.values()) { String dayOfWeekName = dayOfWeek.getDisplayName(TextStyle.FULL, Locale.CHINA); if (boy != null && !boy.isEmpty()) { for (MesLine mesLine : boy) { String lineName = mesLine.getLineName(); if (StringUtils.isBlank(lineName)) { continue; } Map> dayMap = newMap.computeIfAbsent(lineName, k -> new LinkedHashMap<>()); Map statsMap = dayMap.computeIfAbsent(dayOfWeekName, k -> new HashMap() {{ put("产量", 0L); }}); } } } //遍历集合 if (boy != null && !boy.isEmpty()) { for (MesLine mesLine : boy) { // 获取星期几 LocalDate date = mesLine.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); String week = date.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.CHINA); Long count = mesLine.getCurrentQty(); // 获取产量 String lineName = mesLine.getLineName(); // 获取产线名称 if (StringUtils.isBlank(lineName)) { continue; } //获取内层 Map> dayMap = newMap.get(lineName); Map statsMap = dayMap.get(week); // 更新内层Map中的产量 Long totalOutPut = (Long) statsMap.getOrDefault("产量", 0L); totalOutPut += count; statsMap.put("产量", totalOutPut); } } return R.ok(newMap); } /** * 统计本周 每条产线数据 * * @return */ public R>> queryDay() { //获取当前时间 LocalDate now = LocalDate.now(); //计算本周的星期一 LocalDate mondayOfWeek = now.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)); // 计算本周的星期天 LocalDate sundayOfWeek = now.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY)); //获取星期一致星期天的数据 LambdaQueryWrapper wr = new LambdaQueryWrapper<>(); wr.between(MesLine::getCreateTime, mondayOfWeek, sundayOfWeek); List boy = mesLineMapper.selectList(wr); // 创建一个LinkedHashMap用于存储统计结果 Map> lineSummary = new LinkedHashMap<>(); // 遍历集合,统计每条产线的数据 if (boy != null && !boy.isEmpty()) { for (MesLine mesLine : boy) { try { //获取产线名称 String lineName = mesLine.getLineName(); LocalDate createTime = mesLine.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); if (createTime.isAfter(mondayOfWeek.minusDays(1)) && createTime.isBefore(sundayOfWeek.plusDays(1))) { Map lineData = lineSummary.computeIfAbsent(lineName, k -> new HashMap<>()); //累加产量 Long totalOutput = (Long) lineData.getOrDefault("产量", 0L); Long count = mesLine.getCurrentQty();//产量=产量(包含合格数量)+不合格数量 Long poorQty = mesLine.getPoorQty();//不合格数量 totalOutput += (count + poorQty); lineData.put("产量", totalOutput); //累加不合格数量 Long totalPoorQty = (Long) lineData.getOrDefault("不合格数量", 0L); Long currentPoorQty = mesLine.getPoorQty(); totalPoorQty += currentPoorQty; lineData.put("不合格数量", totalPoorQty); //计算合格数量 Long totalQualifiedQty = (Long) lineData.getOrDefault("合格数量", 0L); totalQualifiedQty += count; lineData.put("合格数量", totalQualifiedQty); //更新合格率 if (totalOutput > 0) { double qualificationRate = ((double) totalQualifiedQty / (double) totalOutput) * 100; lineData.put("合格率", String.format("%.2f%%", qualificationRate)); } else { lineData.put("合格率", "0.00%"); } } } catch (Exception e) { log.warn("数据转换异常", e); } } } return R.ok(lineSummary); } /** * 获取本月总产量 * * @return */ public R> getMonthTotal() { //获取当前时间 LocalDate now = LocalDate.now(); //获取本月的开始时间和结束时间 LocalDate startOfMonth = now.withDayOfMonth(1); LocalDate endOfMonth = now.withDayOfMonth(now.lengthOfMonth()); //按月份查询数据 LambdaQueryWrapper wr = new LambdaQueryWrapper<>(); wr.between(MesLine::getCreateTime, startOfMonth, endOfMonth); List list = mesLineMapper.selectList(wr); // 开始累加本月各产线总产量 Map totalByLine = new HashMap<>(); if (list != null && !list.isEmpty()) { for (MesLine mesLine : list) { String lineName = mesLine.getLineName(); Long currentQty = mesLine.getCurrentQty(); if (totalByLine.containsKey(lineName)) { totalByLine.put(lineName, totalByLine.get(lineName) + currentQty); } else { totalByLine.put(lineName, currentQty); } } } return R.ok(totalByLine); } /** * 获取合格率 星期1-7 * * @return */ public R< Map>>> getPassRate() { //获取当前日期 LocalDate now = LocalDate.now(); //计算本周的星期一 LocalDate mondayOfWeek = now.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)); // 计算本周的星期天 LocalDate sundayOfWeek = now.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY)); //获取星期一致星期天的数据 LambdaQueryWrapper wr = new LambdaQueryWrapper<>(); wr.between(MesLine::getCreateTime, mondayOfWeek, sundayOfWeek); List boy = mesLineMapper.selectList(wr); //存储的数据格式 key:产线名称 value:星期几 key:产量,value:数量 Map>> map = new LinkedHashMap<>(); //初始化每周的数据 for (DayOfWeek dayOfWeek : DayOfWeek.values()) { String dayOfWeekName = dayOfWeek.getDisplayName(TextStyle.FULL, Locale.CHINA); if (boy != null && !boy.isEmpty()) { for (MesLine mesLine : boy) { //获取产线名称 String lineName = mesLine.getLineName(); if (StringUtils.isBlank(lineName)) { continue; } Map> dayMap = map.computeIfAbsent(lineName, k -> new LinkedHashMap<>()); dayMap.putIfAbsent(dayOfWeekName, new HashMap() {{ put("产量", 0L); put("不合格数量", 0L); put("合格数量", 0L); put("合格率", "0.00%"); }}); } } } // 遍历集合,统计每条产线的数据 if (boy != null && !boy.isEmpty()) { for (MesLine mesLine : boy) { // 获取创建日期 LocalDate createTime = mesLine.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); if (createTime.isAfter(mondayOfWeek.minusDays(1)) && createTime.isBefore(sundayOfWeek.plusDays(1))) { DayOfWeek dayOfWeek = createTime.getDayOfWeek(); String dayOfWeekName = dayOfWeek.getDisplayName(TextStyle.FULL, Locale.CHINA); String lineName = mesLine.getLineName(); if (StringUtils.isBlank(lineName)) { continue; } Map> dayMap = map.get(lineName); Map stats = dayMap.get(dayOfWeekName); // 累加总产量 Long totalOutput = (Long) stats.getOrDefault("产量", 0L); Long count = mesLine.getCurrentQty();//产量+不合格数 Long poorQty = mesLine.getPoorQty();//不合格数量 totalOutput += (count + poorQty); stats.put("产量", totalOutput); // 累加不合格数量 Long totalPoorQty = (Long) stats.getOrDefault("不合格数量", 0L); totalPoorQty += mesLine.getPoorQty(); stats.put("不合格数量", totalPoorQty); //计算合格数量 Long totalQualifiedQty = (Long) stats.getOrDefault("合格数量", 0L); totalQualifiedQty += count; stats.put("合格数量", totalQualifiedQty); // 更新合格率 if (totalOutput > 0) { double qualificationRate = ((double) totalQualifiedQty / (double) totalOutput) * 100; stats.put("合格率", String.format(Locale.US, "%.2f%%", qualificationRate)); } else { stats.put("合格率", "0.00%"); } } } } return R.ok(map); } /** * 获取人均产出(按月) * * @return */ public R>>> getWorkerQty() { //获取当前系统时间 LocalDate now = LocalDate.now(); //计算当月的第一天 LocalDate firstDayOfMonth = now.withDayOfMonth(1); //计算当月的最后一天 LocalDate lastDayOfMonth = now.withDayOfMonth(now.lengthOfMonth()); //获取当月的数据 LambdaQueryWrapper wr = new LambdaQueryWrapper<>(); wr.between(MesLine::getCreateTime, firstDayOfMonth, lastDayOfMonth); List boy = mesLineMapper.selectList(wr); //创建Map 用于存储统计结果 日期:产线 每日产量 每日工作人数 人均产出 Map>> weekMap = new LinkedHashMap<>(); //初始化 每月1号到当前时间 LocalDate currentDate = firstDayOfMonth; while (currentDate.isBefore(now.plusDays(1))) { String dateString = currentDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); if (boy != null && !boy.isEmpty()) { for (MesLine mesLine : boy) { String lineName = mesLine.getLineName(); Map> dayStats = weekMap.computeIfAbsent(lineName, k -> new TreeMap<>(Comparator.naturalOrder())); dayStats.putIfAbsent(dateString, new HashMap() {{ put("产量", 0L); put("每日工作人数", 0); put("人均产出", BigDecimal.ZERO); }}); } currentDate = currentDate.plusDays(1); } } //遍历集合 获取某条线产量 if (boy != null && !boy.isEmpty()) { for (MesLine mesLine : boy) { //获取产线名称 String lineName = mesLine.getLineName(); // 获取创建日期 LocalDate createTime = mesLine.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); //序列化日期格式 年月日 String dateString = createTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); //初始化数据 Map> dayStats = weekMap.get(lineName); Map lineStats = dayStats.get(dateString); //累加产量 Long totalOutPut = (Long) lineStats.getOrDefault("产量", 0L); Long count = mesLine.getCurrentQty();//产量 totalOutPut += count;//产量 lineStats.put("产量", totalOutPut); //累加每条线的投产人员 Integer workerQty = (Integer) lineStats.getOrDefault("每日工作人数", 0); workerQty += mesLine.getWorkerQty(); lineStats.put("每日工作人数", workerQty); } // 计算每个产线每天人均产出 for (Map.Entry>> entry : weekMap.entrySet()) { String lineName = entry.getKey(); for (Map.Entry> lineEntry : entry.getValue().entrySet()) { String dateString = lineEntry.getKey(); Long totalOutput = (Long) lineEntry.getValue().get("产量"); Integer workerQty = (Integer) lineEntry.getValue().get("每日工作人数"); //计算平均人均产出 if (workerQty > 0) { BigDecimal averageOutputPerPerson = BigDecimal.valueOf(totalOutput).divide(BigDecimal.valueOf(workerQty), 0, RoundingMode.HALF_UP); lineEntry.getValue().put("人均产出", averageOutputPerPerson); } else { lineEntry.getValue().put("人均产出", BigDecimal.ZERO); } } } } return R.ok(weekMap); } }