Selaa lähdekoodia

解决库存日统计

wukai 1 kuukausi sitten
vanhempi
commit
daa0c1bf33
25 muutettua tiedostoa jossa 1697 lisäystä ja 122 poistoa
  1. 2 2
      jjt-admin/src/test/java/com/jjt/inventory/BpOutTest.java
  2. 8 0
      jjt-admin/src/test/java/com/jjt/inventory/InventoryTest.java
  3. 4 0
      jjt-biz/src/main/java/com/jjt/calc/mapper/TwinCalcDayYhjMapper.java
  4. 253 94
      jjt-biz/src/main/java/com/jjt/inventory/controller/InventoryController.java
  5. 113 0
      jjt-biz/src/main/java/com/jjt/inventory/controller/TwinCalcDayBpController.java
  6. 113 0
      jjt-biz/src/main/java/com/jjt/inventory/controller/TwinCalcDayPtController.java
  7. 131 0
      jjt-biz/src/main/java/com/jjt/inventory/domain/TwinCalcDayBp.java
  8. 62 0
      jjt-biz/src/main/java/com/jjt/inventory/domain/TwinCalcDayPt.java
  9. 69 0
      jjt-biz/src/main/java/com/jjt/inventory/mapper/TwinCalcDayBpMapper.java
  10. 68 0
      jjt-biz/src/main/java/com/jjt/inventory/mapper/TwinCalcDayPtMapper.java
  11. 22 10
      jjt-biz/src/main/java/com/jjt/inventory/mapper/TwinCalcHourBpMapper.java
  12. 76 0
      jjt-biz/src/main/java/com/jjt/inventory/service/ITwinCalcDayBpService.java
  13. 77 0
      jjt-biz/src/main/java/com/jjt/inventory/service/ITwinCalcDayPtService.java
  14. 13 0
      jjt-biz/src/main/java/com/jjt/inventory/service/ITwinCalcHourBpService.java
  15. 10 0
      jjt-biz/src/main/java/com/jjt/inventory/service/ITwinCalcHourPtService.java
  16. 124 7
      jjt-biz/src/main/java/com/jjt/inventory/service/impl/InventoryServiceImpl.java
  17. 114 0
      jjt-biz/src/main/java/com/jjt/inventory/service/impl/TwinCalcDayBpServiceImpl.java
  18. 116 0
      jjt-biz/src/main/java/com/jjt/inventory/service/impl/TwinCalcDayPtServiceImpl.java
  19. 16 0
      jjt-biz/src/main/java/com/jjt/inventory/service/impl/TwinCalcHourBpServiceImpl.java
  20. 16 0
      jjt-biz/src/main/java/com/jjt/inventory/service/impl/TwinCalcHourPtServiceImpl.java
  21. 18 9
      jjt-biz/src/main/java/com/jjt/inventory/vo/BpVO.java
  22. 153 0
      jjt-biz/src/main/resources/mapper/inventory/TwinCalcDayBpMapper.xml
  23. 105 0
      jjt-biz/src/main/resources/mapper/inventory/TwinCalcDayPtMapper.xml
  24. 11 0
      jjt-biz/src/main/resources/mapper/inventory/TwinCalcHourBpMapper.xml
  25. 3 0
      jjt-biz/src/main/resources/mapper/inventory/TwinCalcHourPtMapper.xml

+ 2 - 2
jjt-admin/src/test/java/com/jjt/inventory/BpOutTest.java

@@ -21,11 +21,11 @@ public class BpOutTest {
 
     @Test
     public void hour() {
-        String st = "2025-06-01";
+        String st = "2025-06-11";
         String ed = "2025-06-12";
         LocalDate localDate = LocalDate.parse(st);
         LocalDate endDate = LocalDate.parse(ed);
-        LocalDateTime start = LocalDateTime.of(localDate, LocalTime.MIN).plusHours(13);
+        LocalDateTime start = LocalDateTime.of(localDate, LocalTime.MIN).plusHours(15);
 //        hourRzService.hour(start, start.plusHours(1));
         LocalDateTime end = LocalDateTime.of(endDate.plusDays(1), LocalTime.MIN).plusHours(6);
         LocalDateTime curr = LocalDateTime.now();

+ 8 - 0
jjt-admin/src/test/java/com/jjt/inventory/InventoryTest.java

@@ -7,6 +7,7 @@ import org.springframework.boot.test.context.SpringBootTest;
 
 import javax.annotation.Resource;
 import java.math.BigDecimal;
+import java.time.LocalDate;
 
 /**
  * 印花机
@@ -21,6 +22,13 @@ public class InventoryTest {
         inventoryService.hour();
     }
 
+    @Test
+    public void day() {
+        String date = "2025-06-12";
+        LocalDate localDate = LocalDate.parse(date);
+        inventoryService.day(localDate);
+    }
+
     public static void main(String[] args) {
         String v = "299.000";
         System.out.println(new BigDecimal(v).intValue());

+ 4 - 0
jjt-biz/src/main/java/com/jjt/calc/mapper/TwinCalcDayYhjMapper.java

@@ -60,5 +60,9 @@ public interface TwinCalcDayYhjMapper extends BaseMapper<TwinCalcDayYhj> {
      */
     public int deleteTwinCalcDayYhjByIds(Long[] ids);
 
+    /**
+     * 根据时间删除
+     * @param date  日期
+     */
     void delete4date(String date);
 }

+ 253 - 94
jjt-biz/src/main/java/com/jjt/inventory/controller/InventoryController.java

@@ -3,11 +3,12 @@ package com.jjt.inventory.controller;
 import com.jjt.common.core.controller.BaseController;
 import com.jjt.common.core.domain.R;
 import com.jjt.common.core.redis.RedisCache;
+import com.jjt.common.utils.DateUtils;
+import com.jjt.inventory.domain.TwinCalcDayBp;
+import com.jjt.inventory.domain.TwinCalcDayPt;
 import com.jjt.inventory.domain.TwinCalcHourBp;
 import com.jjt.inventory.domain.TwinCalcHourPt;
-import com.jjt.inventory.service.IInventoryService;
-import com.jjt.inventory.service.ITwinCalcHourBpService;
-import com.jjt.inventory.service.ITwinCalcHourPtService;
+import com.jjt.inventory.service.*;
 import com.jjt.inventory.vo.BpVO;
 import com.jjt.inventory.vo.PtVO;
 import com.jjt.inventory.vo.TopVO;
@@ -23,10 +24,8 @@ import java.math.RoundingMode;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.temporal.ChronoUnit;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
+import java.util.function.IntFunction;
 import java.util.stream.Collectors;
 
 /**
@@ -44,9 +43,13 @@ public class InventoryController extends BaseController {
     @Resource
     private MssqlService mssqlService;
     @Resource
-    private ITwinCalcHourBpService bpService;
+    private ITwinCalcHourBpService hourBpService;
     @Resource
-    private ITwinCalcHourPtService ptService;
+    private ITwinCalcHourPtService hourPtService;
+    @Resource
+    private ITwinCalcDayPtService dayPtService;
+    @Resource
+    private ITwinCalcDayBpService dayBpService;
 
 
     @ApiOperation("盘头库库存分析")
@@ -55,42 +58,34 @@ public class InventoryController extends BaseController {
     @ResponseBody
     public R<PtVO> pt() {
         PtVO ptVO = new PtVO();
+        //当前库统计
         String sql = "SELECT TOP 10 SKU,SKU_DESCRC,LOT01 FROM V_WMS_STOCK WHERE WAREHOUSE_ID='WH03-盘头仓库' AND UOM='个' AND LOT01 IS NOT NULL AND LOT01!='' ORDER BY LOT01";
         List<TopVO> tops = topProcess(sql);
         ptVO.setTops(tops);
-
-        // 模拟30天的使用情况数据
-        for (int day = 0; day < 30; day++) {
-            PtVO.Usage usage = new PtVO.Usage();
-            usage.setMax(1500 + day * 10);
-            // 每天最大使用量增加10
-            usage.setRate(BigDecimal.valueOf(0.7 + day * 0.005).setScale(2, RoundingMode.HALF_UP));
-            // 使用率每天递增0.5%
-            usage.setDate(LocalDate.now().minusDays(29 - day));
-            // 从30天前到今天
-
-            int yarnCount = 3 + (int) (Math.random() * 8);
-            // 随机3-10个纱种
-            int totalNum = 0;
-            for (int i = 1; i <= yarnCount; i++) {
-                PtVO.YarnTypeDetail detail = new PtVO.YarnTypeDetail();
-                detail.setName("纱种" + i);
-                detail.setNum(50 + (int) (Math.random() * 100));
-                // 随机50-150的数量
-                totalNum += detail.getNum();
-                usage.getDetails().add(detail);
-            }
-            // 计算比例
-            for (PtVO.YarnTypeDetail detail : usage.getDetails()) {
-                BigDecimal ratio = new BigDecimal(detail.getNum()).divide(new BigDecimal(totalNum), 2, RoundingMode.HALF_UP);
-                detail.setRatio(ratio);
-            }
-            ptVO.getUsages().add(usage);
-        }
-
+        //30天统计
+        List<TwinCalcDayPt> calcDayList = dayPtService.selectStartDate(LocalDateTime.now().minusHours(7).minusDays(30).toLocalDate());
+        calcDayList = calcDayList.stream().sorted(Comparator.comparing(TwinCalcDayPt::getTime)).collect(Collectors.toList());
+        calcDayList.stream()
+                .map(day -> {
+                    PtVO.Usage usage = new PtVO.Usage();
+                    usage.setMax(day.getMaxNum());
+                    usage.setRate(day.getRate());
+                    usage.setDate(DateUtils.toLocalDate(day.getTime()));
+                    Integer hour = Integer.parseInt(day.getData());
+                    List<TwinCalcHourPt> hourPtList = hourPtService.selectTwinCalcHourPtByHour(day.getTime(), hour);
+                    hourPtList.stream().filter(item -> item.getNum() > 0).sorted(Comparator.comparing(TwinCalcHourPt::getNum).reversed()).forEach(hourPt -> {
+                        PtVO.YarnTypeDetail detail = new PtVO.YarnTypeDetail();
+                        detail.setName(hourPt.getName());
+                        detail.setNum(hourPt.getNum());
+                        BigDecimal ratio = new BigDecimal(hourPt.getNum()).divide(new BigDecimal(day.getMaxNum()), 4, RoundingMode.HALF_UP);
+                        detail.setRatio(ratio);
+                        usage.getDetails().add(detail);
+                    });
+                    return usage;
+                }).forEach(ptVO.getUsages()::add);
+        //当日统计
         Map<String, PtVO.Stock> stats = new HashMap<>(16);
-        List<TwinCalcHourPt> hourPtList = ptService.selectTwinCalcHourPtByDay(LocalDateTime.now().minusHours(7).toLocalDate());
-
+        List<TwinCalcHourPt> hourPtList = hourPtService.selectTwinCalcHourPtByDay(LocalDateTime.now().minusHours(7).toLocalDate());
         hourPtList.forEach(pt -> {
             PtVO.Stock stock = stats.computeIfAbsent(pt.getName(), k -> new PtVO.Stock());
             stock.setName(pt.getName());
@@ -114,70 +109,229 @@ public class InventoryController extends BaseController {
     @ResponseBody
     public R<BpVO> bp() {
         BpVO bpVO = new BpVO();
+        //当前库统计
         String sql = "SELECT TOP 10 SKU,SKU_DESCRC,LOT01 FROM V_WMS_STOCK WHERE  WAREHOUSE_ID='WH04-白坯仓库' AND UOM='KG' AND LOT01 IS NOT NULL AND LOT01!='' ORDER BY LOT01";
         List<TopVO> tops = topProcess(sql);
         bpVO.setTops(tops);
+        //30天统计
+        List<TwinCalcDayBp> calcDayList = dayBpService.selectStartDate(LocalDateTime.now().minusHours(7).minusDays(30).toLocalDate());
+        calcDayList.stream().sorted(Comparator.comparing(TwinCalcDayBp::getTime)).forEach(day -> {
+            Integer rollMaxHour = Integer.parseInt(day.getRollData().split(",")[0]);
+            Integer rollMinHour = Integer.parseInt(day.getRollData().split(",")[1]);
+            Integer meterMaxHour = Integer.parseInt(day.getMeterData().split(",")[0]);
+            Integer meterMinHour = Integer.parseInt(day.getMeterData().split(",")[1]);
+            Integer weightMaxHour = Integer.parseInt(day.getWeightData().split(",")[0]);
+            Integer weightMinHour = Integer.parseInt(day.getWeightData().split(",")[1]);
+            int[] hours = Arrays.stream(new int[]{rollMaxHour, rollMinHour, meterMaxHour, meterMinHour, weightMaxHour, weightMinHour}).distinct().toArray();
+            Map<Integer, List<TwinCalcHourBp>> hourMap = hourBpService.selectTwinCalcHourBpByHours(day.getTime(), hours);
+            IntFunction<BpVO.YarnTypeDetail> createDetail = mick -> {
+                BpVO.YarnTypeDetail detail = new BpVO.YarnTypeDetail();
+                detail.setName("米克重(" + mick + ")");
+                return detail;
+            };
 
-        // 模拟近一月库存情况 - 卷数、米数、重量三种类型
-        for (int i = 0; i < 30; i++) {
             // 米数库存
             BpVO.MonthStock meterStock = new BpVO.MonthStock();
-            meterStock.setMax(800 + (int) (Math.random() * 400));
-            // 800-1200米
-            meterStock.setMin(300 + (int) (Math.random() * 300));
-            // 300-600米
-            meterStock.setAvg(new BigDecimal((meterStock.getMax() + meterStock.getMin()) / 2.0).setScale(2, RoundingMode.HALF_UP));
-            meterStock.setDate(LocalDate.now().minusDays(29 - i));
+            meterStock.setMax(day.getMeterMax());
+            meterStock.setMin(day.getMeterMin());
+            meterStock.setAvg(day.getMeterAvg());
+            meterStock.setDate(DateUtils.toLocalDate(day.getTime()));
+
+            hourMap.get(meterMaxHour).stream()
+                    .filter(item -> item.getMeterNum() > 0)
+                    .sorted(Comparator.comparing(TwinCalcHourBp::getMeterNum).reversed())
+                    .collect(Collectors.groupingBy(TwinCalcHourBp::getMick))
+                    .forEach((mick, list) -> {
+                        int meterNum = list.stream().mapToInt(TwinCalcHourBp::getMeterNum).sum();
+                        BpVO.YarnTypeDetail detail = createDetail.apply(mick);
+                        detail.setNum(meterNum);
+                        detail.setRatio(new BigDecimal(meterNum).divide(new BigDecimal(day.getMeterMax()), 4, RoundingMode.HALF_UP));
+                        meterStock.getDetails().add(detail);
+                    });
+
+            hourMap.get(meterMinHour).stream()
+                    .filter(item -> item.getMeterNum() > 0)
+                    .collect(Collectors.groupingBy(TwinCalcHourBp::getMick))
+                    .forEach((mick, list) -> {
+                        int meterNum = list.stream().mapToInt(TwinCalcHourBp::getMeterNum).sum();
+                        BpVO.YarnTypeDetail detail = createDetail.apply(mick);
+                        detail.setNum(meterNum);
+                        detail.setRatio(new BigDecimal(meterNum).divide(new BigDecimal(day.getMeterMin()), 4, RoundingMode.HALF_UP));
+                        meterStock.getMinDetails().add(detail);
+                    });
+            meterStock.getDetails().sort(Comparator.comparing(BpVO.YarnTypeDetail::getNum).reversed());
+            meterStock.getMinDetails().sort(Comparator.comparing(BpVO.YarnTypeDetail::getNum).reversed());
             bpVO.getMeterMonthStocks().add(meterStock);
 
             // 重量库存
             BpVO.MonthStock weightStock = new BpVO.MonthStock();
-            weightStock.setMax(500 + (int) (Math.random() * 300));
-            // 500-800公斤
-            weightStock.setMin(200 + (int) (Math.random() * 200));
-            // 200-400公斤
-            weightStock.setAvg(new BigDecimal((weightStock.getMax() + weightStock.getMin()) / 2.0).setScale(2, RoundingMode.HALF_UP));
-            weightStock.setDate(LocalDate.now().minusDays(29 - i));
+            weightStock.setMax(day.getWeightMax());
+            weightStock.setMin(day.getWeightMin());
+            weightStock.setAvg(day.getWeightAvg());
+            weightStock.setDate(DateUtils.toLocalDate(day.getTime()));
+            hourMap.get(weightMaxHour).stream()
+                    .filter(item -> item.getWeightNum() > 0)
+                    .collect(Collectors.groupingBy(TwinCalcHourBp::getMick))
+                    .forEach((mick, list) -> {
+                        int weightNum = list.stream().mapToInt(TwinCalcHourBp::getWeightNum).sum();
+                        BpVO.YarnTypeDetail detail = createDetail.apply(mick);
+                        detail.setNum(weightNum);
+                        detail.setRatio(new BigDecimal(weightNum).divide(new BigDecimal(day.getWeightMax()), 4, RoundingMode.HALF_UP));
+                        weightStock.getDetails().add(detail);
+                    });
+
+            hourMap.get(weightMinHour).stream()
+                    .filter(item -> item.getWeightNum() > 0)
+                    .collect(Collectors.groupingBy(TwinCalcHourBp::getMick))
+                    .forEach((mick, list) -> {
+                        int weightNum = list.stream().mapToInt(TwinCalcHourBp::getWeightNum).sum();
+                        BpVO.YarnTypeDetail detail = createDetail.apply(mick);
+                        detail.setNum(weightNum);
+                        detail.setRatio(new BigDecimal(weightNum).divide(new BigDecimal(day.getWeightMin()), 4, RoundingMode.HALF_UP));
+                        weightStock.getMinDetails().add(detail);
+                    });
+            weightStock.getDetails().sort(Comparator.comparing(BpVO.YarnTypeDetail::getNum).reversed());
+            weightStock.getMinDetails().sort(Comparator.comparing(BpVO.YarnTypeDetail::getNum).reversed());
             bpVO.getWeightMonthStocks().add(weightStock);
 
             // 卷数库存
             BpVO.MonthStock rollStock = new BpVO.MonthStock();
-            rollStock.setMax(150 + (int) (Math.random() * 100));
-            // 150-250卷
-            rollStock.setMin(50 + (int) (Math.random() * 80));
-            // 50-130卷
-            rollStock.setAvg(new BigDecimal((rollStock.getMax() + rollStock.getMin()) / 2.0).setScale(2, RoundingMode.HALF_UP));
-            rollStock.setDate(LocalDate.now().minusDays(29 - i));
+            rollStock.setMax(day.getRollMax());
+            rollStock.setMin(day.getRollMin());
+            rollStock.setAvg(day.getRollAvg());
+            rollStock.setDate(DateUtils.toLocalDate(day.getTime()));
+
+            hourMap.get(rollMaxHour).stream()
+                    .filter(item -> item.getRollNum() > 0)
+                    .sorted(Comparator.comparing(TwinCalcHourBp::getRollNum).reversed())
+                    .collect(Collectors.groupingBy(TwinCalcHourBp::getMick))
+                    .forEach((mick, list) -> {
+                        int rollNum = list.stream().mapToInt(TwinCalcHourBp::getRollNum).sum();
+                        BpVO.YarnTypeDetail detail = createDetail.apply(mick);
+                        detail.setNum(rollNum);
+                        detail.setRatio(new BigDecimal(rollNum).divide(new BigDecimal(day.getRollMax()), 4, RoundingMode.HALF_UP));
+                        rollStock.getDetails().add(detail);
+                    });
+            hourMap.get(rollMinHour).stream()
+                    .filter(item -> item.getRollNum() > 0)
+                    .sorted(Comparator.comparing(TwinCalcHourBp::getRollNum).reversed())
+                    .collect(Collectors.groupingBy(TwinCalcHourBp::getMick))
+                    .forEach((mick, list) -> {
+                        int rollNum = list.stream().mapToInt(TwinCalcHourBp::getRollNum).sum();
+                        BpVO.YarnTypeDetail detail = createDetail.apply(mick);
+                        detail.setNum(rollNum);
+                        detail.setRatio(new BigDecimal(rollNum).divide(new BigDecimal(day.getRollMin()), 4, RoundingMode.HALF_UP));
+                        rollStock.getMinDetails().add(detail);
+                    });
+            rollStock.getDetails().sort(Comparator.comparing(BpVO.YarnTypeDetail::getNum).reversed());
+            rollStock.getMinDetails().sort(Comparator.comparing(BpVO.YarnTypeDetail::getNum).reversed());
             bpVO.getRollMonthStocks().add(rollStock);
-            for (BpVO.MonthStock stock : new BpVO.MonthStock[]{meterStock, weightStock, rollStock}) {
-                int totalNum = 0;
-                int yarnCount = 3 + (int) (Math.random() * 8);
-                // 随机3-10个纱种
-                List<BpVO.YarnTypeDetail> details = new java.util.ArrayList<>();
 
-                // 先设置数量并计算总数
-                for (int j = 1; j <= yarnCount; j++) {
-                    BpVO.YarnTypeDetail detail = new BpVO.YarnTypeDetail();
-                    detail.setName("纱种" + j);
-                    detail.setNum(50 + (int) (Math.random() * 100));
-                    // 随机50-150的数量
-                    totalNum += detail.getNum();
-                    details.add(detail);
-                }
 
-                // 根据数量计算比例
-                for (BpVO.YarnTypeDetail detail : details) {
-                    BigDecimal ratio = new BigDecimal(detail.getNum()).divide(new BigDecimal(totalNum), 2, RoundingMode.HALF_UP);
-                    detail.setRatio(ratio);
-                    stock.getDetails().add(detail);
-                }
-            }
-        }
-        Map<String, BpVO.Stock[]> stats = new HashMap<>(16);
-        List<TwinCalcHourBp> hourBpList = bpService.selectTwinCalcHourPtByDay(LocalDateTime.now().minusHours(7).toLocalDate());
+//            for (BpVO.MonthStock stock : new BpVO.MonthStock[]{meterStock, weightStock, rollStock}) {
+//                int totalNum = 0;
+//                int yarnCount = 3 + (int) (Math.random() * 8);
+//                // 随机3-10个纱种
+//                List<BpVO.YarnTypeDetail> details = new java.util.ArrayList<>();
+//
+//                // 先设置数量并计算总数
+//                for (int j = 1; j <= yarnCount; j++) {
+//                    BpVO.YarnTypeDetail detail = new BpVO.YarnTypeDetail();
+//                    detail.setName("纱种" + j);
+//                    detail.setNum(50 + (int) (Math.random() * 100));
+//                    // 随机50-150的数量
+//                    totalNum += detail.getNum();
+//                    details.add(detail);
+//                }
+//
+//                // 根据数量计算比例
+//                for (BpVO.YarnTypeDetail detail : details) {
+//                    BigDecimal ratio = new BigDecimal(detail.getNum()).divide(new BigDecimal(totalNum), 2, RoundingMode.HALF_UP);
+//                    detail.setRatio(ratio);
+//                    stock.getDetails().add(detail);
+//                }
+//            }
+        });
+//        calcDayList.stream()
+//                .map(day -> {
+//                    BpVO.MonthStock monthStock = new BpVO.MonthStock();
+//                    monthStock.set
+//                    usage.setMax(day.getMaxNum());
+//                    usage.setRate(day.getRate());
+//                    usage.setDate(DateUtils.toLocalDate(day.getTime()));
+//                    Integer hour = Integer.parseInt(day.getData());
+//                    List<TwinCalcHourPt> hourPtList = hourPtService.selectTwinCalcHourPtByHour(day.getTime(), hour);
+//                    hourPtList.stream().filter(item -> item.getNum() > 0).sorted(Comparator.comparing(TwinCalcHourPt::getNum).reversed()).forEach(hourPt -> {
+//                        PtVO.YarnTypeDetail detail = new PtVO.YarnTypeDetail();
+//                        detail.setName(hourPt.getName());
+//                        detail.setNum(hourPt.getNum());
+//                        BigDecimal ratio = new BigDecimal(hourPt.getNum()).divide(new BigDecimal(day.getMaxNum()), 4, RoundingMode.HALF_UP);
+//                        detail.setRatio(ratio);
+//                        usage.getDetails().add(detail);
+//                    });
+//                    return monthStock;
+//                }).forEach(bpVO.getRollMonthStocks()::add);
+        // 模拟近一月库存情况 - 卷数、米数、重量三种类型
+//        for (int i = 0; i < 30; i++) {
+//            // 米数库存
+//            BpVO.MonthStock meterStock = new BpVO.MonthStock();
+//            meterStock.setMax(800 + (int) (Math.random() * 400));
+//            // 800-1200米
+//            meterStock.setMin(300 + (int) (Math.random() * 300));
+//            // 300-600米
+//            meterStock.setAvg(new BigDecimal((meterStock.getMax() + meterStock.getMin()) / 2.0).setScale(2, RoundingMode.HALF_UP));
+//            meterStock.setDate(LocalDate.now().minusDays(29 - i));
+//            bpVO.getMeterMonthStocks().add(meterStock);
+//
+//            // 重量库存
+//            BpVO.MonthStock weightStock = new BpVO.MonthStock();
+//            weightStock.setMax(500 + (int) (Math.random() * 300));
+//            // 500-800公斤
+//            weightStock.setMin(200 + (int) (Math.random() * 200));
+//            // 200-400公斤
+//            weightStock.setAvg(new BigDecimal((weightStock.getMax() + weightStock.getMin()) / 2.0).setScale(2, RoundingMode.HALF_UP));
+//            weightStock.setDate(LocalDate.now().minusDays(29 - i));
+//            bpVO.getWeightMonthStocks().add(weightStock);
+//
+//            // 卷数库存
+//            BpVO.MonthStock rollStock = new BpVO.MonthStock();
+//            rollStock.setMax(150 + (int) (Math.random() * 100));
+//            // 150-250卷
+//            rollStock.setMin(50 + (int) (Math.random() * 80));
+//            // 50-130卷
+//            rollStock.setAvg(new BigDecimal((rollStock.getMax() + rollStock.getMin()) / 2.0).setScale(2, RoundingMode.HALF_UP));
+//            rollStock.setDate(LocalDate.now().minusDays(29 - i));
+//            bpVO.getRollMonthStocks().add(rollStock);
+//            for (BpVO.MonthStock stock : new BpVO.MonthStock[]{meterStock, weightStock, rollStock}) {
+//                int totalNum = 0;
+//                int yarnCount = 3 + (int) (Math.random() * 8);
+//                // 随机3-10个纱种
+//                List<BpVO.YarnTypeDetail> details = new java.util.ArrayList<>();
+//
+//                // 先设置数量并计算总数
+//                for (int j = 1; j <= yarnCount; j++) {
+//                    BpVO.YarnTypeDetail detail = new BpVO.YarnTypeDetail();
+//                    detail.setName("纱种" + j);
+//                    detail.setNum(50 + (int) (Math.random() * 100));
+//                    // 随机50-150的数量
+//                    totalNum += detail.getNum();
+//                    details.add(detail);
+//                }
+//
+//                // 根据数量计算比例
+//                for (BpVO.YarnTypeDetail detail : details) {
+//                    BigDecimal ratio = new BigDecimal(detail.getNum()).divide(new BigDecimal(totalNum), 2, RoundingMode.HALF_UP);
+//                    detail.setRatio(ratio);
+//                    stock.getDetails().add(detail);
+//                }
+//            }
+//        }
 
+        //当日统计,按米克重统计
+        Map<Integer, BpVO.Stock[]> stats = new HashMap<>(16);
+        List<TwinCalcHourBp> hourBpList = hourBpService.selectTwinCalcHourPtByDay(LocalDateTime.now().minusHours(7).toLocalDate());
         hourBpList.forEach(bp -> {
-            BpVO.Stock[] stock = stats.computeIfAbsent(bp.getName(), k -> {
+            BpVO.Stock[] stock = stats.computeIfAbsent(bp.getMick(), k -> {
                 BpVO.Stock[] newStock = new BpVO.Stock[3];
                 newStock[0] = new BpVO.Stock(); // 卷数
                 newStock[1] = new BpVO.Stock(); // 米数
@@ -185,15 +339,15 @@ public class InventoryController extends BaseController {
                 return newStock;
             });
             // 处理卷数统计
-            processStock(stock[0], bp.getName(), bp.getRollIn(), bp.getRollOut(), bp.getRollNum());
+            processStock(stock[0], bp.getMick(), bp.getRollIn(), bp.getRollOut(), bp.getRollNum());
             // 处理米数统计
-            processStock(stock[1], bp.getName(), bp.getMeterIn(), bp.getMeterOut(), bp.getMeterNum());
+            processStock(stock[1], bp.getMick(), bp.getMeterIn(), bp.getMeterOut(), bp.getMeterNum());
             // 处理重量统计
-            processStock(stock[2], bp.getName(), bp.getWeightIn(), bp.getWeightOut(), bp.getWeightNum());
+            processStock(stock[2], bp.getMick(), bp.getWeightIn(), bp.getWeightOut(), bp.getWeightNum());
         });
 
         long hours = hourBpList.stream().map(TwinCalcHourBp::getHour).distinct().count();
-        
+
         // 使用流式处理优化计算和分类
         List<BpVO.Stock> rollStocks = new ArrayList<>();
         List<BpVO.Stock> meterStocks = new ArrayList<>();
@@ -203,11 +357,15 @@ public class InventoryController extends BaseController {
             stockArray[0].calcAvg((int) hours);
             stockArray[1].calcAvg((int) hours);
             stockArray[2].calcAvg((int) hours);
-            
+
             rollStocks.add(stockArray[0]);
             meterStocks.add(stockArray[1]);
             weightStocks.add(stockArray[2]);
         });
+
+        rollStocks.sort(Comparator.comparing(BpVO.Stock::getMick).reversed());
+        meterStocks.sort(Comparator.comparing(BpVO.Stock::getMick).reversed());
+        weightStocks.sort(Comparator.comparing(BpVO.Stock::getMick).reversed());
         bpVO.setRollStocks(rollStocks);
         bpVO.setMeterStocks(meterStocks);
         bpVO.setWeightStocks(weightStocks);
@@ -238,13 +396,14 @@ public class InventoryController extends BaseController {
      * 处理库存数据
      *
      * @param stock 库存数据
-     * @param name  名称
+     * @param mick  米克重
      * @param in    入库数量
      * @param out   出库数量
      * @param num   数量
      */
-    private void processStock(BpVO.Stock stock, String name, Integer in, Integer out, Integer num) {
-        stock.setName(name);
+    private void processStock(BpVO.Stock stock, Integer mick, Integer in, Integer out, Integer num) {
+        stock.setName("米克重(" + mick + ")");
+        stock.setMick(mick);
         stock.addIn(in);
         stock.addOut(out);
         stock.updateMax(num);

+ 113 - 0
jjt-biz/src/main/java/com/jjt/inventory/controller/TwinCalcDayBpController.java

@@ -0,0 +1,113 @@
+package com.jjt.inventory.controller;
+
+import java.util.List;
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jjt.common.annotation.Log;
+import com.jjt.common.core.controller.BaseController;
+import com.jjt.common.core.domain.AjaxResult;
+import com.jjt.common.enums.BusinessType;
+import com.jjt.inventory.domain.TwinCalcDayBp;
+import com.jjt.inventory.service.ITwinCalcDayBpService;
+import com.jjt.common.utils.poi.ExcelUtil;
+import com.jjt.common.core.page.TableDataInfo;
+
+/**
+ * 白坯库日统计数据Controller
+ *
+ * @author wukai
+ * @date 2025-06-13
+ */
+@Api(tags="白坯库日统计数据")
+@RestController
+@RequestMapping("/inventory/bpDay")
+public class TwinCalcDayBpController extends BaseController{
+    @Resource
+    private ITwinCalcDayBpService twinCalcDayBpService;
+
+    /**
+     * 查询白坯库日统计数据列表
+     */
+    @ApiOperation("查询白坯库日统计数据列表")
+    @PreAuthorize("@ss.hasPermi('inventory:bpDay:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(TwinCalcDayBp twinCalcDayBp)
+    {
+        startPage();
+        List<TwinCalcDayBp> list = twinCalcDayBpService.selectTwinCalcDayBpList(twinCalcDayBp);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出白坯库日统计数据列表
+     */
+    @ApiOperation("导出白坯库日统计数据列表")
+    @PreAuthorize("@ss.hasPermi('inventory:bpDay:export')")
+    @Log(title = "白坯库日统计数据", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, TwinCalcDayBp twinCalcDayBp)
+    {
+        List<TwinCalcDayBp> list = twinCalcDayBpService.selectTwinCalcDayBpList(twinCalcDayBp);
+        ExcelUtil<TwinCalcDayBp> util = new ExcelUtil<TwinCalcDayBp>(TwinCalcDayBp.class);
+        util.exportExcel(response, list, "白坯库日统计数据数据");
+    }
+
+    /**
+     * 获取白坯库日统计数据详细信息
+     */
+    @ApiOperation("获取白坯库日统计数据详细信息")
+    @PreAuthorize("@ss.hasPermi('inventory:bpDay:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(twinCalcDayBpService.selectTwinCalcDayBpById(id));
+    }
+
+    /**
+     * 新增白坯库日统计数据
+     */
+    @ApiOperation("新增白坯库日统计数据")
+    @PreAuthorize("@ss.hasPermi('inventory:bpDay:add')")
+    @Log(title = "白坯库日统计数据", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody TwinCalcDayBp twinCalcDayBp)
+    {
+        return toAjax(twinCalcDayBpService.insertTwinCalcDayBp(twinCalcDayBp));
+    }
+
+    /**
+     * 修改白坯库日统计数据
+     */
+    @ApiOperation("修改白坯库日统计数据")
+    @PreAuthorize("@ss.hasPermi('inventory:bpDay:edit')")
+    @Log(title = "白坯库日统计数据", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody TwinCalcDayBp twinCalcDayBp)
+    {
+        return toAjax(twinCalcDayBpService.updateTwinCalcDayBp(twinCalcDayBp));
+    }
+
+    /**
+     * 删除白坯库日统计数据
+     */
+    @ApiOperation("删除白坯库日统计数据")
+    @PreAuthorize("@ss.hasPermi('inventory:bpDay:remove')")
+    @Log(title = "白坯库日统计数据", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(twinCalcDayBpService.deleteTwinCalcDayBpByIds(ids));
+    }
+}

+ 113 - 0
jjt-biz/src/main/java/com/jjt/inventory/controller/TwinCalcDayPtController.java

@@ -0,0 +1,113 @@
+package com.jjt.inventory.controller;
+
+import java.util.List;
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.jjt.common.annotation.Log;
+import com.jjt.common.core.controller.BaseController;
+import com.jjt.common.core.domain.AjaxResult;
+import com.jjt.common.enums.BusinessType;
+import com.jjt.inventory.domain.TwinCalcDayPt;
+import com.jjt.inventory.service.ITwinCalcDayPtService;
+import com.jjt.common.utils.poi.ExcelUtil;
+import com.jjt.common.core.page.TableDataInfo;
+
+/**
+ * 盘头库日统计数据Controller
+ *
+ * @author wukai
+ * @date 2025-06-13
+ */
+@Api(tags="盘头库日统计数据")
+@RestController
+@RequestMapping("/inventory/ptDay")
+public class TwinCalcDayPtController extends BaseController{
+    @Resource
+    private ITwinCalcDayPtService twinCalcDayPtService;
+
+    /**
+     * 查询盘头库日统计数据列表
+     */
+    @ApiOperation("查询盘头库日统计数据列表")
+    @PreAuthorize("@ss.hasPermi('inventory:ptDay:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(TwinCalcDayPt twinCalcDayPt)
+    {
+        startPage();
+        List<TwinCalcDayPt> list = twinCalcDayPtService.selectTwinCalcDayPtList(twinCalcDayPt);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出盘头库日统计数据列表
+     */
+    @ApiOperation("导出盘头库日统计数据列表")
+    @PreAuthorize("@ss.hasPermi('inventory:ptDay:export')")
+    @Log(title = "盘头库日统计数据", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, TwinCalcDayPt twinCalcDayPt)
+    {
+        List<TwinCalcDayPt> list = twinCalcDayPtService.selectTwinCalcDayPtList(twinCalcDayPt);
+        ExcelUtil<TwinCalcDayPt> util = new ExcelUtil<TwinCalcDayPt>(TwinCalcDayPt.class);
+        util.exportExcel(response, list, "盘头库日统计数据数据");
+    }
+
+    /**
+     * 获取盘头库日统计数据详细信息
+     */
+    @ApiOperation("获取盘头库日统计数据详细信息")
+    @PreAuthorize("@ss.hasPermi('inventory:ptDay:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(twinCalcDayPtService.selectTwinCalcDayPtById(id));
+    }
+
+    /**
+     * 新增盘头库日统计数据
+     */
+    @ApiOperation("新增盘头库日统计数据")
+    @PreAuthorize("@ss.hasPermi('inventory:ptDay:add')")
+    @Log(title = "盘头库日统计数据", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody TwinCalcDayPt twinCalcDayPt)
+    {
+        return toAjax(twinCalcDayPtService.insertTwinCalcDayPt(twinCalcDayPt));
+    }
+
+    /**
+     * 修改盘头库日统计数据
+     */
+    @ApiOperation("修改盘头库日统计数据")
+    @PreAuthorize("@ss.hasPermi('inventory:ptDay:edit')")
+    @Log(title = "盘头库日统计数据", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody TwinCalcDayPt twinCalcDayPt)
+    {
+        return toAjax(twinCalcDayPtService.updateTwinCalcDayPt(twinCalcDayPt));
+    }
+
+    /**
+     * 删除盘头库日统计数据
+     */
+    @ApiOperation("删除盘头库日统计数据")
+    @PreAuthorize("@ss.hasPermi('inventory:ptDay:remove')")
+    @Log(title = "盘头库日统计数据", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(twinCalcDayPtService.deleteTwinCalcDayPtByIds(ids));
+    }
+}

+ 131 - 0
jjt-biz/src/main/java/com/jjt/inventory/domain/TwinCalcDayBp.java

@@ -0,0 +1,131 @@
+package com.jjt.inventory.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.jjt.common.annotation.Excel;
+import com.jjt.common.core.domain.BaseEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 白坯库日统计数据对象 TWIN_CALC_DAY_BP
+ *
+ * @author wukai
+ * @date 2025-06-13
+ */
+@ApiModel(value = "TwinCalcDayBp", description = "白坯库日统计数据")
+@Data
+public class TwinCalcDayBp extends BaseEntity {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * ID
+     */
+    @ApiModelProperty("ID")
+    @TableId
+    private Long id;
+
+    /**
+     * 时间
+     */
+    @ApiModelProperty("时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date time;
+
+    /**
+     * 产线编号
+     */
+    @ApiModelProperty("产线编号")
+    @Excel(name = "产线编号")
+    private Integer deviceId;
+
+    /**
+     * 最大库存-卷
+     */
+    @ApiModelProperty("最大库存-卷")
+    @Excel(name = "最大库存-卷")
+    private Integer rollMax;
+
+    /**
+     * 最大库存-米
+     */
+    @ApiModelProperty("最大库存-米")
+    @Excel(name = "最大库存-米")
+    private Integer meterMax;
+
+    /**
+     * 最大库存-重
+     */
+    @ApiModelProperty("最大库存-重")
+    @Excel(name = "最大库存-重")
+    private Integer weightMax;
+
+    /**
+     * 最小库存-卷
+     */
+    @ApiModelProperty("最小库存-卷")
+    @Excel(name = "最小库存-卷")
+    private Integer rollMin;
+
+    /**
+     * 最小库存-米
+     */
+    @ApiModelProperty("最小库存-米")
+    @Excel(name = "最小库存-米")
+    private Integer meterMin;
+
+    /**
+     * 最小库存-重
+     */
+    @ApiModelProperty("最小库存-重")
+    @Excel(name = "最小库存-重")
+    private Integer weightMin;
+
+    /**
+     * 平均库存-卷
+     */
+    @ApiModelProperty("平均库存-卷")
+    @Excel(name = "平均库存-卷")
+    private BigDecimal rollAvg;
+
+    /**
+     * 平均库存-米
+     */
+    @ApiModelProperty("平均库存-米")
+    @Excel(name = "平均库存-米")
+    private BigDecimal meterAvg;
+
+    /**
+     * 平均库存-重
+     */
+    @ApiModelProperty("平均库存-重")
+    @Excel(name = "平均库存-重")
+    private BigDecimal weightAvg;
+
+    /**
+     * 明细数据-卷
+     */
+    @ApiModelProperty("明细数据-卷")
+    @Excel(name = "明细数据-卷")
+    private String rollData;
+
+    /**
+     * 明细数据-米
+     */
+    @ApiModelProperty("明细数据-米")
+    @Excel(name = "明细数据-米")
+    private String meterData;
+
+    /**
+     * 明细数据-重
+     */
+    @ApiModelProperty("明细数据-重")
+    @Excel(name = "明细数据-重")
+    private String weightData;
+
+}

+ 62 - 0
jjt-biz/src/main/java/com/jjt/inventory/domain/TwinCalcDayPt.java

@@ -0,0 +1,62 @@
+package com.jjt.inventory.domain;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.baomidou.mybatisplus.annotation.TableId;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.jjt.common.annotation.Excel;
+import com.jjt.common.core.domain.BaseEntity;
+
+/**
+ * 盘头库日统计数据对象 TWIN_CALC_DAY_PT
+ *
+ * @author wukai
+ * @date 2025-06-13
+ */
+@ApiModel(value = "TwinCalcDayPt", description = "盘头库日统计数据")
+@Data
+public class TwinCalcDayPt extends BaseEntity{
+    private static final long serialVersionUID = 1L;
+
+    /** ID */
+    @ApiModelProperty("ID")
+    @TableId
+    private Long id;
+
+    /** 时间 */
+    @ApiModelProperty("时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @Excel(name = "时间", width = 30, dateFormat = "yyyy-MM-dd")
+    private Date time;
+
+    /** 产线编号 */
+    @ApiModelProperty("产线编号")
+    @Excel(name = "产线编号")
+    private Integer deviceId;
+
+    /** 最大使用量 */
+    @ApiModelProperty("最大使用量")
+    @Excel(name = "最大使用量")
+    private Integer maxNum;
+
+    /** 平均库存 */
+    @ApiModelProperty("平均库存")
+    @Excel(name = "平均库存")
+    private BigDecimal avgNum;
+
+    /** 使用率 */
+    @ApiModelProperty("使用率")
+    @Excel(name = "使用率")
+    private BigDecimal rate;
+
+    /** 明细数据 */
+    @ApiModelProperty("明细数据")
+    @Excel(name = "明细数据")
+    private String data;
+
+}

+ 69 - 0
jjt-biz/src/main/java/com/jjt/inventory/mapper/TwinCalcDayBpMapper.java

@@ -0,0 +1,69 @@
+package com.jjt.inventory.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.jjt.inventory.domain.TwinCalcDayBp;
+
+import java.util.List;
+
+/**
+ * 白坯库日统计数据Mapper接口
+ *
+ * @author wukai
+ * @date 2025-06-13
+ */
+public interface TwinCalcDayBpMapper extends BaseMapper<TwinCalcDayBp> {
+    /**
+     * 查询白坯库日统计数据
+     *
+     * @param id 白坯库日统计数据主键
+     * @return 白坯库日统计数据
+     */
+    public TwinCalcDayBp selectTwinCalcDayBpById(Long id);
+
+    /**
+     * 查询白坯库日统计数据列表
+     *
+     * @param twinCalcDayBp 白坯库日统计数据
+     * @return 白坯库日统计数据集合
+     */
+    public List<TwinCalcDayBp> selectTwinCalcDayBpList(TwinCalcDayBp twinCalcDayBp);
+
+    /**
+     * 新增白坯库日统计数据
+     *
+     * @param twinCalcDayBp 白坯库日统计数据
+     * @return 结果
+     */
+    public int insertTwinCalcDayBp(TwinCalcDayBp twinCalcDayBp);
+
+    /**
+     * 修改白坯库日统计数据
+     *
+     * @param twinCalcDayBp 白坯库日统计数据
+     * @return 结果
+     */
+    public int updateTwinCalcDayBp(TwinCalcDayBp twinCalcDayBp);
+
+    /**
+     * 删除白坯库日统计数据
+     *
+     * @param id 白坯库日统计数据主键
+     * @return 结果
+     */
+    public int deleteTwinCalcDayBpById(Long id);
+
+    /**
+     * 批量删除白坯库日统计数据
+     *
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    public int deleteTwinCalcDayBpByIds(Long[] ids);
+
+    /**
+     * 删除白坯库日统计数据信息
+     *
+     * @param date 白坯库日统计数据主键
+     */
+    void delete4date(String date);
+}

+ 68 - 0
jjt-biz/src/main/java/com/jjt/inventory/mapper/TwinCalcDayPtMapper.java

@@ -0,0 +1,68 @@
+package com.jjt.inventory.mapper;
+
+import java.util.List;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.jjt.inventory.domain.TwinCalcDayPt;
+
+/**
+ * 盘头库日统计数据Mapper接口
+ *
+ * @author wukai
+ * @date 2025-06-13
+ */
+public interface TwinCalcDayPtMapper extends BaseMapper<TwinCalcDayPt>
+{
+    /**
+     * 查询盘头库日统计数据
+     *
+     * @param id 盘头库日统计数据主键
+     * @return 盘头库日统计数据
+     */
+    public TwinCalcDayPt selectTwinCalcDayPtById(Long id);
+
+    /**
+     * 查询盘头库日统计数据列表
+     *
+     * @param twinCalcDayPt 盘头库日统计数据
+     * @return 盘头库日统计数据集合
+     */
+    public List<TwinCalcDayPt> selectTwinCalcDayPtList(TwinCalcDayPt twinCalcDayPt);
+
+    /**
+     * 新增盘头库日统计数据
+     *
+     * @param twinCalcDayPt 盘头库日统计数据
+     * @return 结果
+     */
+    public int insertTwinCalcDayPt(TwinCalcDayPt twinCalcDayPt);
+
+    /**
+     * 修改盘头库日统计数据
+     *
+     * @param twinCalcDayPt 盘头库日统计数据
+     * @return 结果
+     */
+    public int updateTwinCalcDayPt(TwinCalcDayPt twinCalcDayPt);
+
+    /**
+     * 删除盘头库日统计数据
+     *
+     * @param id 盘头库日统计数据主键
+     * @return 结果
+     */
+    public int deleteTwinCalcDayPtById(Long id);
+
+    /**
+     * 批量删除盘头库日统计数据
+     *
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    public int deleteTwinCalcDayPtByIds(Long[] ids);
+    /**
+     * 删除白坯库日统计数据信息
+     *
+     * @param date 白坯库日统计数据主键
+     */
+    void delete4date(String date);
+}

+ 22 - 10
jjt-biz/src/main/java/com/jjt/inventory/mapper/TwinCalcHourBpMapper.java

@@ -1,20 +1,23 @@
 package com.jjt.inventory.mapper;
 
-import java.util.List;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.jjt.inventory.domain.TwinCalcHourBp;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
 
 /**
  * 白坯仓库小时数据Mapper接口
- * 
+ *
  * @author wukai
  * @date 2025-06-10
  */
-public interface TwinCalcHourBpMapper extends BaseMapper<TwinCalcHourBp>
-{
+public interface TwinCalcHourBpMapper extends BaseMapper<TwinCalcHourBp> {
     /**
      * 查询白坯仓库小时数据
-     * 
+     *
      * @param id 白坯仓库小时数据主键
      * @return 白坯仓库小时数据
      */
@@ -22,7 +25,7 @@ public interface TwinCalcHourBpMapper extends BaseMapper<TwinCalcHourBp>
 
     /**
      * 查询白坯仓库小时数据列表
-     * 
+     *
      * @param twinCalcHourBp 白坯仓库小时数据
      * @return 白坯仓库小时数据集合
      */
@@ -30,7 +33,7 @@ public interface TwinCalcHourBpMapper extends BaseMapper<TwinCalcHourBp>
 
     /**
      * 新增白坯仓库小时数据
-     * 
+     *
      * @param twinCalcHourBp 白坯仓库小时数据
      * @return 结果
      */
@@ -38,7 +41,7 @@ public interface TwinCalcHourBpMapper extends BaseMapper<TwinCalcHourBp>
 
     /**
      * 修改白坯仓库小时数据
-     * 
+     *
      * @param twinCalcHourBp 白坯仓库小时数据
      * @return 结果
      */
@@ -46,7 +49,7 @@ public interface TwinCalcHourBpMapper extends BaseMapper<TwinCalcHourBp>
 
     /**
      * 删除白坯仓库小时数据
-     * 
+     *
      * @param id 白坯仓库小时数据主键
      * @return 结果
      */
@@ -54,9 +57,18 @@ public interface TwinCalcHourBpMapper extends BaseMapper<TwinCalcHourBp>
 
     /**
      * 批量删除白坯仓库小时数据
-     * 
+     *
      * @param ids 需要删除的数据主键集合
      * @return 结果
      */
     public int deleteTwinCalcHourBpByIds(Long[] ids);
+
+    /**
+     * 查询白坯仓库小时数据
+     *
+     * @param time  时间
+     * @param hours 小时
+     * @return 白坯仓库小时数据集合
+     */
+    List<TwinCalcHourBp> selectTwinCalcHourBpByHours(@Param("time") Date time, @Param("hours") int[] hours);
 }

+ 76 - 0
jjt-biz/src/main/java/com/jjt/inventory/service/ITwinCalcDayBpService.java

@@ -0,0 +1,76 @@
+package com.jjt.inventory.service;
+
+import com.jjt.inventory.domain.TwinCalcDayBp;
+
+import java.time.LocalDate;
+import java.util.List;
+
+/**
+ * 白坯库日统计数据Service接口
+ *
+ * @author wukai
+ * @date 2025-06-13
+ */
+public interface ITwinCalcDayBpService {
+    /**
+     * 查询白坯库日统计数据
+     *
+     * @param id 白坯库日统计数据主键
+     * @return 白坯库日统计数据
+     */
+    public TwinCalcDayBp selectTwinCalcDayBpById(Long id);
+
+    /**
+     * 查询白坯库日统计数据列表
+     *
+     * @param twinCalcDayBp 白坯库日统计数据
+     * @return 白坯库日统计数据集合
+     */
+    public List<TwinCalcDayBp> selectTwinCalcDayBpList(TwinCalcDayBp twinCalcDayBp);
+
+    /**
+     * 新增白坯库日统计数据
+     *
+     * @param twinCalcDayBp 白坯库日统计数据
+     * @return 结果
+     */
+    public int insertTwinCalcDayBp(TwinCalcDayBp twinCalcDayBp);
+
+    /**
+     * 修改白坯库日统计数据
+     *
+     * @param twinCalcDayBp 白坯库日统计数据
+     * @return 结果
+     */
+    public int updateTwinCalcDayBp(TwinCalcDayBp twinCalcDayBp);
+
+    /**
+     * 批量删除白坯库日统计数据
+     *
+     * @param ids 需要删除的白坯库日统计数据主键集合
+     * @return 结果
+     */
+    public int deleteTwinCalcDayBpByIds(Long[] ids);
+
+    /**
+     * 删除白坯库日统计数据信息
+     *
+     * @param id 白坯库日统计数据主键
+     * @return 结果
+     */
+    public int deleteTwinCalcDayBpById(Long id);
+
+    /**
+     * 删除白坯库日统计数据信息
+     *
+     * @param date 白坯库日统计数据主键
+     */
+    void delete4date(String date);
+
+    /**
+     * 查询指定日期之后的白坯库日统计数据列表
+     *
+     * @param date 白坯库日统计数据主键
+     */
+    List<TwinCalcDayBp> selectStartDate(LocalDate date);
+}

+ 77 - 0
jjt-biz/src/main/java/com/jjt/inventory/service/ITwinCalcDayPtService.java

@@ -0,0 +1,77 @@
+package com.jjt.inventory.service;
+
+import com.jjt.inventory.domain.TwinCalcDayPt;
+
+import java.time.LocalDate;
+import java.util.List;
+
+/**
+ * 盘头库日统计数据Service接口
+ *
+ * @author wukai
+ * @date 2025-06-13
+ */
+public interface ITwinCalcDayPtService {
+    /**
+     * 查询盘头库日统计数据
+     *
+     * @param id 盘头库日统计数据主键
+     * @return 盘头库日统计数据
+     */
+    public TwinCalcDayPt selectTwinCalcDayPtById(Long id);
+
+    /**
+     * 查询盘头库日统计数据列表
+     *
+     * @param twinCalcDayPt 盘头库日统计数据
+     * @return 盘头库日统计数据集合
+     */
+    public List<TwinCalcDayPt> selectTwinCalcDayPtList(TwinCalcDayPt twinCalcDayPt);
+
+    /**
+     * 新增盘头库日统计数据
+     *
+     * @param twinCalcDayPt 盘头库日统计数据
+     * @return 结果
+     */
+    public int insertTwinCalcDayPt(TwinCalcDayPt twinCalcDayPt);
+
+    /**
+     * 修改盘头库日统计数据
+     *
+     * @param twinCalcDayPt 盘头库日统计数据
+     * @return 结果
+     */
+    public int updateTwinCalcDayPt(TwinCalcDayPt twinCalcDayPt);
+
+    /**
+     * 批量删除盘头库日统计数据
+     *
+     * @param ids 需要删除的盘头库日统计数据主键集合
+     * @return 结果
+     */
+    public int deleteTwinCalcDayPtByIds(Long[] ids);
+
+    /**
+     * 删除盘头库日统计数据信息
+     *
+     * @param id 盘头库日统计数据主键
+     * @return 结果
+     */
+    public int deleteTwinCalcDayPtById(Long id);
+
+    /**
+     * 删除白坯库日统计数据信息
+     *
+     * @param date 白坯库日统计数据主键
+     */
+    void delete4date(String date);
+
+    /**
+     * 获取指定日期之后的盘头库日统计数据
+     *
+     * @param toLocalDate 白坯库日统计数据主键
+     * @return 盘头库日统计数据集合
+     */
+    List<TwinCalcDayPt> selectStartDate(LocalDate toLocalDate);
+}

+ 13 - 0
jjt-biz/src/main/java/com/jjt/inventory/service/ITwinCalcHourBpService.java

@@ -3,7 +3,9 @@ package com.jjt.inventory.service;
 import com.jjt.inventory.domain.TwinCalcHourBp;
 
 import java.time.LocalDate;
+import java.util.Date;
 import java.util.List;
+import java.util.Map;
 
 /**
  * 白坯仓库小时数据Service接口
@@ -67,10 +69,21 @@ public interface ITwinCalcHourBpService {
      * @param hour 小时
      */
     void delete(LocalDate date, int hour);
+
     /**
      * 按天查询数据
+     *
      * @param date 日期
      * @return 结果
      */
     List<TwinCalcHourBp> selectTwinCalcHourPtByDay(LocalDate date);
+
+    /**
+     * 按照天统计数据查询
+     *
+     * @param date 日期
+     * @param hours 需要查询的小时
+     * @return 以小时分组的结果
+     */
+    Map<Integer, List<TwinCalcHourBp>> selectTwinCalcHourBpByHours(Date date, int[] hours);
 }

+ 10 - 0
jjt-biz/src/main/java/com/jjt/inventory/service/ITwinCalcHourPtService.java

@@ -3,6 +3,7 @@ package com.jjt.inventory.service;
 import com.jjt.inventory.domain.TwinCalcHourPt;
 
 import java.time.LocalDate;
+import java.util.Date;
 import java.util.List;
 
 /**
@@ -70,8 +71,17 @@ public interface ITwinCalcHourPtService {
 
     /**
      * 按天查询数据
+     *
      * @param date 日期
      * @return 结果
      */
     List<TwinCalcHourPt> selectTwinCalcHourPtByDay(LocalDate date);
+
+    /**
+     * 按小时查询数据
+     *
+     * @param time 时间
+     * @param hour 小时
+     */
+    List<TwinCalcHourPt>  selectTwinCalcHourPtByHour(Date time, Integer hour);
 }

+ 124 - 7
jjt-biz/src/main/java/com/jjt/inventory/service/impl/InventoryServiceImpl.java

@@ -1,16 +1,18 @@
 package com.jjt.inventory.service.impl;
 
 import com.jjt.common.utils.DateUtils;
+import com.jjt.inventory.domain.TwinCalcDayBp;
+import com.jjt.inventory.domain.TwinCalcDayPt;
 import com.jjt.inventory.domain.TwinCalcHourBp;
 import com.jjt.inventory.domain.TwinCalcHourPt;
 import com.jjt.inventory.mapper.TwinCalcHourBpMapper;
 import com.jjt.inventory.mapper.TwinCalcHourPtMapper;
-import com.jjt.inventory.service.IInventoryService;
-import com.jjt.inventory.service.ITwinCalcHourBpService;
-import com.jjt.inventory.service.ITwinCalcHourPtService;
+import com.jjt.inventory.service.*;
 import com.jjt.inventory.vo.StockVO;
+import com.jjt.system.service.ISysConfigService;
 import com.jjt.utils.MssqlService;
 import com.jjt.utils.Tools;
+import javafx.util.Pair;
 import org.apache.ibatis.session.ExecutorType;
 import org.apache.ibatis.session.SqlSession;
 import org.apache.ibatis.session.SqlSessionFactory;
@@ -18,12 +20,17 @@ import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
 import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
+import java.time.LocalTime;
 import java.util.*;
 import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
+import java.util.function.ToIntFunction;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 
 /**
  * * 库存管理接口Service业务层处理
@@ -38,9 +45,15 @@ public class InventoryServiceImpl implements IInventoryService {
     @Resource
     private SqlSessionFactory factory;
     @Resource
-    private ITwinCalcHourBpService bpService;
+    private ITwinCalcHourBpService hourBpService;
     @Resource
-    private ITwinCalcHourPtService ptService;
+    private ITwinCalcHourPtService hourPtService;
+    @Resource
+    private ISysConfigService configService;
+    @Resource
+    private ITwinCalcDayPtService dayPtService;
+    @Resource
+    private ITwinCalcDayBpService dayBpService;
 
     /**
      * 按小时库存数据
@@ -139,7 +152,7 @@ public class InventoryServiceImpl implements IInventoryService {
             pt.setCreateTime(new Date());
         });
 
-        ptService.delete(start.toLocalDate(), start.getHour());
+        hourPtService.delete(start.toLocalDate(), start.getHour());
         try (SqlSession sqlSession = factory.openSession(ExecutorType.BATCH, false)) {
             if (resultList.size() > 0) {
                 TwinCalcHourPtMapper mapper = sqlSession.getMapper(TwinCalcHourPtMapper.class);
@@ -220,7 +233,7 @@ public class InventoryServiceImpl implements IInventoryService {
             }
         });
 
-        bpService.delete(start.toLocalDate(), start.getHour());
+        hourBpService.delete(start.toLocalDate(), start.getHour());
         try (SqlSession sqlSession = factory.openSession(ExecutorType.BATCH, false)) {
             if (resultList.size() > 0) {
                 TwinCalcHourBpMapper mapper = sqlSession.getMapper(TwinCalcHourBpMapper.class);
@@ -238,6 +251,110 @@ public class InventoryServiceImpl implements IInventoryService {
      */
     @Override
     public void day(LocalDate localDate) {
+        ptDay(localDate);
+        bpDay(localDate);
+
+    }
+
+    private void bpDay(LocalDate date) {
+        //先删除当前日期数据
+        dayBpService.delete4date(date.toString());
+        TwinCalcHourBp search = new TwinCalcHourBp();
+        Map<String, Object> params = new HashMap<>(16);
+        LocalDateTime st = LocalDateTime.of(date, LocalTime.MIN).plusHours(7);
+        LocalDateTime ed = st.plusHours(23);
+        params.put("sTime", DateUtils.toDate(st));
+        params.put("eTime", DateUtils.toDate(ed));
+        search.setParams(params);
+        Map<Integer, List<TwinCalcHourBp>> hourMap = hourBpService.selectTwinCalcHourBpList(search).stream().collect(Collectors.groupingBy(TwinCalcHourBp::getHour));
+
+        // 统计方法
+        BiFunction<Integer, ToIntFunction<TwinCalcHourBp>, Pair<Integer, Integer>> stats;
+        stats = (defaultHour, mapper) -> {
+            Optional<Map.Entry<Integer, List<TwinCalcHourBp>>> maxEntry = hourMap.entrySet().stream()
+                    .max(Comparator.comparingInt(entry -> entry.getValue().stream().mapToInt(mapper).sum()));
+            Optional<Map.Entry<Integer, List<TwinCalcHourBp>>> minEntry = hourMap.entrySet().stream()
+                    .min(Comparator.comparingInt(entry -> entry.getValue().stream().mapToInt(mapper).sum()));
+
+//            int max = maxEntry.map(e -> e.getValue().stream().mapToInt(mapper).sum()).orElse(0);
+//            int min = minEntry.map(e -> e.getValue().stream().mapToInt(mapper).sum()).orElse(0);
+            int maxHour = maxEntry.map(Map.Entry::getKey).orElse(defaultHour);
+            int minHour = minEntry.map(Map.Entry::getKey).orElse(defaultHour);
+
+            return new Pair<>(maxHour, minHour);
+        };
 
+        // 卷数统计
+        Pair<Integer, Integer> rollStats = stats.apply(-1, TwinCalcHourBp::getRollNum);
+        int rollMaxHour = rollStats.getKey();
+        int rollMinHour = rollStats.getValue();
+        int rollMax = hourMap.getOrDefault(rollMaxHour, Collections.emptyList()).stream().mapToInt(TwinCalcHourBp::getRollNum).sum();
+        int rollMin = hourMap.getOrDefault(rollMinHour, Collections.emptyList()).stream().mapToInt(TwinCalcHourBp::getRollNum).sum();
+
+        // 米数统计
+        Pair<Integer, Integer> meterStats = stats.apply(-1, TwinCalcHourBp::getMeterNum);
+        int meterMaxHour = meterStats.getKey();
+        int meterMinHour = meterStats.getValue();
+        int meterMax = hourMap.getOrDefault(meterMaxHour, Collections.emptyList()).stream().mapToInt(TwinCalcHourBp::getMeterNum).sum();
+        int meterMin = hourMap.getOrDefault(meterMinHour, Collections.emptyList()).stream().mapToInt(TwinCalcHourBp::getMeterNum).sum();
+
+        // 重量统计
+        Pair<Integer, Integer> weightStats = stats.apply(-1, TwinCalcHourBp::getWeightNum);
+        int weightMaxHour = weightStats.getKey();
+        int weightMinHour = weightStats.getValue();
+        int weightMax = hourMap.getOrDefault(weightMaxHour, Collections.emptyList()).stream().mapToInt(TwinCalcHourBp::getWeightNum).sum();
+        int weightMin = hourMap.getOrDefault(weightMinHour, Collections.emptyList()).stream().mapToInt(TwinCalcHourBp::getWeightNum).sum();
+
+        TwinCalcDayBp day = new TwinCalcDayBp();
+        day.setRollMax(rollMax);
+        day.setRollMin(rollMin);
+        day.setMeterMax(meterMax);
+        day.setMeterMin(meterMin);
+        day.setWeightMax(weightMax);
+        day.setWeightMin(weightMin);
+        day.setRollData(rollMaxHour + "," + rollMinHour);
+        day.setMeterData(meterMaxHour + "," + meterMinHour);
+        day.setWeightData(weightMaxHour + "," + weightMinHour);
+
+        day.setTime(DateUtils.toDate(date));
+        dayBpService.insertTwinCalcDayBp(day);
+    }
+
+
+    private void ptDay(LocalDate date) {
+        Integer maxLimit = Integer.parseInt(configService.selectConfigByKey("inventory.pt.max"));
+        //先删除当前日期数据
+        dayPtService.delete4date(date.toString());
+        TwinCalcHourPt search = new TwinCalcHourPt();
+        Map<String, Object> params = new HashMap<>(16);
+        LocalDateTime st = LocalDateTime.of(date, LocalTime.MIN).plusHours(7);
+        LocalDateTime ed = st.plusHours(23);
+        params.put("sTime", DateUtils.toDate(st));
+        params.put("eTime", DateUtils.toDate(ed));
+        search.setParams(params);
+        Map<Integer, List<TwinCalcHourPt>> hourMap = hourPtService.selectTwinCalcHourPtList(search).stream().collect(Collectors.groupingBy(TwinCalcHourPt::getHour));
+        //找到最大值所在的小时及其小时值
+        Optional<Map.Entry<Integer, List<TwinCalcHourPt>>> maxEntry = hourMap.entrySet().stream()
+                .max(Comparator.comparingInt(entry -> entry.getValue().stream().mapToInt(TwinCalcHourPt::getNum).sum()));
+        int maxHour = maxEntry.map(Map.Entry::getKey).orElse(-1);
+        List<TwinCalcHourPt> tempList = maxEntry.map(Map.Entry::getValue).orElse(new ArrayList<>());
+        int max = tempList.stream().mapToInt(TwinCalcHourPt::getNum).sum();
+        TwinCalcDayPt day = new TwinCalcDayPt();
+        day.setMaxNum(max);
+        BigDecimal rate = BigDecimal.valueOf(max).divide(BigDecimal.valueOf(maxLimit), 4, RoundingMode.HALF_UP);
+        day.setRate(rate);
+        List<Map<String, Object>> dataList = new ArrayList<>();
+        tempList.stream().filter(item -> item.getNum() > 0).forEach(item -> {
+            BigDecimal ratio = BigDecimal.valueOf(item.getNum()).divide(BigDecimal.valueOf(max), 4, RoundingMode.HALF_UP);
+            Map<String, Object> map = new HashMap<>(16);
+            map.put("name", item.getName());
+            map.put("num", item.getNum());
+            map.put("ratio", ratio);
+            dataList.add(map);
+
+        });
+        day.setData(maxHour + "");
+        day.setTime(DateUtils.toDate(date));
+        dayPtService.insertTwinCalcDayPt(day);
     }
 }

+ 114 - 0
jjt-biz/src/main/java/com/jjt/inventory/service/impl/TwinCalcDayBpServiceImpl.java

@@ -0,0 +1,114 @@
+package com.jjt.inventory.service.impl;
+
+import com.jjt.inventory.domain.TwinCalcDayBp;
+import com.jjt.inventory.mapper.TwinCalcDayBpMapper;
+import com.jjt.inventory.service.ITwinCalcDayBpService;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.time.LocalDate;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 白坯库日统计数据Service业务层处理
+ *
+ * @author wukai
+ * @date 2025-06-13
+ */
+@Service
+public class TwinCalcDayBpServiceImpl implements ITwinCalcDayBpService {
+    @Resource
+    private TwinCalcDayBpMapper twinCalcDayBpMapper;
+
+    /**
+     * 查询白坯库日统计数据
+     *
+     * @param id 白坯库日统计数据主键
+     * @return 白坯库日统计数据
+     */
+    @Override
+    public TwinCalcDayBp selectTwinCalcDayBpById(Long id) {
+        return twinCalcDayBpMapper.selectTwinCalcDayBpById(id);
+    }
+
+    /**
+     * 查询白坯库日统计数据列表
+     *
+     * @param twinCalcDayBp 白坯库日统计数据
+     * @return 白坯库日统计数据
+     */
+    @Override
+    public List<TwinCalcDayBp> selectTwinCalcDayBpList(TwinCalcDayBp twinCalcDayBp) {
+        return twinCalcDayBpMapper.selectTwinCalcDayBpList(twinCalcDayBp);
+    }
+
+    /**
+     * 新增白坯库日统计数据
+     *
+     * @param twinCalcDayBp 白坯库日统计数据
+     * @return 结果
+     */
+    @Override
+    public int insertTwinCalcDayBp(TwinCalcDayBp twinCalcDayBp) {
+        return twinCalcDayBpMapper.insertTwinCalcDayBp(twinCalcDayBp);
+    }
+
+    /**
+     * 修改白坯库日统计数据
+     *
+     * @param twinCalcDayBp 白坯库日统计数据
+     * @return 结果
+     */
+    @Override
+    public int updateTwinCalcDayBp(TwinCalcDayBp twinCalcDayBp) {
+        return twinCalcDayBpMapper.updateTwinCalcDayBp(twinCalcDayBp);
+    }
+
+    /**
+     * 批量删除白坯库日统计数据
+     *
+     * @param ids 需要删除的白坯库日统计数据主键
+     * @return 结果
+     */
+    @Override
+    public int deleteTwinCalcDayBpByIds(Long[] ids) {
+        return twinCalcDayBpMapper.deleteTwinCalcDayBpByIds(ids);
+    }
+
+    /**
+     * 删除白坯库日统计数据信息
+     *
+     * @param id 白坯库日统计数据主键
+     * @return 结果
+     */
+    @Override
+    public int deleteTwinCalcDayBpById(Long id) {
+        return twinCalcDayBpMapper.deleteTwinCalcDayBpById(id);
+    }
+
+    /**
+     * 删除白坯库日统计数据信息
+     *
+     * @param date 白坯库日统计数据主键
+     */
+    @Override
+    public void delete4date(String date) {
+        twinCalcDayBpMapper.delete4date(date);
+    }
+
+    /**
+     * 查询指定日期之后的白坯库日统计数据列表
+     *
+     * @param date 白坯库日统计数据主键
+     */
+    @Override
+    public List<TwinCalcDayBp> selectStartDate(LocalDate date) {
+        TwinCalcDayBp query = new TwinCalcDayBp();
+        Map<String, Object> params = new HashMap<>(16);
+        params.put("time", date);
+        query.setParams(params);
+        return selectTwinCalcDayBpList(query);
+    }
+}

+ 116 - 0
jjt-biz/src/main/java/com/jjt/inventory/service/impl/TwinCalcDayPtServiceImpl.java

@@ -0,0 +1,116 @@
+package com.jjt.inventory.service.impl;
+
+import com.jjt.inventory.domain.TwinCalcDayPt;
+import com.jjt.inventory.mapper.TwinCalcDayPtMapper;
+import com.jjt.inventory.service.ITwinCalcDayPtService;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.time.LocalDate;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 盘头库日统计数据Service业务层处理
+ *
+ * @author wukai
+ * @date 2025-06-13
+ */
+@Service
+public class TwinCalcDayPtServiceImpl implements ITwinCalcDayPtService {
+    @Resource
+    private TwinCalcDayPtMapper twinCalcDayPtMapper;
+
+    /**
+     * 查询盘头库日统计数据
+     *
+     * @param id 盘头库日统计数据主键
+     * @return 盘头库日统计数据
+     */
+    @Override
+    public TwinCalcDayPt selectTwinCalcDayPtById(Long id) {
+        return twinCalcDayPtMapper.selectTwinCalcDayPtById(id);
+    }
+
+    /**
+     * 查询盘头库日统计数据列表
+     *
+     * @param twinCalcDayPt 盘头库日统计数据
+     * @return 盘头库日统计数据
+     */
+    @Override
+    public List<TwinCalcDayPt> selectTwinCalcDayPtList(TwinCalcDayPt twinCalcDayPt) {
+        return twinCalcDayPtMapper.selectTwinCalcDayPtList(twinCalcDayPt);
+    }
+
+    /**
+     * 新增盘头库日统计数据
+     *
+     * @param twinCalcDayPt 盘头库日统计数据
+     * @return 结果
+     */
+    @Override
+    public int insertTwinCalcDayPt(TwinCalcDayPt twinCalcDayPt) {
+        return twinCalcDayPtMapper.insertTwinCalcDayPt(twinCalcDayPt);
+    }
+
+    /**
+     * 修改盘头库日统计数据
+     *
+     * @param twinCalcDayPt 盘头库日统计数据
+     * @return 结果
+     */
+    @Override
+    public int updateTwinCalcDayPt(TwinCalcDayPt twinCalcDayPt) {
+        return twinCalcDayPtMapper.updateTwinCalcDayPt(twinCalcDayPt);
+    }
+
+    /**
+     * 批量删除盘头库日统计数据
+     *
+     * @param ids 需要删除的盘头库日统计数据主键
+     * @return 结果
+     */
+    @Override
+    public int deleteTwinCalcDayPtByIds(Long[] ids) {
+        return twinCalcDayPtMapper.deleteTwinCalcDayPtByIds(ids);
+    }
+
+    /**
+     * 删除盘头库日统计数据信息
+     *
+     * @param id 盘头库日统计数据主键
+     * @return 结果
+     */
+    @Override
+    public int deleteTwinCalcDayPtById(Long id) {
+        return twinCalcDayPtMapper.deleteTwinCalcDayPtById(id);
+    }
+
+    /**
+     * 删除白坯库日统计数据信息
+     *
+     * @param date 白坯库日统计数据主键
+     */
+    @Override
+    public void delete4date(String date) {
+        twinCalcDayPtMapper.delete4date(date);
+    }
+
+
+    /**
+     * 查询白坯库日统计数据
+     *
+     * @param date 白坯库日统计数据主键
+     * @return 白坯库日统计数据
+     */
+    @Override
+    public List<TwinCalcDayPt> selectStartDate(LocalDate date) {
+        TwinCalcDayPt query = new TwinCalcDayPt();
+        Map<String, Object> params = new HashMap<>(16);
+        params.put("time", date);
+        query.setParams(params);
+        return selectTwinCalcDayPtList(query);
+    }
+}

+ 16 - 0
jjt-biz/src/main/java/com/jjt/inventory/service/impl/TwinCalcHourBpServiceImpl.java

@@ -9,7 +9,10 @@ import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
 import java.time.LocalDate;
+import java.util.Date;
 import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * 白坯仓库小时数据Service业务层处理
@@ -114,4 +117,17 @@ public class TwinCalcHourBpServiceImpl implements ITwinCalcHourBpService {
         query.setDataDate(DateUtils.toDate(date));
         return selectTwinCalcHourBpList(query);
     }
+
+    /**
+     * 按照天统计数据查询
+     *
+     * @param date 日期
+     * @param hours 需要查询的小时
+     * @return 以小时分组的结果
+     */
+    @Override
+    public Map<Integer, List<TwinCalcHourBp>> selectTwinCalcHourBpByHours(Date date, int[] hours) {
+        List<TwinCalcHourBp> list = twinCalcHourBpMapper.selectTwinCalcHourBpByHours(date, hours);
+        return list.stream().collect(Collectors.groupingBy(TwinCalcHourBp::getHour));
+    }
 }

+ 16 - 0
jjt-biz/src/main/java/com/jjt/inventory/service/impl/TwinCalcHourPtServiceImpl.java

@@ -9,6 +9,7 @@ import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
 import java.time.LocalDate;
+import java.util.Date;
 import java.util.List;
 
 /**
@@ -114,4 +115,19 @@ public class TwinCalcHourPtServiceImpl implements ITwinCalcHourPtService {
         query.setDataDate(DateUtils.toDate(date));
         return selectTwinCalcHourPtList(query);
     }
+
+    /**
+     * 按时间查询
+     *
+     * @param time 时间
+     * @param hour 小时
+     * @return 结果
+     */
+    @Override
+    public List<TwinCalcHourPt> selectTwinCalcHourPtByHour(Date time, Integer hour) {
+        TwinCalcHourPt query = new TwinCalcHourPt();
+        query.setDataDate(time);
+        query.setHour(hour);
+        return selectTwinCalcHourPtList(query);
+    }
 }

+ 18 - 9
jjt-biz/src/main/java/com/jjt/inventory/vo/BpVO.java

@@ -8,8 +8,10 @@ import lombok.NoArgsConstructor;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.time.LocalDate;
+import java.util.ArrayList;
 import java.util.List;
 
+
 /**
  * 白柸布库存视图
  *
@@ -36,13 +38,13 @@ public class BpVO {
     private List<Stock> weightStocks;
 
     public BpVO() {
-        this.tops = new java.util.ArrayList<>();
-        this.rollMonthStocks = new java.util.ArrayList<>();
-        this.meterMonthStocks = new java.util.ArrayList<>();
-        this.weightMonthStocks = new java.util.ArrayList<>();
-        this.rollStocks = new java.util.ArrayList<>();
-        this.meterStocks = new java.util.ArrayList<>();
-        this.weightStocks = new java.util.ArrayList<>();
+        this.tops = new ArrayList<>();
+        this.rollMonthStocks = new ArrayList<>();
+        this.meterMonthStocks = new ArrayList<>();
+        this.weightMonthStocks = new ArrayList<>();
+        this.rollStocks = new ArrayList<>();
+        this.meterStocks = new ArrayList<>();
+        this.weightStocks = new ArrayList<>();
     }
 
     @Data
@@ -50,6 +52,8 @@ public class BpVO {
     public static class Stock {
         @ApiModelProperty("纱种名称")
         private String name;
+        @ApiModelProperty("米克重")
+        private Integer mick;
         @ApiModelProperty("入库数量")
         private Integer in;
         @ApiModelProperty("出库数量")
@@ -105,11 +109,14 @@ public class BpVO {
         private BigDecimal avg;
         @ApiModelProperty("时间")
         private LocalDate date;
-        @ApiModelProperty("纱种明细")
+        @ApiModelProperty("最大库存时-纱种明细")
         private List<YarnTypeDetail> details;
+        @ApiModelProperty("最小库存时-纱种明细")
+        private List<YarnTypeDetail> minDetails;
 
         public MonthStock() {
-            this.details = new java.util.ArrayList<>();
+            this.details = new ArrayList<>();
+            this.minDetails = new ArrayList<>();
         }
     }
 
@@ -119,6 +126,8 @@ public class BpVO {
     public static class YarnTypeDetail {
         @ApiModelProperty("纱种名称")
         private String name;
+        @ApiModelProperty("米克重")
+        private Integer mick;
         @ApiModelProperty("数量")
         private Integer num;
         @ApiModelProperty("纱种占比")

+ 153 - 0
jjt-biz/src/main/resources/mapper/inventory/TwinCalcDayBpMapper.xml

@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jjt.inventory.mapper.TwinCalcDayBpMapper">
+
+    <resultMap type="TwinCalcDayBp" id="TwinCalcDayBpResult">
+        <result property="id" column="ID"/>
+        <result property="time" column="TIME"/>
+        <result property="deviceId" column="DEVICE_ID"/>
+        <result property="rollMax" column="ROLL_MAX"/>
+        <result property="meterMax" column="METER_MAX"/>
+        <result property="weightMax" column="WEIGHT_MAX"/>
+        <result property="rollMin" column="ROLL_MIN"/>
+        <result property="meterMin" column="METER_MIN"/>
+        <result property="weightMin" column="WEIGHT_MIN"/>
+        <result property="rollAvg" column="ROLL_AVG"/>
+        <result property="meterAvg" column="METER_AVG"/>
+        <result property="weightAvg" column="WEIGHT_AVG"/>
+        <result property="rollData" column="ROLL_DATA"/>
+        <result property="meterData" column="METER_DATA"/>
+        <result property="weightData" column="WEIGHT_DATA"/>
+        <result property="remark" column="REMARK"/>
+    </resultMap>
+
+    <sql id="selectTwinCalcDayBpVo">
+        select ID,
+               TIME,
+               DEVICE_ID,
+               ROLL_MAX,
+               METER_MAX,
+               WEIGHT_MAX,
+               ROLL_MIN,
+               METER_MIN,
+               WEIGHT_MIN,
+               ROLL_AVG,
+               METER_AVG,
+               WEIGHT_AVG,
+               ROLL_DATA,
+               METER_DATA,
+               WEIGHT_DATA,
+               REMARK
+        from TWIN_CALC_DAY_BP
+    </sql>
+
+    <select id="selectTwinCalcDayBpList" parameterType="TwinCalcDayBp" resultMap="TwinCalcDayBpResult">
+        <include refid="selectTwinCalcDayBpVo"/>
+        <where>
+            <if test="time != null ">and TIME = #{time}</if>
+            <if test="deviceId != null ">and DEVICE_ID = #{deviceId}</if>
+            <if test="rollMax != null ">and ROLL_MAX = #{rollMax}</if>
+            <if test="meterMax != null ">and METER_MAX = #{meterMax}</if>
+            <if test="weightMax != null ">and WEIGHT_MAX = #{weightMax}</if>
+            <if test="rollMin != null ">and ROLL_MIN = #{rollMin}</if>
+            <if test="meterMin != null ">and METER_MIN = #{meterMin}</if>
+            <if test="weightMin != null ">and WEIGHT_MIN = #{weightMin}</if>
+            <if test="rollAvg != null ">and ROLL_AVG = #{rollAvg}</if>
+            <if test="meterAvg != null ">and METER_AVG = #{meterAvg}</if>
+            <if test="weightAvg != null ">and WEIGHT_AVG = #{weightAvg}</if>
+            <if test="rollData != null  and rollData != ''">and ROLL_DATA = #{rollData}</if>
+            <if test="meterData != null  and meterData != ''">and METER_DATA = #{meterData}</if>
+            <if test="weightData != null  and weightData != ''">and WEIGHT_DATA = #{weightData}</if>
+            <if test="remark != null  and remark != ''">and REMARK = #{remark}</if>
+            <if test="params.start != null and params.start != ''">
+                and TIME >= #{params.start}
+            </if>
+        </where>
+        order by time desc
+    </select>
+
+    <select id="selectTwinCalcDayBpById" parameterType="Long" resultMap="TwinCalcDayBpResult">
+        <include refid="selectTwinCalcDayBpVo"/>
+        where ID = #{id}
+    </select>
+
+    <insert id="insertTwinCalcDayBp" parameterType="TwinCalcDayBp" useGeneratedKeys="true" keyProperty="id">
+        insert into TWIN_CALC_DAY_BP
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="time != null">TIME,</if>
+            <if test="deviceId != null">DEVICE_ID,</if>
+            <if test="rollMax != null">ROLL_MAX,</if>
+            <if test="meterMax != null">METER_MAX,</if>
+            <if test="weightMax != null">WEIGHT_MAX,</if>
+            <if test="rollMin != null">ROLL_MIN,</if>
+            <if test="meterMin != null">METER_MIN,</if>
+            <if test="weightMin != null">WEIGHT_MIN,</if>
+            <if test="rollAvg != null">ROLL_AVG,</if>
+            <if test="meterAvg != null">METER_AVG,</if>
+            <if test="weightAvg != null">WEIGHT_AVG,</if>
+            <if test="rollData != null">ROLL_DATA,</if>
+            <if test="meterData != null">METER_DATA,</if>
+            <if test="weightData != null">WEIGHT_DATA,</if>
+            <if test="remark != null">REMARK,</if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="time != null">#{time},</if>
+            <if test="deviceId != null">#{deviceId},</if>
+            <if test="rollMax != null">#{rollMax},</if>
+            <if test="meterMax != null">#{meterMax},</if>
+            <if test="weightMax != null">#{weightMax},</if>
+            <if test="rollMin != null">#{rollMin},</if>
+            <if test="meterMin != null">#{meterMin},</if>
+            <if test="weightMin != null">#{weightMin},</if>
+            <if test="rollAvg != null">#{rollAvg},</if>
+            <if test="meterAvg != null">#{meterAvg},</if>
+            <if test="weightAvg != null">#{weightAvg},</if>
+            <if test="rollData != null">#{rollData},</if>
+            <if test="meterData != null">#{meterData},</if>
+            <if test="weightData != null">#{weightData},</if>
+            <if test="remark != null">#{remark},</if>
+        </trim>
+    </insert>
+
+    <update id="updateTwinCalcDayBp" parameterType="TwinCalcDayBp">
+        update TWIN_CALC_DAY_BP
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="time != null">TIME = #{time},</if>
+            <if test="deviceId != null">DEVICE_ID = #{deviceId},</if>
+            <if test="rollMax != null">ROLL_MAX = #{rollMax},</if>
+            <if test="meterMax != null">METER_MAX = #{meterMax},</if>
+            <if test="weightMax != null">WEIGHT_MAX = #{weightMax},</if>
+            <if test="rollMin != null">ROLL_MIN = #{rollMin},</if>
+            <if test="meterMin != null">METER_MIN = #{meterMin},</if>
+            <if test="weightMin != null">WEIGHT_MIN = #{weightMin},</if>
+            <if test="rollAvg != null">ROLL_AVG = #{rollAvg},</if>
+            <if test="meterAvg != null">METER_AVG = #{meterAvg},</if>
+            <if test="weightAvg != null">WEIGHT_AVG = #{weightAvg},</if>
+            <if test="rollData != null">ROLL_DATA = #{rollData},</if>
+            <if test="meterData != null">METER_DATA = #{meterData},</if>
+            <if test="weightData != null">WEIGHT_DATA = #{weightData},</if>
+            <if test="remark != null">REMARK = #{remark},</if>
+        </trim>
+        where ID = #{id}
+    </update>
+
+    <delete id="deleteTwinCalcDayBpById" parameterType="Long">
+        delete
+        from TWIN_CALC_DAY_BP
+        where ID = #{id}
+    </delete>
+
+    <delete id="deleteTwinCalcDayBpByIds" parameterType="String">
+        delete from TWIN_CALC_DAY_BP where ID in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+    <delete id="delete4date">
+        delete
+        from TWIN_CALC_DAY_BP
+        where time = #{date}
+    </delete>
+</mapper>

+ 105 - 0
jjt-biz/src/main/resources/mapper/inventory/TwinCalcDayPtMapper.xml

@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jjt.inventory.mapper.TwinCalcDayPtMapper">
+
+    <resultMap type="TwinCalcDayPt" id="TwinCalcDayPtResult">
+        <result property="id" column="ID"/>
+        <result property="time" column="TIME"/>
+        <result property="deviceId" column="DEVICE_ID"/>
+        <result property="maxNum" column="MAX_NUM"/>
+        <result property="avgNum" column="AVG_NUM"/>
+        <result property="rate" column="RATE"/>
+        <result property="data" column="DATA"/>
+        <result property="remark" column="REMARK"/>
+    </resultMap>
+
+    <sql id="selectTwinCalcDayPtVo">
+        select ID,
+               TIME,
+               DEVICE_ID,
+               MAX_NUM,
+               AVG_NUM,
+               RATE,
+               DATA,
+               REMARK
+        from TWIN_CALC_DAY_PT
+    </sql>
+
+    <select id="selectTwinCalcDayPtList" parameterType="TwinCalcDayPt" resultMap="TwinCalcDayPtResult">
+        <include refid="selectTwinCalcDayPtVo"/>
+        <where>
+            <if test="time != null ">and TIME = #{time}</if>
+            <if test="deviceId != null ">and DEVICE_ID = #{deviceId}</if>
+            <if test="maxNum != null ">and MAX_NUM = #{maxNum}</if>
+            <if test="avgNum != null ">and AVG_NUM = #{avgNum}</if>
+            <if test="rate != null ">and RATE = #{rate}</if>
+            <if test="data != null  and data != ''">and DATA = #{data}</if>
+            <if test="remark != null  and remark != ''">and REMARK = #{remark}</if>
+            <if test="params.start != null and params.start != ''">
+                and TIME >= #{params.start}
+            </if>
+        </where>
+        order by time desc
+    </select>
+
+    <select id="selectTwinCalcDayPtById" parameterType="Long" resultMap="TwinCalcDayPtResult">
+        <include refid="selectTwinCalcDayPtVo"/>
+        where ID = #{id}
+    </select>
+
+    <insert id="insertTwinCalcDayPt" parameterType="TwinCalcDayPt" useGeneratedKeys="true" keyProperty="id">
+        insert into TWIN_CALC_DAY_PT
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="time != null">TIME,</if>
+            <if test="deviceId != null">DEVICE_ID,</if>
+            <if test="maxNum != null">MAX_NUM,</if>
+            <if test="avgNum != null">AVG_NUM,</if>
+            <if test="rate != null">RATE,</if>
+            <if test="data != null">DATA,</if>
+            <if test="remark != null">REMARK,</if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="time != null">#{time},</if>
+            <if test="deviceId != null">#{deviceId},</if>
+            <if test="maxNum != null">#{maxNum},</if>
+            <if test="avgNum != null">#{avgNum},</if>
+            <if test="rate != null">#{rate},</if>
+            <if test="data != null">#{data},</if>
+            <if test="remark != null">#{remark},</if>
+        </trim>
+    </insert>
+
+    <update id="updateTwinCalcDayPt" parameterType="TwinCalcDayPt">
+        update TWIN_CALC_DAY_PT
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="time != null">TIME = #{time},</if>
+            <if test="deviceId != null">DEVICE_ID = #{deviceId},</if>
+            <if test="maxNum != null">MAX_NUM = #{maxNum},</if>
+            <if test="avgNum != null">AVG_NUM = #{avgNum},</if>
+            <if test="rate != null">RATE = #{rate},</if>
+            <if test="data != null">DATA = #{data},</if>
+            <if test="remark != null">REMARK = #{remark},</if>
+        </trim>
+        where ID = #{id}
+    </update>
+
+    <delete id="deleteTwinCalcDayPtById" parameterType="Long">
+        delete
+        from TWIN_CALC_DAY_PT
+        where ID = #{id}
+    </delete>
+
+    <delete id="deleteTwinCalcDayPtByIds" parameterType="String">
+        delete from TWIN_CALC_DAY_PT where ID in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+    <delete id="delete4date">
+        delete
+        from TWIN_CALC_DAY_PT
+        where TIME = #{date}
+    </delete>
+</mapper>

+ 11 - 0
jjt-biz/src/main/resources/mapper/inventory/TwinCalcHourBpMapper.xml

@@ -73,6 +73,9 @@
             <if test="updatedBy != null  and updatedBy != ''">and UPDATED_BY = #{updatedBy}</if>
             <if test="updatedTime != null ">and UPDATED_TIME = #{updatedTime}</if>
             <if test="remark != null  and remark != ''">and REMARK = #{remark}</if>
+            <if test="params.sTime != null and params.eTime != null">
+                and DATEADD(hour, HOUR, DATA_DATE) between #{params.sTime} and #{params.eTime}
+            </if>
         </where>
         ORDER BY DATA_DATE DESC,HOUR DESC
     </select>
@@ -81,6 +84,14 @@
         <include refid="selectTwinCalcHourBpVo"/>
         where ID = #{id}
     </select>
+    <select id="selectTwinCalcHourBpByHours"  resultMap="TwinCalcHourBpResult">
+        select * from TWIN_CALC_HOUR_BP
+        where DATA_DATE = #{time}
+        and HOUR in
+        <foreach item="item" collection="hours" separator="," open="(" close=")" index="">
+            #{item}
+        </foreach>
+    </select>
 
     <insert id="insertTwinCalcHourBp" parameterType="TwinCalcHourBp">
         insert into TWIN_CALC_HOUR_BP

+ 3 - 0
jjt-biz/src/main/resources/mapper/inventory/TwinCalcHourPtMapper.xml

@@ -52,6 +52,9 @@
             <if test="updatedBy != null  and updatedBy != ''">and UPDATED_BY = #{updatedBy}</if>
             <if test="updatedTime != null ">and UPDATED_TIME = #{updatedTime}</if>
             <if test="remark != null  and remark != ''">and REMARK = #{remark}</if>
+            <if test="params.sTime != null and params.eTime != null">
+                and DATEADD(hour, HOUR, DATA_DATE) between #{params.sTime} and #{params.eTime}
+            </if>
         </where>
         ORDER BY DATA_DATE DESC,HOUR DESC
     </select>