浏览代码

报表统计开发

klzhangweiya 3 月之前
父节点
当前提交
bd742558b2
共有 100 个文件被更改,包括 5918 次插入896 次删除
  1. 1 0
      .gitignore
  2. 2 1
      SERVER/ChickenFarmV3/.script/docker/docker-compose.local.yml
  3. 14 6
      SERVER/ChickenFarmV3/.script/docker/docker-compose.yml
  4. 466 384
      SERVER/ChickenFarmV3/.script/docker/sql/init.sql
  5. 10 10
      SERVER/ChickenFarmV3/pom.xml
  6. 1 1
      SERVER/ChickenFarmV3/vb-admin/src/main/resources/application-dev.yml
  7. 3 0
      SERVER/ChickenFarmV3/vb-common/vb-common-core/src/main/java/cn/vber/common/core/service/ChickenSopService.java
  8. 23 5
      SERVER/ChickenFarmV3/vb-common/vb-common-core/src/main/java/cn/vber/common/core/utils/ChickenCalcUtils.java
  9. 41 0
      SERVER/ChickenFarmV3/vb-common/vb-common-core/src/main/java/cn/vber/common/core/utils/DateUtils.java
  10. 1 1
      SERVER/ChickenFarmV3/vb-extend/vb-job-admin/src/main/resources/application-dev.yml
  11. 10 0
      SERVER/ChickenFarmV3/vb-modules/vb-base/src/main/java/cn/vber/base/constant/CommonConstant.java
  12. 22 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/controller/BatchController.java
  13. 3 2
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/controller/CageChangeController.java
  14. 19 1
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/controller/ChickenController.java
  15. 135 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/controller/ChickenMetatarsalController.java
  16. 133 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/controller/ChickenTibiaController.java
  17. 158 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/controller/CoopBatchReportController.java
  18. 108 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/controller/CoopBatchReportDetailController.java
  19. 0 132
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/controller/CoopEggDayController.java
  20. 5 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/CageChange.java
  21. 6 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/ChickenCoop.java
  22. 10 15
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/ChickenMetatarsal.java
  23. 64 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/ChickenTibia.java
  24. 177 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/CoopBatchReport.java
  25. 163 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/CoopBatchReportDetail.java
  26. 6 6
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/MeasureDetail.java
  27. 4 1
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/bo/CageChangeBo.java
  28. 1 1
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/bo/ChickenBo.java
  29. 2 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/bo/ChickenCoopBo.java
  30. 62 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/bo/ChickenMetatarsalBo.java
  31. 15 17
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/bo/ChickenTibiaBo.java
  32. 183 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/bo/CoopBatchReportBo.java
  33. 169 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/bo/CoopBatchReportDetailBo.java
  34. 6 6
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/bo/MeasureDetailBo.java
  35. 11 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/bo/chicken/QuerySopLogBo.java
  36. 19 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/bo/statistic/QueryStaBo.java
  37. 32 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/bo/statistic/QueryStaScopeParam.java
  38. 34 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/bo/statistic/QueryStaScopeParamBo.java
  39. 5 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/CageChangeVo.java
  40. 3 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/ChickenCoopVo.java
  41. 2 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/ChickenDrugVo.java
  42. 2 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/ChickenFeedVo.java
  43. 74 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/ChickenMetatarsalVo.java
  44. 19 22
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/ChickenTibiaVo.java
  45. 2 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/ChickenVaccineVo.java
  46. 184 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/CoopBatchReportDetailVo.java
  47. 206 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/CoopBatchReportVo.java
  48. 21 6
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/MeasureDetailVo.java
  49. 15 2
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/MiddleWeightInfoVo.java
  50. 28 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/excel/ChickenMetatarsalImportVo.java
  51. 28 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/excel/ChickenTibiaImportVo.java
  52. 2 2
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/excel/MeasureDetailImportVo.java
  53. 17 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/report/CoopBatchReportDetailResult.java
  54. 166 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/report/CoopBatchReportDetailView.java
  55. 15 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/report/CoopBatchReportResultVo.java
  56. 36 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/sop/SopBindLogVo.java
  57. 25 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/statistic/ChickenStatisticDayResultVo.java
  58. 20 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/statistic/CoopBatchChickenStatisticResultVo.java
  59. 16 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/statistic/CoopBatchCommonSta.java
  60. 20 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/statistic/CoopBatchEggStatisticResultVo.java
  61. 13 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/statistic/StatisticLastDayResultDto.java
  62. 86 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/statistic/StatisticTmpResultDto.java
  63. 15 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/statistic/SumFemaleCountTmpDto.java
  64. 1 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/listener/BreedingEggImportListener.java
  65. 14 5
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/listener/CageChangeImportListener.java
  66. 57 34
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/listener/ChickenImportListener.java
  67. 152 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/listener/ChickenMetatarsalImportListener.java
  68. 149 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/listener/ChickenTibiaImportListener.java
  69. 234 17
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/listener/MeasureDetailImportListener.java
  70. 4 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/mapper/BatchFeedMapper.java
  71. 22 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/mapper/ChickenCoopMapper.java
  72. 22 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/mapper/ChickenMetatarsalMapper.java
  73. 22 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/mapper/ChickenTibiaMapper.java
  74. 56 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/mapper/CoopBatchReportDetailMapper.java
  75. 22 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/mapper/CoopBatchReportMapper.java
  76. 0 22
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/mapper/CoopEggDayMapper.java
  77. 2 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/IBatchService.java
  78. 54 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/IChickenMetatarsalService.java
  79. 54 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/IChickenTibiaService.java
  80. 20 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/ICommonService.java
  81. 61 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/ICoopBatchReportDetailService.java
  82. 57 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/ICoopBatchReportService.java
  83. 0 54
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/ICoopEggDayService.java
  84. 14 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/ISopService.java
  85. 32 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/IStatisticsHelperService.java
  86. 10 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/IStatisticsService.java
  87. 15 2
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/impl/BatchServiceImpl.java
  88. 6 2
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/impl/CageChangeServiceImpl.java
  89. 3 2
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/impl/ChickenCoopServiceImpl.java
  90. 117 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/impl/ChickenMetatarsalServiceImpl.java
  91. 26 14
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/impl/ChickenServiceImpl.java
  92. 15 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/impl/ChickenSopServiceImpl.java
  93. 117 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/impl/ChickenTibiaServiceImpl.java
  94. 377 5
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/impl/CommonServiceImpl.java
  95. 190 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/impl/CoopBatchReportDetailServiceImpl.java
  96. 162 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/impl/CoopBatchReportServiceImpl.java
  97. 0 118
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/impl/CoopEggDayServiceImpl.java
  98. 6 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/impl/MeasureServiceImpl.java
  99. 284 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/impl/SopServiceImpl.java
  100. 402 0
      SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/impl/StatisticsHelperServiceImpl.java

+ 1 - 0
.gitignore

@@ -72,3 +72,4 @@ UI/VAP_V3.VUE/pnpm-lock.yaml
 
 .data/
 
+docs/部署文档/*.rar

+ 2 - 1
SERVER/ChickenFarmV3/.script/docker/docker-compose.local.yml

@@ -40,7 +40,8 @@ services:
       - ./redis/conf/redis.conf:/redis/config/redis.conf
       # 数据文件
       - ../../.data/redis/data:/redis/data/:rw
-    command: "redis-server /redis/config/redis.conf"
+    command: /bin/bash -c "mkdir -p /redis/data &&
+      chmod 777 /redis/data && redis-server /redis/config/redis.conf"
     privileged: true
     networks:
       - chicken-net

+ 14 - 6
SERVER/ChickenFarmV3/.script/docker/docker-compose.yml

@@ -1,6 +1,6 @@
 services:
   mysql:
-    image: mysql:8.0.39
+    image: mysql:8.0.42
     container_name: cf-mysql
     environment:
       # 时区上海
@@ -32,7 +32,7 @@ services:
       - chicken-net
 
   redis:
-    image: redis:6.2.6
+    image: redis:7.2.8
     container_name: cf-redis
     ports:
       - "6399:6379"
@@ -48,20 +48,28 @@ services:
       - /home/docker/chicken_farm/redis/conf/redis.conf:/redis/config/redis.conf
       #数据文件
       - /home/docker/chicken_farm/redis/data:/redis/data/:rw
-    command: "redis-server /redis/config/redis.conf"
+    command: /bin/bash -c "mkdir -p /redis/data &&
+      chmod 777 /redis/data && redis-server /redis/config/redis.conf"
     privileged: true
     networks:
       - chicken-net
 
   chicken-farm-admin-server1:
     #build: ../../vb-admin
-    image: chicken-farm-admin-server:1.0.0
+    image: cf-admin-server:1.0.0
     container_name: cf-admin-server1
     environment:
       # 时区上海
       TZ: Asia/Shanghai
       #SERVER_PORT: 6080
-      JAVA_OPTS: --spring.datasource.dynamic.datasource.master.url=jdbc:mysql://cf-mysql:3306/ChickenFarmDB_DEV?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true --spring.datasource.dynamic.datasource.master.username=root --spring.datasource.dynamic.datasource.master.password=root --spring.data.redis.host=cf-redis --spring.data.redis.port=6379 --spring.data.redis.password=123456cf
+      #JAVA_OPTS: --spring.datasource.dynamic.datasource.master.url=jdbc:mysql://cf-mysql:3306/ChickenFarmDB_DEV?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true --spring.datasource.dynamic.datasource.master.username=root --spring.datasource.dynamic.datasource.master.password=root --spring.data.redis.host=cf-redis --spring.data.redis.port=6379 --spring.data.redis.password=123456cf
+      JAVA_OPTS: >-
+        --spring.datasource.dynamic.datasource.master.url=jdbc:mysql://cf-mysql:3306/ChickenFarmDB_DEV?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true 
+        --spring.datasource.dynamic.datasource.master.username=root 
+        --spring.datasource.dynamic.datasource.master.password=root 
+        --spring.data.redis.host=cf-redis 
+        --spring.data.redis.port=6379 
+        --spring.data.redis.password=123456cf
     volumes:
       # 配置文件
       - /home/docker/chicken_farm/server/:/vber/server/
@@ -78,7 +86,7 @@ services:
 
   chicken-farm-ui-web:
     image: cf-admin-ui:1.0.0
-    container_name: chicken_farm_ui_web
+    container_name: cf_admin_ui_web
     environment:
       # 时区上海
       TZ: Asia/Shanghai

文件差异内容过多而无法显示
+ 466 - 384
SERVER/ChickenFarmV3/.script/docker/sql/init.sql


+ 10 - 10
SERVER/ChickenFarmV3/pom.xml

@@ -71,16 +71,16 @@
     </properties>
 
     <profiles>
-        <profile>
-            <id>local</id>
-            <properties>
-                <!-- 环境标识,需要与配置文件的名称相对应 -->
-                <profiles.active>local</profiles.active>
-                <logging.level>info</logging.level>
-                <monitor.username>vber</monitor.username>
-                <monitor.password>vb123456</monitor.password>
-            </properties>
-        </profile>
+<!--        <profile>-->
+<!--            <id>local</id>-->
+<!--            <properties>-->
+<!--                &lt;!&ndash; 环境标识,需要与配置文件的名称相对应 &ndash;&gt;-->
+<!--                <profiles.active>local</profiles.active>-->
+<!--                <logging.level>info</logging.level>-->
+<!--                <monitor.username>vber</monitor.username>-->
+<!--                <monitor.password>vb123456</monitor.password>-->
+<!--            </properties>-->
+<!--        </profile>-->
         <profile>
             <id>dev</id>
             <properties>

+ 1 - 1
SERVER/ChickenFarmV3/vb-admin/src/main/resources/application-dev.yml

@@ -113,7 +113,7 @@ spring.boot.admin.client:
 --- # xxl-job 配置
 xxl.job:
   # 执行器开关
-  enabled: false
+  enabled: true
   # 调度中心地址:如调度中心集群部署存在多个地址则用逗号分隔。
   admin-addresses: http://localhost:6076/job
   # 执行器通讯TOKEN:非空时启用

+ 3 - 0
SERVER/ChickenFarmV3/vb-common/vb-common-core/src/main/java/cn/vber/common/core/service/ChickenSopService.java

@@ -1,5 +1,8 @@
 package cn.vber.common.core.service;
 
+import java.util.List;
+
 public interface ChickenSopService {
     String querySopNameByChickenId(Long chickenId, String sopType);
+
 }

+ 23 - 5
SERVER/ChickenFarmV3/vb-common/vb-common-core/src/main/java/cn/vber/common/core/utils/ChickenCalcUtils.java

@@ -7,15 +7,33 @@ import java.util.Date;
 
 public class ChickenCalcUtils {
     /**
-     * 计算鸡的年龄
-     * @param date
+     * 根据出生日期计算鸡当前的年龄
+     * @param hatchDate
      * @return
      */
-    public static int calcChickenAge(Date date){
-        if(date == null){
+    public static int calcChickenAge(Date hatchDate){
+        if(hatchDate == null){
             return 0;
         }
-        return Math.toIntExact(DateUtil.between(date, new Date(), DateUnit.DAY) + 1);
+        return Math.toIntExact(DateUtil.between(hatchDate, new Date(), DateUnit.DAY) + 1);
+    }
+    /**
+     * 根据出生日期到指定的日期计算鸡当前的年龄
+     * @param date 指定日期
+     * @param hatchDate  出生日期
+     * @return 鸡日龄
+     */
+    public static int calcChickenAge(Date date, Date hatchDate){
+        if(date == null || hatchDate == null){
+            return 0;
+        }
+        if(date.before(hatchDate)){
+            return 0;
+        }
+        if(date.equals(hatchDate)){
+            return 1;
+        }
+        return Math.toIntExact(DateUtil.between(hatchDate,date, DateUnit.DAY) + 1);
     }
 
 }

+ 41 - 0
SERVER/ChickenFarmV3/vb-common/vb-common-core/src/main/java/cn/vber/common/core/utils/DateUtils.java

@@ -8,6 +8,7 @@ import java.lang.management.ManagementFactory;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.time.*;
+import java.util.Calendar;
 import java.util.Date;
 import java.util.concurrent.TimeUnit;
 
@@ -297,4 +298,44 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
         }
     }
 
+    /**
+     * 根据传入的年、月、日返回一个Date对象
+     *
+     * @param year  年份
+     * @param month 月份 (1-12)
+     * @param day   日期 (1-31)
+     * @return Date对象,表示指定年月日的0点0分0秒
+     * @throws IllegalArgumentException 当参数不合法时抛出异常
+     */
+    public static Date createDate(int year, int month, int day) {
+        // 参数校验
+        if (month < 1 || month > 12) {
+            throw new IllegalArgumentException("月份必须在1-12之间");
+        }
+
+        if (day < 1 || day > 31) {
+            throw new IllegalArgumentException("日期必须在1-31之间");
+        }
+
+        Calendar calendar = Calendar.getInstance();
+        calendar.set(Calendar.YEAR, year);
+        calendar.set(Calendar.MONTH, month - 1); // Calendar中月份从0开始
+        calendar.set(Calendar.DAY_OF_MONTH, day);
+
+        // 设置时间为当天的0点0分0秒
+        calendar.set(Calendar.HOUR_OF_DAY, 0);
+        calendar.set(Calendar.MINUTE, 0);
+        calendar.set(Calendar.SECOND, 0);
+        calendar.set(Calendar.MILLISECOND, 0);
+
+        // 验证日期是否有效(例如2月30日是无效日期)
+        if (calendar.get(Calendar.YEAR) != year ||
+                calendar.get(Calendar.MONTH) != (month - 1) ||
+                calendar.get(Calendar.DAY_OF_MONTH) != day) {
+            throw new IllegalArgumentException("无效的日期:" + year + "-" + month + "-" + day);
+        }
+
+        return calendar.getTime();
+    }
+
 }

+ 1 - 1
SERVER/ChickenFarmV3/vb-extend/vb-job-admin/src/main/resources/application-dev.yml

@@ -16,7 +16,7 @@ spring:
   datasource:
     type: com.zaxxer.hikari.HikariDataSource
     driver-class-name: com.mysql.cj.jdbc.Driver
-    url: jdbc:mysql://192.168.0.104:3316/ChickenFarm?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&serverTimezone=Asia/Shanghai
+    url: jdbc:mysql://192.168.0.104:3316/ChickenFarmDB_DEV?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&serverTimezone=Asia/Shanghai
     username: root
     password: 123456
     hikari:

+ 10 - 0
SERVER/ChickenFarmV3/vb-modules/vb-base/src/main/java/cn/vber/base/constant/CommonConstant.java

@@ -0,0 +1,10 @@
+package cn.vber.base.constant;
+
+public class CommonConstant {
+
+    public static final String CULL_LEG_DISEASE_DICT_VALUE = "1";
+    public static final String CULL_ASCITES_DICT_VALUE = "2"  ;
+    public static final String CULL_BACTERIAL_DICT_VALUE = "3";
+    public static final String CULL_TRAUMA_DICT_VALUE = "4";
+    public static final String CULL_OTHER_DICT_VALUE = "5";
+}

+ 22 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/controller/BatchController.java

@@ -3,8 +3,12 @@
 package cn.vber.breeding.controller;
 
 import java.util.List;
+import java.util.Objects;
 
+import cn.vber.base.enums.BatchStatusEnum;
+import cn.vber.breeding.domain.Batch;
 import cn.vber.breeding.domain.bo.batchSop.CullBatchBo;
+import cn.vber.common.core.utils.MapstructUtils;
 import lombok.RequiredArgsConstructor;
 import jakarta.servlet.http.HttpServletResponse;
 import jakarta.validation.constraints.*;
@@ -110,6 +114,24 @@ public class BatchController extends BaseController {
     public R<Void> cull(@RequestBody CullBatchBo bo) {
         return toAjax(batchService.cull(bo));
     }
+    @SaCheckPermission("breeding:batch:edit")
+    @Log(title = "批次信息", businessType = BusinessType.UPDATE)
+    @GetMapping("/start/{batchNum}")
+    public R<Void> startBatch(@PathVariable  String batchNum) {
+        BatchVo batchVo = this.batchService.queryById(batchNum);
+        if(batchVo == null){
+            return R.fail("批次不存在");
+        }
+        Batch batch = MapstructUtils.convert(batchVo, Batch.class);
+        if(batch == null){
+            return R.fail("批次状态异常");
+        }
+        if(Objects.equals(batch.getStatus(), BatchStatusEnum.CREATED.getCode())){
+            int result = batchService.changeBatchStatus(batch, BatchStatusEnum.GROWING.getCode());
+            return toAjax(result);
+        }
+        return R.ok();
+    }
 }
 
           

+ 3 - 2
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/controller/CageChangeController.java

@@ -3,6 +3,7 @@
 package cn.vber.breeding.controller;
 
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.List;
 import java.util.Objects;
 
@@ -90,10 +91,10 @@ public class CageChangeController extends BaseController {
     @Log(title = "换笼管理", businessType = BusinessType.IMPORT)
     @SaCheckPermission("breeding:cageChange:add")
     @PostMapping(value = "/import", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
-    public R<Void> importData(@RequestPart("file") MultipartFile file, boolean updateSupport) throws Exception {
+    public R<Void> importData(@RequestPart("file") MultipartFile file, boolean updateSupport, Date bindDate) throws Exception {
         ExcelResult<CageChangeImportVo> result = ExcelUtil.importExcel(file.getInputStream()
                 , CageChangeImportVo.class
-                , new CageChangeImportListener(updateSupport));
+                , new CageChangeImportListener(bindDate));
         return R.ok(result.getAnalysis());
     }
     /**

+ 19 - 1
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/controller/ChickenController.java

@@ -10,12 +10,15 @@ import java.util.Objects;
 import cn.vber.base.enums.BatchStatusEnum;
 import cn.vber.breeding.domain.Batch;
 import cn.vber.breeding.domain.bo.chicken.CullChickenBo;
+import cn.vber.breeding.domain.bo.chicken.QuerySopLogBo;
 import cn.vber.breeding.domain.vo.BatchVo;
 import cn.vber.breeding.domain.vo.excel.ChickenExportVo;
 import cn.vber.breeding.domain.vo.excel.ChickenImportVo;
+import cn.vber.breeding.domain.vo.sop.SopBindLogVo;
 import cn.vber.breeding.listener.ChickenImportListener;
 import cn.vber.breeding.mapper.BatchMapper;
 import cn.vber.breeding.service.IBatchService;
+import cn.vber.breeding.service.ISopService;
 import cn.vber.common.excel.core.ExcelResult;
 import cn.vber.common.json.utils.JsonUtils;
 import com.fasterxml.jackson.annotation.JsonFormat;
@@ -56,6 +59,7 @@ public class ChickenController extends BaseController {
 
     private final IChickenService chickenService;
     private final IBatchService batchService;
+    private final ISopService sopService;
 
     /**
      * 查询鸡只个体信息列表
@@ -163,7 +167,21 @@ public class ChickenController extends BaseController {
     public R<Void> cull(@RequestBody CullChickenBo bo){
         return toAjax(chickenService.cull(bo));
     }
-
+    @SaCheckPermission("breeding:chicken")
+    @Log(title = "个体SOP绑定记录", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @GetMapping("/querySop")
+    public List<SopBindLogVo> queryChickenSopRecord(QuerySopLogBo bo) {
+        Long chickenId = bo.getChickenId() ;
+        String batchNum = bo.getBatchNum();
+        String type = bo.getType();
+        return switch (type) {
+            case "feed" -> sopService.queryChickenFeedRecord(chickenId, batchNum);
+            case "drug" -> sopService.queryChickenDrugRecord(chickenId, batchNum);
+            case "vaccine" -> sopService.queryChickenVaccineRecord(chickenId, batchNum);
+            default -> new ArrayList<SopBindLogVo>();
+        };
+    }
 
 
 }

+ 135 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/controller/ChickenMetatarsalController.java

@@ -0,0 +1,135 @@
+
+
+package cn.vber.breeding.controller;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import cn.vber.breeding.domain.vo.excel.ChickenMetatarsalImportVo;
+import cn.vber.breeding.domain.vo.excel.ChickenWeightImportVo;
+import cn.vber.breeding.listener.ChickenMetatarsalImportListener;
+import cn.vber.breeding.listener.ChickenWeightImportListener;
+import cn.vber.common.excel.core.ExcelResult;
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import cn.vber.common.idempotent.annotation.RepeatSubmit;
+import cn.vber.common.log.annotation.Log;
+import cn.vber.common.web.core.BaseController;
+import cn.vber.common.mybatis.core.page.PageQuery;
+import cn.vber.common.core.domain.R;
+import cn.vber.common.core.validate.AddGroup;
+import cn.vber.common.core.validate.EditGroup;
+import cn.vber.common.log.enums.BusinessType;
+import cn.vber.common.excel.utils.ExcelUtil;
+import cn.vber.breeding.domain.vo.ChickenMetatarsalVo;
+import cn.vber.breeding.domain.bo.ChickenMetatarsalBo;
+import cn.vber.breeding.service.IChickenMetatarsalService;
+import cn.vber.common.mybatis.core.page.TableDataInfo;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * 跖骨长管理
+ *
+ * @author IwbY
+ * @date 2025-08-14
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/breeding/chickenMetatarsal")
+public class ChickenMetatarsalController extends BaseController {
+
+    private final IChickenMetatarsalService chickenMetatarsalService;
+
+    /**
+     * 查询跖骨长管理列表
+     */
+    @SaCheckPermission("breeding:chickenMetatarsal")
+    @GetMapping("/list")
+    public TableDataInfo<ChickenMetatarsalVo> list(ChickenMetatarsalBo bo, PageQuery pageQuery) {
+        return chickenMetatarsalService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 导出跖骨长管理列表
+     */
+    @SaCheckPermission("breeding:chickenMetatarsal:export")
+    @Log(title = "跖骨长管理", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(ChickenMetatarsalBo bo, HttpServletResponse response) {
+        List<ChickenMetatarsalVo> list = chickenMetatarsalService.queryList(bo);
+        ExcelUtil.exportExcel(list, "跖骨长管理", ChickenMetatarsalVo.class, response);
+    }
+
+    /**
+     * 获取导入模板
+     */
+    @GetMapping("/importTemplate")
+    public void importTemplate(HttpServletResponse response) {
+        ExcelUtil.exportExcel(new ArrayList<>(), "个体跖骨长数据", ChickenMetatarsalImportVo.class, response);
+    }
+
+    @Log(title = "个体跖骨长管理", businessType = BusinessType.IMPORT)
+    @SaCheckPermission("breeding:chickenMetatarsal:add")
+    @PostMapping(value = "/importData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
+    public R<Void> importData(@RequestPart("file") MultipartFile file, boolean updateSupport, Date recordDate) throws Exception {
+        ExcelResult<ChickenMetatarsalImportVo> result = ExcelUtil.importExcel(file.getInputStream()
+                , ChickenMetatarsalImportVo.class
+                , new ChickenMetatarsalImportListener(recordDate));
+        return R.ok(result.getAnalysis());
+    }
+
+    /**
+     * 获取跖骨长管理详细信息
+     *
+     * @param id 主键
+     */
+    @SaCheckPermission("breeding:chickenMetatarsal:query")
+    @GetMapping("/{id}")
+    public R<ChickenMetatarsalVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) {
+        return R.ok(chickenMetatarsalService.queryById(id));
+    }
+
+    /**
+     * 新增跖骨长管理
+     */
+    @SaCheckPermission("breeding:chickenMetatarsal:add")
+    @Log(title = "跖骨长管理", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody ChickenMetatarsalBo bo) {
+        return toAjax(chickenMetatarsalService.insertByBo(bo));
+    }
+
+    /**
+     * 修改跖骨长管理
+     */
+    @SaCheckPermission("breeding:chickenMetatarsal:edit")
+    @Log(title = "跖骨长管理", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody ChickenMetatarsalBo bo) {
+        return toAjax(chickenMetatarsalService.updateByBo(bo));
+    }
+
+    /**
+     * 删除跖骨长管理
+     *
+     * @param ids 主键串
+     */
+    @SaCheckPermission("breeding:chickenMetatarsal:remove")
+    @Log(title = "跖骨长管理", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) {
+        return toAjax(chickenMetatarsalService.deleteWithValidByIds(List.of(ids), true));
+    }
+}
+
+          
+        

+ 133 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/controller/ChickenTibiaController.java

@@ -0,0 +1,133 @@
+
+
+package cn.vber.breeding.controller;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import cn.vber.breeding.domain.vo.excel.ChickenMetatarsalImportVo;
+import cn.vber.breeding.domain.vo.excel.ChickenTibiaImportVo;
+import cn.vber.breeding.listener.ChickenMetatarsalImportListener;
+import cn.vber.breeding.listener.ChickenTibiaImportListener;
+import cn.vber.common.excel.core.ExcelResult;
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import cn.vber.common.idempotent.annotation.RepeatSubmit;
+import cn.vber.common.log.annotation.Log;
+import cn.vber.common.web.core.BaseController;
+import cn.vber.common.mybatis.core.page.PageQuery;
+import cn.vber.common.core.domain.R;
+import cn.vber.common.core.validate.AddGroup;
+import cn.vber.common.core.validate.EditGroup;
+import cn.vber.common.log.enums.BusinessType;
+import cn.vber.common.excel.utils.ExcelUtil;
+import cn.vber.breeding.domain.vo.ChickenTibiaVo;
+import cn.vber.breeding.domain.bo.ChickenTibiaBo;
+import cn.vber.breeding.service.IChickenTibiaService;
+import cn.vber.common.mybatis.core.page.TableDataInfo;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * 胫骨长管理
+ *
+ * @author IwbY
+ * @date 2025-08-14
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/breeding/chickenTibia")
+public class ChickenTibiaController extends BaseController {
+
+    private final IChickenTibiaService chickenTibiaService;
+
+    /**
+     * 查询胫骨长管理列表
+     */
+    @SaCheckPermission("breeding:chickenTibia")
+    @GetMapping("/list")
+    public TableDataInfo<ChickenTibiaVo> list(ChickenTibiaBo bo, PageQuery pageQuery) {
+        return chickenTibiaService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 导出胫骨长管理列表
+     */
+    @SaCheckPermission("breeding:chickenTibia:export")
+    @Log(title = "胫骨长管理", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(ChickenTibiaBo bo, HttpServletResponse response) {
+        List<ChickenTibiaVo> list = chickenTibiaService.queryList(bo);
+        ExcelUtil.exportExcel(list, "胫骨长管理", ChickenTibiaVo.class, response);
+    }
+    /**
+     * 获取导入模板
+     */
+    @GetMapping("/importTemplate")
+    public void importTemplate(HttpServletResponse response) {
+        ExcelUtil.exportExcel(new ArrayList<>(), "个体胫骨长数据", ChickenTibiaImportVo.class, response);
+    }
+
+    @Log(title = "个体跖骨长管理", businessType = BusinessType.IMPORT)
+    @SaCheckPermission("breeding:chickenTibia:add")
+    @PostMapping(value = "/importData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
+    public R<Void> importData(@RequestPart("file") MultipartFile file, boolean updateSupport, Date recordDate) throws Exception {
+        ExcelResult<ChickenTibiaImportVo> result = ExcelUtil.importExcel(file.getInputStream()
+                , ChickenTibiaImportVo.class
+                , new ChickenTibiaImportListener(recordDate));
+        return R.ok(result.getAnalysis());
+    }
+    /**
+     * 获取胫骨长管理详细信息
+     *
+     * @param id 主键
+     */
+    @SaCheckPermission("breeding:chickenTibia:query")
+    @GetMapping("/{id}")
+    public R<ChickenTibiaVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) {
+        return R.ok(chickenTibiaService.queryById(id));
+    }
+
+    /**
+     * 新增胫骨长管理
+     */
+    @SaCheckPermission("breeding:chickenTibia:add")
+    @Log(title = "胫骨长管理", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody ChickenTibiaBo bo) {
+        return toAjax(chickenTibiaService.insertByBo(bo));
+    }
+
+    /**
+     * 修改胫骨长管理
+     */
+    @SaCheckPermission("breeding:chickenTibia:edit")
+    @Log(title = "胫骨长管理", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody ChickenTibiaBo bo) {
+        return toAjax(chickenTibiaService.updateByBo(bo));
+    }
+
+    /**
+     * 删除胫骨长管理
+     *
+     * @param ids 主键串
+     */
+    @SaCheckPermission("breeding:chickenTibia:remove")
+    @Log(title = "胫骨长管理", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) {
+        return toAjax(chickenTibiaService.deleteWithValidByIds(List.of(ids), true));
+    }
+}
+
+          
+        

+ 158 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/controller/CoopBatchReportController.java

@@ -0,0 +1,158 @@
+
+
+package cn.vber.breeding.controller;
+
+import java.util.List;
+import java.util.Objects;
+
+import cn.vber.breeding.domain.bo.statistic.QueryStaBo;
+import cn.vber.breeding.domain.bo.statistic.QueryStaScopeParam;
+import cn.vber.breeding.domain.vo.report.CoopBatchReportDetailResult;
+import cn.vber.breeding.domain.vo.report.CoopBatchReportDetailView;
+import cn.vber.breeding.domain.vo.report.CoopBatchReportResultVo;
+import cn.vber.breeding.service.ICommonService;
+import cn.vber.breeding.service.ICoopBatchReportDetailService;
+import cn.vber.breeding.service.IStatisticsHelperService;
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import cn.vber.common.idempotent.annotation.RepeatSubmit;
+import cn.vber.common.log.annotation.Log;
+import cn.vber.common.web.core.BaseController;
+import cn.vber.common.mybatis.core.page.PageQuery;
+import cn.vber.common.core.domain.R;
+import cn.vber.common.core.validate.AddGroup;
+import cn.vber.common.core.validate.EditGroup;
+import cn.vber.common.log.enums.BusinessType;
+import cn.vber.common.excel.utils.ExcelUtil;
+import cn.vber.breeding.domain.vo.CoopBatchReportVo;
+import cn.vber.breeding.domain.bo.CoopBatchReportBo;
+import cn.vber.breeding.service.ICoopBatchReportService;
+import cn.vber.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 报表信息
+ *
+ * @author IwbY
+ * @date 2025-08-18
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@Slf4j
+@RequestMapping("/breeding/coopBatchReport")
+public class CoopBatchReportController extends BaseController {
+
+    private final ICoopBatchReportService coopBatchReportService;
+    private final IStatisticsHelperService statisticsHelperService;
+    private final ICoopBatchReportDetailService coopBatchReportDetailService;
+    private final ICommonService commonService;
+
+    /**
+     * 查询报表信息列表
+     */
+    @SaCheckPermission("breeding:coopBatchReport")
+    @GetMapping("/list")
+    public TableDataInfo<CoopBatchReportVo> list(CoopBatchReportBo bo, PageQuery pageQuery) {
+        return coopBatchReportService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 导出报表信息列表
+     */
+    @SaCheckPermission("breeding:coopBatchReport:export")
+    @Log(title = "报表信息", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(CoopBatchReportBo bo, HttpServletResponse response) {
+        List<CoopBatchReportVo> list = coopBatchReportService.queryList(bo);
+        ExcelUtil.exportExcel(list, "报表信息", CoopBatchReportVo.class, response);
+    }
+
+    /**
+     * 获取报表信息详细信息
+     *
+     * @param id 主键
+     */
+    @SaCheckPermission("breeding:coopBatchReport:query")
+    @GetMapping("/{id}")
+    public R<CoopBatchReportVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) {
+        return R.ok(coopBatchReportService.queryById(id));
+    }
+
+    /**
+     * 新增报表信息
+     */
+    @SaCheckPermission("breeding:coopBatchReport:add")
+    @Log(title = "报表信息", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody CoopBatchReportBo bo) {
+        return toAjax(coopBatchReportService.insertByBo(bo));
+    }
+
+    /**
+     * 修改报表信息
+     */
+    @SaCheckPermission("breeding:coopBatchReport:edit")
+    @Log(title = "报表信息", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody CoopBatchReportBo bo) {
+        return toAjax(coopBatchReportService.updateByBo(bo));
+    }
+
+    /**
+     * 删除报表信息
+     *
+     * @param ids 主键串
+     */
+    @SaCheckPermission("breeding:coopBatchReport:remove")
+    @Log(title = "报表信息", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) {
+        return toAjax(coopBatchReportService.deleteWithValidByIds(List.of(ids), true));
+    }
+
+    //@SaCheckPermission("breeding:coopBatchReport")
+    @GetMapping("/queryReport")
+    public R<CoopBatchReportResultVo> queryReport(QueryStaBo bo) {
+        CoopBatchReportVo coopBatchReportVo = coopBatchReportService.queryByStaParam(bo);
+        if(coopBatchReportVo == null){
+            return R.warn("未查询到数据");
+        }
+        QueryStaScopeParam param = commonService.convertQueryStaToParam(bo);
+        List<CoopBatchReportDetailResult> views =
+                coopBatchReportDetailService.queryListViewByReportId(coopBatchReportVo.getId(), param);
+
+         CoopBatchReportResultVo vo= new CoopBatchReportResultVo();
+         vo.setData(views);
+         vo.setTotalData(coopBatchReportVo);
+        return R.ok(vo);
+    }
+
+    //@SaCheckPermission("breeding:coopBatchReport:add")
+    @Log(title = "报表信息", businessType = BusinessType.INSERT)
+    @PostMapping("/create")
+    public R<Void> create(@Validated @RequestBody QueryStaBo bo) {
+        String reportCycle = bo.getReportCycle();
+        try{
+            if(Objects.equals(reportCycle, "D")){
+                statisticsHelperService.statisticDay(bo);
+            }else{
+                statisticsHelperService.statisticMonthOrYearOrQuarter(bo);
+            }
+            return R.ok();
+        }catch (Exception e){
+            log.error("创建报表失败",e);
+            return R.fail("请选择正确的报表周期");
+        }
+
+    }
+}
+
+          
+        

+ 108 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/controller/CoopBatchReportDetailController.java

@@ -0,0 +1,108 @@
+
+
+package cn.vber.breeding.controller;
+
+import java.util.List;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import cn.vber.common.idempotent.annotation.RepeatSubmit;
+import cn.vber.common.log.annotation.Log;
+import cn.vber.common.web.core.BaseController;
+import cn.vber.common.mybatis.core.page.PageQuery;
+import cn.vber.common.core.domain.R;
+import cn.vber.common.core.validate.AddGroup;
+import cn.vber.common.core.validate.EditGroup;
+import cn.vber.common.log.enums.BusinessType;
+import cn.vber.common.excel.utils.ExcelUtil;
+import cn.vber.breeding.domain.vo.CoopBatchReportDetailVo;
+import cn.vber.breeding.domain.bo.CoopBatchReportDetailBo;
+import cn.vber.breeding.service.ICoopBatchReportDetailService;
+import cn.vber.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 统计报表详情信息
+ *
+ * @author IwbY
+ * @date 2025-08-18
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/breeding/coopBatchReportDetail")
+public class CoopBatchReportDetailController extends BaseController {
+
+    private final ICoopBatchReportDetailService coopBatchReportDetailService;
+
+    /**
+     * 查询统计报表详情信息列表
+     */
+    @SaCheckPermission("breeding:coopBatchReportDetail")
+    @GetMapping("/list")
+    public TableDataInfo<CoopBatchReportDetailVo> list(CoopBatchReportDetailBo bo, PageQuery pageQuery) {
+        return coopBatchReportDetailService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 导出统计报表详情信息列表
+     */
+    @SaCheckPermission("breeding:coopBatchReportDetail:export")
+    @Log(title = "统计报表详情信息", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(CoopBatchReportDetailBo bo, HttpServletResponse response) {
+        List<CoopBatchReportDetailVo> list = coopBatchReportDetailService.queryList(bo);
+        ExcelUtil.exportExcel(list, "统计报表详情信息", CoopBatchReportDetailVo.class, response);
+    }
+
+    /**
+     * 获取统计报表详情信息详细信息
+     *
+     * @param id 主键
+     */
+    @SaCheckPermission("breeding:coopBatchReportDetail:query")
+    @GetMapping("/{id}")
+    public R<CoopBatchReportDetailVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) {
+        return R.ok(coopBatchReportDetailService.queryById(id));
+    }
+
+    /**
+     * 新增统计报表详情信息
+     */
+    @SaCheckPermission("breeding:coopBatchReportDetail:add")
+    @Log(title = "统计报表详情信息", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody CoopBatchReportDetailBo bo) {
+        return toAjax(coopBatchReportDetailService.insertByBo(bo));
+    }
+
+    /**
+     * 修改统计报表详情信息
+     */
+    @SaCheckPermission("breeding:coopBatchReportDetail:edit")
+    @Log(title = "统计报表详情信息", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody CoopBatchReportDetailBo bo) {
+        return toAjax(coopBatchReportDetailService.updateByBo(bo));
+    }
+
+    /**
+     * 删除统计报表详情信息
+     *
+     * @param ids 主键串
+     */
+    @SaCheckPermission("breeding:coopBatchReportDetail:remove")
+    @Log(title = "统计报表详情信息", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) {
+        return toAjax(coopBatchReportDetailService.deleteWithValidByIds(List.of(ids), true));
+    }
+}
+
+          
+        

+ 0 - 132
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/controller/CoopEggDayController.java

@@ -1,132 +0,0 @@
-
-
-package cn.vber.breeding.controller;
-
-import java.util.*;
-
-import cn.hutool.core.date.DateUtil;
-import cn.vber.breeding.domain.vo.excel.Demo;
-import cn.vber.common.core.utils.DateUtils;
-import lombok.RequiredArgsConstructor;
-import jakarta.servlet.http.HttpServletResponse;
-import jakarta.validation.constraints.*;
-import cn.dev33.satoken.annotation.SaCheckPermission;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.validation.annotation.Validated;
-import cn.vber.common.idempotent.annotation.RepeatSubmit;
-import cn.vber.common.log.annotation.Log;
-import cn.vber.common.web.core.BaseController;
-import cn.vber.common.mybatis.core.page.PageQuery;
-import cn.vber.common.core.domain.R;
-import cn.vber.common.core.validate.AddGroup;
-import cn.vber.common.core.validate.EditGroup;
-import cn.vber.common.log.enums.BusinessType;
-import cn.vber.common.excel.utils.ExcelUtil;
-import cn.vber.breeding.domain.vo.CoopEggDayVo;
-import cn.vber.breeding.domain.bo.CoopEggDayBo;
-import cn.vber.breeding.service.ICoopEggDayService;
-import cn.vber.common.mybatis.core.page.TableDataInfo;
-
-/**
- * 鸡舍日产蛋记录
- *
- * @author IwbY
- * @date 2025-07-31
- */
-@Validated
-@RequiredArgsConstructor
-@RestController
-@RequestMapping("/breeding/coopEggDay")
-public class CoopEggDayController extends BaseController {
-
-    private final ICoopEggDayService coopEggDayService;
-
-    /**
-     * 查询鸡舍日产蛋记录列表
-     */
-    @SaCheckPermission("breeding:coopEggDay")
-    @GetMapping("/list")
-    public TableDataInfo<CoopEggDayVo> list(CoopEggDayBo bo, PageQuery pageQuery) {
-        return coopEggDayService.queryPageList(bo, pageQuery);
-    }
-
-    /**
-     * 导出鸡舍日产蛋记录列表
-     */
-    @SaCheckPermission("breeding:coopEggDay:export")
-    @Log(title = "鸡舍日产蛋记录", businessType = BusinessType.EXPORT)
-    @PostMapping("/export")
-    public void export(CoopEggDayBo bo, HttpServletResponse response) {
-        List<CoopEggDayVo> list = coopEggDayService.queryList(bo);
-        ExcelUtil.exportExcel(list, "鸡舍日产蛋记录", CoopEggDayVo.class, response);
-    }
-
-    @SaCheckPermission("breeding:coopEggDay")
-    @PostMapping(value = "export2")
-    public void export2(CoopEggDayBo bo, HttpServletResponse response) {
-//       List<Demo> list = new ArrayList<Demo>();
-//        for (int i = 0; i < 10; i++) {
-//            Demo demo = new Demo();
-//            demo.setCoopName("鸡舍"+ i);
-//            demo.setCount1(10+i);
-//            demo.setCount2(20+i);
-//            demo.setCount3(30+i);
-//            demo.setCount4(40+i);
-//            demo.setCount(demo.getCount1()+demo.getCount2()+demo.getCount3()+demo.getCount4());
-//            list.add(demo);
-//        }
-//        Map<String, Object> data = new HashMap<>();
-//        data.put("egg", list);
-//        data.put("date", DateUtil.format(new Date(), "yyyy-MM-dd"));
-//        ExcelUtil.exportTemplateMultiList(data, "鸡舍日产蛋记录", "excel/test.xlsx", response);
-
-    }
-
-    /**
-     * 获取鸡舍日产蛋记录详细信息
-     *
-     * @param id 主键
-     */
-    @SaCheckPermission("breeding:coopEggDay:query")
-    @GetMapping("/{id}")
-    public R<CoopEggDayVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) {
-        return R.ok(coopEggDayService.queryById(id));
-    }
-
-    /**
-     * 新增鸡舍日产蛋记录
-     */
-    @SaCheckPermission("breeding:coopEggDay:add")
-    @Log(title = "鸡舍日产蛋记录", businessType = BusinessType.INSERT)
-    @RepeatSubmit()
-    @PostMapping()
-    public R<Void> add(@Validated(AddGroup.class) @RequestBody CoopEggDayBo bo) {
-        return toAjax(coopEggDayService.insertByBo(bo));
-    }
-
-    /**
-     * 修改鸡舍日产蛋记录
-     */
-    @SaCheckPermission("breeding:coopEggDay:edit")
-    @Log(title = "鸡舍日产蛋记录", businessType = BusinessType.UPDATE)
-    @RepeatSubmit()
-    @PutMapping()
-    public R<Void> edit(@Validated(EditGroup.class) @RequestBody CoopEggDayBo bo) {
-        return toAjax(coopEggDayService.updateByBo(bo));
-    }
-
-    /**
-     * 删除鸡舍日产蛋记录
-     *
-     * @param ids 主键串
-     */
-    @SaCheckPermission("breeding:coopEggDay:remove")
-    @Log(title = "鸡舍日产蛋记录", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{ids}")
-    public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) {
-        return toAjax(coopEggDayService.deleteWithValidByIds(List.of(ids), true));
-    }
-}
-
-          
-        

+ 5 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/CageChange.java

@@ -56,6 +56,11 @@ public class CageChange extends BaseEntity {
      */
     private Integer status;
 
+    /**
+     * 是否跨鸡舍(0:不跨鸡舍, 1:跨鸡舍)
+     */
+    private Integer crossCoop;
+
     /**
      * 备注
      */

+ 6 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/ChickenCoop.java

@@ -39,6 +39,12 @@ public class ChickenCoop extends BaseEntity {
      */
     private String coopNum;
 
+    /**
+     * 鸡舍类型
+     * (1:育成舍 2:产蛋舍)
+     */
+    private Integer coopType;
+
     /**
      * 鸡舍名称
      */

+ 10 - 15
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/CoopEggDay.java → SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/ChickenMetatarsal.java

@@ -12,15 +12,15 @@ import com.fasterxml.jackson.annotation.JsonFormat;
 import java.io.Serial;
 
 /**
- * 鸡舍日产蛋记录对象 f_coop_egg_day
+ * 跖骨长管理对象 f_chicken_metatarsal
  *
  * @author IwbY
- * @date 2025-07-31
+ * @date 2025-08-14
  */
 @Data
 @EqualsAndHashCode(callSuper = true)
-@TableName("f_coop_egg_day")
-public class CoopEggDay extends BaseEntity {
+@TableName("f_chicken_metatarsal")
+public class ChickenMetatarsal extends BaseEntity {
 
     @Serial
     private static final long serialVersionUID = 1L;
@@ -32,24 +32,19 @@ public class CoopEggDay extends BaseEntity {
     private Long id;
 
     /**
-     * 鸡舍ID
-     */
-    private Long coopId;
-
-    /**
-     * 蛋数量
+     *
      */
-    private Long eggCount;
+    private Long chickenId;
 
     /**
-     * 蛋类型
+     *
      */
-    private Long eggType;
+    private Date recordDate;
 
     /**
-     * 日期
+     *
      */
-    private Date layDate;
+    private Float metatarsalLength;
 
     /**
      * 备注

+ 64 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/ChickenTibia.java

@@ -0,0 +1,64 @@
+
+
+package cn.vber.breeding.domain;
+
+import cn.vber.common.mybatis.core.domain.BaseEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+import java.io.Serial;
+
+/**
+ * 胫骨长管理对象 f_chicken_tibia
+ *
+ * @author IwbY
+ * @date 2025-08-14
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("f_chicken_tibia")
+public class ChickenTibia extends BaseEntity {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     *
+     */
+    @TableId(value = "id")
+    private Long id;
+
+    /**
+     *
+     */
+    private Long chickenId;
+
+    /**
+     *
+     */
+    private Date recordDate;
+
+    /**
+     *
+     */
+    private Float tibiaLength;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+    /**
+     * 删除标志(0:未删除, 1:已删除)
+     */
+    @TableLogic
+    private String delFlag;
+
+
+}
+
+          
+        

+ 177 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/CoopBatchReport.java

@@ -0,0 +1,177 @@
+
+
+package cn.vber.breeding.domain;
+
+import cn.vber.common.mybatis.core.domain.BaseEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+
+/**
+ * 报表信息对象 f_coop_batch_report
+ *
+ * @author IwbY
+ * @date 2025-08-18
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("f_coop_batch_report")
+public class CoopBatchReport extends BaseEntity {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     *
+     */
+    @TableId(value = "id")
+    private String id;
+
+    /**
+     *
+     */
+    private String title;
+
+    /**
+     * 统计周期 (年:Y  月:M 日:D 季:Q)
+     */
+    private String reportCycle;
+
+    /**
+     * coop|egg (统计育成舍或产蛋舍)
+     */
+    private String reportType;
+
+    /**
+     * 年
+     */
+    private Integer year;
+
+    /**
+     * 月
+     */
+    private Integer month;
+
+    /**
+     * 日
+     */
+    private Integer day;
+
+    /**
+     * 季度
+     */
+    private Integer quarter;
+
+    /**
+     * 上日存栏-公
+     */
+    private Integer lastSave0;
+
+    /**
+     * 上日存栏-母
+     */
+    private Integer lastSave1;
+
+    /**
+     * 本日存栏-公
+     */
+    private Integer save0;
+
+    /**
+     * 本日存栏-母
+     */
+    private Integer save1;
+
+    /**
+     * 本日淘汰数量-公
+     */
+    private Integer cull0;
+
+    /**
+     * 本日淘汰数量-母
+     */
+    private Integer cull1;
+
+    /**
+     * 本日转入-公
+     */
+    private Integer in0;
+
+    /**
+     * 本日转入-母
+     */
+    private Integer in1;
+
+    /**
+     * 本日转出-公
+     */
+    private Integer out0;
+
+    /**
+     * 本日转出-母
+     */
+    private Integer out1;
+
+    /**
+     * 日合格蛋数量
+     */
+    private Integer qualifiedEgg;
+
+    /**
+     * 日畸形蛋数量
+     */
+    private Integer deformedEgg;
+
+    /**
+     * 日坏蛋数
+     */
+    private Integer breakEgg;
+
+    /**
+     * 日产蛋率
+     */
+    private Float eggProductionRate;
+
+    /**
+     * 日产蛋合格率
+     */
+    private Float eggPassRate;
+
+    /**
+     * 公鸡数
+     */
+    private Integer chicken0;
+
+    /**
+     * 母鸡数
+     */
+    private Integer chicken1;
+
+    /**
+     * 存活率
+     */
+    private Float lifeRate;
+
+    /**
+     * 淘汰率
+     */
+    private Float cullRate;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+    /**
+     * 删除标志(0:未删除, 1:已删除)
+     */
+    @TableLogic
+    private String delFlag;
+
+
+}
+
+          
+        

+ 163 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/CoopBatchReportDetail.java

@@ -0,0 +1,163 @@
+
+
+package cn.vber.breeding.domain;
+
+import cn.vber.common.mybatis.core.domain.BaseEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+import java.io.Serial;
+
+/**
+ * 统计报表详情信息对象 f_coop_batch_report_detail
+ *
+ * @author IwbY
+ * @date 2025-08-18
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("f_coop_batch_report_detail")
+public class CoopBatchReportDetail extends BaseEntity {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     *
+     */
+    @TableId(value = "id")
+    private Long id;
+
+    private String reportId;
+
+    /**
+     * 鸡舍ID
+     */
+    private Long coopId;
+
+    /**
+     * 批次号
+     */
+    private String batchNum;
+
+    /**
+     * 上日存栏-公
+     */
+    private Integer lastSave0;
+
+    /**
+     * 上日存栏-母
+     */
+    private Integer lastSave1;
+
+    /**
+     * 本日存栏-公
+     */
+    private Integer save0;
+
+    /**
+     * 本日存栏-母
+     */
+    private Integer save1;
+
+    /**
+     * 本日淘汰数量-公
+     */
+    private Integer cull0;
+
+    /**
+     * 本日淘汰数量-母
+     */
+    private Integer cull1;
+
+    /**
+     * 本日转入-公
+     */
+    private Integer in0;
+
+    /**
+     * 本日转入-母
+     */
+    private Integer in1;
+
+    /**
+     * 本日转出-公
+     */
+    private Integer out0;
+
+    /**
+     * 本日转出-母
+     */
+    private Integer out1;
+
+    /**
+     * 日合格蛋数量
+     */
+    private Integer qualifiedEgg;
+
+    /**
+     * 日畸形蛋数量
+     */
+    private Integer deformedEgg;
+
+    /**
+     * 日坏蛋数
+     */
+    private Integer breakEgg;
+
+    /**
+     * 日产蛋率
+     */
+    private Float eggProductionRate;
+
+    /**
+     * 日产蛋合格率
+     */
+    private Float eggPassRate;
+
+    /**
+     * 公鸡数
+     */
+    private Integer chicken0;
+
+    /**
+     * 母鸡数
+     */
+    private Integer chicken1;
+
+    /**
+     * 淘汰率
+     */
+    private Float cullRate;
+
+    /**
+     * 存活率
+     */
+    private Float lifeRate;
+
+    /**
+     * 报表日期
+     */
+    private Date reportDate;
+
+    private String reportCycle;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+    /**
+     * 删除标志(0:未删除, 1:已删除)
+     */
+    @TableLogic
+    private String delFlag;
+
+
+}
+
+          
+        

+ 6 - 6
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/MeasureDetail.java

@@ -49,17 +49,17 @@ public class MeasureDetail extends BaseEntity {
     /**
      * 饲料量1
      */
-    private Long feedCount1;
+    private Float feedCount1;
 
     /**
      * 饲料量2
      */
-    private Long feedCount2;
+    private Float feedCount2;
 
     /**
      * 起始体重
      */
-    private Long startWeight;
+    private Float startWeight;
 
     /**
      * 起始体重日期
@@ -69,12 +69,12 @@ public class MeasureDetail extends BaseEntity {
     /**
      * 起始体重日龄
      */
-    private Long startWeightAge;
+    private Integer startWeightAge;
 
     /**
      * 结束体重
      */
-    private Long endWeight;
+    private Float endWeight;
 
     /**
      * 结束体重日期
@@ -84,7 +84,7 @@ public class MeasureDetail extends BaseEntity {
     /**
      * 结束体重日期
      */
-    private Long endWeightAge;
+    private Integer endWeightAge;
 
     /**
      * 中途体重信息

+ 4 - 1
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/bo/CageChangeBo.java

@@ -69,7 +69,10 @@ public class CageChangeBo extends BaseEntity {
      */
     //@NotNull(message = "状态(0:待处理, 1:已确认, 2:作废)不能为空", groups = { AddGroup.class, EditGroup.class })
     private Long status;
-
+    /**
+     * 是否跨鸡舍(0:不跨鸡舍, 1:跨鸡舍)
+     */
+    private Integer crossCoop;
     /**
      * 备注
      */

+ 1 - 1
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/bo/ChickenBo.java

@@ -76,7 +76,7 @@ public class ChickenBo extends BaseEntity {
     /**
      * 笼ID(关联f_chicken_cage)
      */
-    @NotNull(message = "笼ID(关联f_chicken_cage)不能为空", groups = { AddGroup.class, EditGroup.class })
+    //@NotNull(message = "笼ID(关联f_chicken_cage)不能为空", groups = { AddGroup.class, EditGroup.class })
     private Long cageId;
 
     /**

+ 2 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/bo/ChickenCoopBo.java

@@ -43,6 +43,8 @@ public class ChickenCoopBo extends BaseEntity {
      */
     private String coopName;
 
+    private Integer coopType;
+
     /**
      * 标准笼子数量
      */

+ 62 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/bo/ChickenMetatarsalBo.java

@@ -0,0 +1,62 @@
+
+
+package cn.vber.breeding.domain.bo;
+
+import cn.vber.breeding.domain.ChickenMetatarsal;
+import cn.vber.common.mybatis.core.domain.BaseEntity;
+import cn.vber.common.core.validate.AddGroup;
+import cn.vber.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 跖骨长管理业务对象 f_chicken_metatarsal
+ *
+ * @author IwbY
+ * @date 2025-08-14
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = ChickenMetatarsal.class,reverseConvertGenerate =false)
+
+public class ChickenMetatarsalBo extends BaseEntity {
+
+    /**
+     *
+     */
+    @NotNull(message = "不能为空", groups = { EditGroup.class })
+    private Long id;
+
+    /**
+     *
+     */
+    @NotNull(message = "不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long chickenId;
+
+    /**
+     *
+     */
+    @NotNull(message = "不能为空", groups = { AddGroup.class, EditGroup.class })
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date recordDate;
+
+    /**
+     *
+     */
+    @NotNull(message = "不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Float metatarsalLength;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+
+}
+
+          
+        

+ 15 - 17
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/bo/CoopEggDayBo.java → SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/bo/ChickenTibiaBo.java

@@ -2,7 +2,7 @@
 
 package cn.vber.breeding.domain.bo;
 
-import cn.vber.breeding.domain.CoopEggDay;
+import cn.vber.breeding.domain.ChickenTibia;
 import cn.vber.common.mybatis.core.domain.BaseEntity;
 import cn.vber.common.core.validate.AddGroup;
 import cn.vber.common.core.validate.EditGroup;
@@ -14,16 +14,16 @@ import java.util.Date;
 import com.fasterxml.jackson.annotation.JsonFormat;
 
 /**
- * 鸡舍日产蛋记录业务对象 f_coop_egg_day
+ * 胫骨长管理业务对象 f_chicken_tibia
  *
  * @author IwbY
- * @date 2025-07-31
+ * @date 2025-08-14
  */
 @Data
 @EqualsAndHashCode(callSuper = true)
-@AutoMapper(target = CoopEggDay.class,reverseConvertGenerate =false)
+@AutoMapper(target = ChickenTibia.class,reverseConvertGenerate =false)
 
-public class CoopEggDayBo extends BaseEntity {
+public class ChickenTibiaBo extends BaseEntity {
 
     /**
      *
@@ -32,25 +32,23 @@ public class CoopEggDayBo extends BaseEntity {
     private Long id;
 
     /**
-     * 鸡舍ID
-     */
-    private Long coopId;
-
-    /**
-     * 蛋数量
+     *
      */
-    private Long eggCount;
+    @NotNull(message = "不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long chickenId;
 
     /**
-     * 蛋类型
+     *
      */
-    private Long eggType;
+    @NotNull(message = "不能为空", groups = { AddGroup.class, EditGroup.class })
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date recordDate;
 
     /**
-     * 日期
+     *
      */
-    @JsonFormat(pattern = "yyyy-MM-dd")
-    private Date layDate;
+    @NotNull(message = "不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Float tibiaLength;
 
     /**
      * 备注

+ 183 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/bo/CoopBatchReportBo.java

@@ -0,0 +1,183 @@
+
+
+package cn.vber.breeding.domain.bo;
+
+import cn.vber.breeding.domain.CoopBatchReport;
+import cn.vber.common.mybatis.core.domain.BaseEntity;
+import cn.vber.common.core.validate.AddGroup;
+import cn.vber.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+
+/**
+ * 报表信息业务对象 f_coop_batch_report
+ *
+ * @author IwbY
+ * @date 2025-08-18
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = CoopBatchReport.class,reverseConvertGenerate =false)
+
+public class CoopBatchReportBo extends BaseEntity {
+
+    /**
+     *
+     */
+    @NotNull(message = "不能为空", groups = { EditGroup.class })
+    private String id;
+
+    /**
+     *
+     */
+    @NotBlank(message = "不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String title;
+
+    /**
+     * 统计周期 (年:Y  月:M 日:D 季:Q)
+     */
+    @NotBlank(message = "统计周期 (年:Y  月:M 日:D 季:Q)不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String reportCycle;
+
+    /**
+     * coop|egg (统计育成舍或产蛋舍)
+     */
+    @NotBlank(message = "coop|egg (统计育成舍或产蛋舍)不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String reportType;
+
+    /**
+     * 年
+     */
+    @NotNull(message = "年不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Integer year;
+
+    /**
+     * 月
+     */
+    private Integer month;
+
+    /**
+     * 日
+     */
+    private Integer day;
+
+    /**
+     * 季度
+     */
+    private Integer quarter;
+
+    /**
+     * 上日存栏-公
+     */
+    @NotNull(message = "上日存栏-公不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Integer lastSave0;
+
+    /**
+     * 上日存栏-母
+     */
+    @NotNull(message = "上日存栏-母不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Integer lastSave1;
+
+    /**
+     * 本日存栏-公
+     */
+    @NotNull(message = "本日存栏-公不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Integer save0;
+
+    /**
+     * 本日存栏-母
+     */
+    @NotNull(message = "本日存栏-母不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Integer save1;
+
+    /**
+     * 本日淘汰数量-公
+     */
+    @NotNull(message = "本日淘汰数量-公不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Integer cull0;
+
+    /**
+     * 本日淘汰数量-母
+     */
+    @NotNull(message = "本日淘汰数量-母不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Integer cull1;
+
+    /**
+     * 本日转入-公
+     */
+    private Integer in0;
+
+    /**
+     * 本日转入-母
+     */
+    private Integer in1;
+
+    /**
+     * 本日转出-公
+     */
+    private Integer out0;
+
+    /**
+     * 本日转出-母
+     */
+    private Integer out1;
+
+    /**
+     * 日合格蛋数量
+     */
+    private Integer qualifiedEgg;
+
+    /**
+     * 日畸形蛋数量
+     */
+    private Integer deformedEgg;
+
+    /**
+     * 日坏蛋数
+     */
+    private Integer breakEgg;
+
+    /**
+     * 日产蛋率
+     */
+    private Float eggProductionRate;
+
+    /**
+     * 日产蛋合格率
+     */
+    private Float eggPassRate;
+
+    /**
+     * 公鸡数
+     */
+    @NotNull(message = "公鸡数不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Integer chicken0;
+
+    /**
+     * 母鸡数
+     */
+    @NotNull(message = "母鸡数不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Integer chicken1;
+
+    /**
+     * 存活率
+     */
+    private Float lifeRate;
+
+    /**
+     * 淘汰率
+     */
+    private Float cullRate;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+
+}
+
+          
+        

+ 169 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/bo/CoopBatchReportDetailBo.java

@@ -0,0 +1,169 @@
+
+
+package cn.vber.breeding.domain.bo;
+
+import cn.vber.breeding.domain.CoopBatchReportDetail;
+import cn.vber.common.mybatis.core.domain.BaseEntity;
+import cn.vber.common.core.validate.AddGroup;
+import cn.vber.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 统计报表详情信息业务对象 f_coop_batch_report_detail
+ *
+ * @author IwbY
+ * @date 2025-08-18
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = CoopBatchReportDetail.class,reverseConvertGenerate =false)
+
+public class CoopBatchReportDetailBo extends BaseEntity {
+
+    /**
+     *
+     */
+    @NotNull(message = "不能为空", groups = { EditGroup.class })
+    private Long id;
+    /**
+     * 报表头ID
+     */
+    private String reportId;
+    /**
+     * 鸡舍ID
+     */
+    @NotNull(message = "鸡舍ID不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Long coopId;
+
+    /**
+     * 批次号
+     */
+    @NotBlank(message = "批次号不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String batchNum;
+
+    /**
+     * 上日存栏-公
+     */
+    @NotNull(message = "上日存栏-公不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Integer lastSave0;
+
+    /**
+     * 上日存栏-母
+     */
+    @NotNull(message = "上日存栏-母不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Integer lastSave1;
+
+    /**
+     * 本日存栏-公
+     */
+    @NotNull(message = "本日存栏-公不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Integer save0;
+
+    /**
+     * 本日存栏-母
+     */
+    @NotNull(message = "本日存栏-母不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Integer save1;
+
+    /**
+     * 本日淘汰数量-公
+     */
+    @NotNull(message = "本日淘汰数量-公不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Integer cull0;
+
+    /**
+     * 本日淘汰数量-母
+     */
+    @NotNull(message = "本日淘汰数量-母不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Integer cull1;
+
+    /**
+     * 本日转入-公
+     */
+    private Integer in0;
+
+    /**
+     * 本日转入-母
+     */
+    private Integer in1;
+
+    /**
+     * 本日转出-公
+     */
+    private Integer out0;
+
+    /**
+     * 本日转出-母
+     */
+    private Integer out1;
+
+    /**
+     * 日合格蛋数量
+     */
+    private Integer qualifiedEgg;
+
+    /**
+     * 日畸形蛋数量
+     */
+    private Integer deformedEgg;
+
+    /**
+     * 日坏蛋数
+     */
+    private Integer breakEgg;
+
+    /**
+     * 日产蛋率
+     */
+    private Float eggProductionRate;
+
+    /**
+     * 日产蛋合格率
+     */
+    private Float eggPassRate;
+
+    /**
+     * 公鸡数
+     */
+    @NotNull(message = "公鸡数不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Integer chicken0;
+
+    /**
+     * 母鸡数
+     */
+    @NotNull(message = "母鸡数不能为空", groups = { AddGroup.class, EditGroup.class })
+    private Integer chicken1;
+
+    /**
+     * 淘汰率
+     */
+    private Float cullRate;
+
+    /**
+     * 存活率
+     */
+    private Float lifeRate;
+
+    /**
+     * 报表日期
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date reportDate;
+
+    private String reportCycle;
+
+    /**
+     * 备注
+     */
+    private String remark;
+
+
+}
+
+          
+        

+ 6 - 6
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/bo/MeasureDetailBo.java

@@ -53,18 +53,18 @@ public class MeasureDetailBo extends BaseEntity {
      * 饲料量1
      */
     @NotNull(message = "饲料量1不能为空", groups = { AddGroup.class, EditGroup.class })
-    private Long feedCount1;
+    private Float feedCount1;
 
     /**
      * 饲料量2
      */
-    private Long feedCount2;
+    private Float feedCount2;
 
     /**
      * 起始体重
      */
     @NotNull(message = "起始体重不能为空", groups = { AddGroup.class, EditGroup.class })
-    private Long startWeight;
+    private Float startWeight;
 
     /**
      * 起始体重日期
@@ -77,12 +77,12 @@ public class MeasureDetailBo extends BaseEntity {
      * 起始体重日龄
      */
     @NotNull(message = "起始体重日龄不能为空", groups = { AddGroup.class, EditGroup.class })
-    private Long startWeightAge;
+    private Integer startWeightAge;
 
     /**
      * 结束体重
      */
-    private Long endWeight;
+    private Float endWeight;
 
     /**
      * 结束体重日期
@@ -93,7 +93,7 @@ public class MeasureDetailBo extends BaseEntity {
     /**
      * 结束体重日期
      */
-    private Long endWeightAge;
+    private Integer endWeightAge;
 
     /**
      * 中途体重信息

+ 11 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/bo/chicken/QuerySopLogBo.java

@@ -0,0 +1,11 @@
+package cn.vber.breeding.domain.bo.chicken;
+
+import lombok.Data;
+
+@Data
+public class QuerySopLogBo {
+    private Long chickenId;
+    private String batchNum;
+
+    private String type;
+}

+ 19 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/bo/statistic/QueryStaBo.java

@@ -0,0 +1,19 @@
+package cn.vber.breeding.domain.bo.statistic;
+
+import lombok.Data;
+
+@Data
+public class QueryStaBo {
+
+    private Integer year;
+
+    private Integer month;
+
+    private Integer day;
+
+    private Integer quarter;
+
+    private String coopType;
+
+    private String reportCycle;
+}

+ 32 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/bo/statistic/QueryStaScopeParam.java

@@ -0,0 +1,32 @@
+package cn.vber.breeding.domain.bo.statistic;
+
+import lombok.Data;
+
+@Data
+public class QueryStaScopeParam {
+
+    /**
+     * 开始时间
+     */
+    private String startDate;
+
+    /**
+     * 结束时间
+     */
+    private String endDate;
+
+    /**
+     * 统计周期 (年:Y  月:M 日:D 季:Q 周:W)
+     */
+    private String reportCycle;
+
+    /**
+     * coop:1|egg:2 (统计育成舍或产蛋舍)
+     */
+    private Integer coopType;
+
+    /**
+     * 鸡舍所属厂区
+     */
+    private String factory;
+}

+ 34 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/bo/statistic/QueryStaScopeParamBo.java

@@ -0,0 +1,34 @@
+package cn.vber.breeding.domain.bo.statistic;
+
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class QueryStaScopeParamBo {
+
+    /**
+     * 开始时间
+     */
+    private Date startDate;
+
+    /**
+     * 结束时间
+     */
+    private Date endDate;
+
+    /**
+     * 统计周期 (年:Y  月:M 日:D 季:Q 周:W)
+     */
+    private String reportCycle;
+
+    /**
+     * coop:1|egg:2 (统计育成舍或产蛋舍)
+     */
+    private String coopType;
+
+    /**
+     * 鸡舍所属厂区
+     */
+    private String factory;
+}

+ 5 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/CageChangeVo.java

@@ -78,6 +78,11 @@ public class CageChangeVo implements Serializable {
     @ExcelDictFormat(readConverterExp = "0=:待处理,,1=:已确认,,2=:作废")
     private Integer status;
 
+    /**
+     * 是否跨鸡舍(0:不跨鸡舍, 1:跨鸡舍)
+     */
+    private Integer crossCoop;
+
     /**
      * 备注
      */

+ 3 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/ChickenCoopVo.java

@@ -56,6 +56,9 @@ public class ChickenCoopVo implements Serializable {
     @ExcelProperty(value = "鸡舍名称")
     private String coopName;
 
+    @ExcelProperty(value = "鸡舍类型")
+    private Integer coopType;
+
     /**
      * 标准笼子数量
      */

+ 2 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/ChickenDrugVo.java

@@ -67,6 +67,8 @@ public class ChickenDrugVo implements Serializable {
     @ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
     @ExcelDictFormat(readConverterExp = "0=:已绑定,,1=:已解绑")
     private Integer status;
+
+
 }
 
           

+ 2 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/ChickenFeedVo.java

@@ -68,6 +68,8 @@ public class ChickenFeedVo implements Serializable {
     @ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
     @ExcelDictFormat(readConverterExp = "0=:已绑定,,1=:已解绑")
     private Integer status;
+
+
 }
 
           

+ 74 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/ChickenMetatarsalVo.java

@@ -0,0 +1,74 @@
+
+
+package cn.vber.breeding.domain.vo;
+
+import java.util.Date;
+
+import cn.vber.common.translation.annotation.Translation;
+import cn.vber.common.translation.constant.TransConstant;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import cn.vber.breeding.domain.ChickenMetatarsal;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import cn.vber.common.excel.annotation.ExcelDictFormat;
+import cn.vber.common.excel.convert.ExcelDictConvert;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+
+/**
+ * 跖骨长管理视图对象 f_chicken_metatarsal
+ *
+ * @author IwbY
+ * @date 2025-08-14
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = ChickenMetatarsal.class)
+
+public class ChickenMetatarsalVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     *
+     */
+    @ExcelProperty(value = "")
+    private Long id;
+
+    /**
+     *
+     */
+    @ExcelProperty(value = "")
+    private Long chickenId;
+    @Translation(type = TransConstant.CHICKEN_ID_TO_OTHER_INFO,mapper = "chickenId",other = "wing_num")
+    private String wingTagNum;
+
+    /**
+     *
+     */
+    @ExcelProperty(value = "")
+    private Date recordDate;
+
+    /**
+     *
+     */
+    @ExcelProperty(value = "")
+    private Float metatarsalLength;
+
+    /**
+     * 备注
+     */
+    @ExcelProperty(value = "备注")
+    private String remark;
+
+
+}
+
+          
+        

+ 19 - 22
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/CoopEggDayVo.java → SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/ChickenTibiaVo.java

@@ -3,8 +3,11 @@
 package cn.vber.breeding.domain.vo;
 
 import java.util.Date;
+
+import cn.vber.common.translation.annotation.Translation;
+import cn.vber.common.translation.constant.TransConstant;
 import com.fasterxml.jackson.annotation.JsonFormat;
-import cn.vber.breeding.domain.CoopEggDay;
+import cn.vber.breeding.domain.ChickenTibia;
 import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
 import cn.idev.excel.annotation.ExcelProperty;
 import cn.vber.common.excel.annotation.ExcelDictFormat;
@@ -18,16 +21,16 @@ import java.util.Date;
 
 
 /**
- * 鸡舍日产蛋记录视图对象 f_coop_egg_day
+ * 胫骨长管理视图对象 f_chicken_tibia
  *
  * @author IwbY
- * @date 2025-07-31
+ * @date 2025-08-14
  */
 @Data
 @ExcelIgnoreUnannotated
-@AutoMapper(target = CoopEggDay.class)
+@AutoMapper(target = ChickenTibia.class)
 
-public class CoopEggDayVo implements Serializable {
+public class ChickenTibiaVo implements Serializable {
 
     @Serial
     private static final long serialVersionUID = 1L;
@@ -39,29 +42,23 @@ public class CoopEggDayVo implements Serializable {
     private Long id;
 
     /**
-     * 鸡舍ID
-     */
-    @ExcelProperty(value = "鸡舍ID")
-    private Long coopId;
-
-    /**
-     * 蛋数量
+     *
      */
-    @ExcelProperty(value = "蛋数量")
-    private Long eggCount;
-
+    @ExcelProperty(value = "")
+    private Long chickenId;
+    @Translation(type = TransConstant.CHICKEN_ID_TO_OTHER_INFO,mapper = "chickenId",other = "wing_num")
+    private String wingTagNum;
     /**
-     * 蛋类型
+     *
      */
-    @ExcelProperty(value = "蛋类型", converter = ExcelDictConvert.class)
-    @ExcelDictFormat(dictType = "breeding_egg_type")
-    private Long eggType;
+    @ExcelProperty(value = "")
+    private Date recordDate;
 
     /**
-     * 日期
+     *
      */
-    @ExcelProperty(value = "日期")
-    private Date layDate;
+    @ExcelProperty(value = "")
+    private Float tibiaLength;
 
     /**
      * 备注

+ 2 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/ChickenVaccineVo.java

@@ -68,6 +68,8 @@ public class ChickenVaccineVo implements Serializable {
     @ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
     @ExcelDictFormat(readConverterExp = "0=:已绑定,,1=:已解绑")
     private Integer status;
+
+
 }
 
           

+ 184 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/CoopBatchReportDetailVo.java

@@ -0,0 +1,184 @@
+
+
+package cn.vber.breeding.domain.vo;
+
+import java.util.Date;
+import cn.vber.breeding.domain.CoopBatchReportDetail;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+
+/**
+ * 统计报表详情信息视图对象 f_coop_batch_report_detail
+ *
+ * @author IwbY
+ * @date 2025-08-18
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = CoopBatchReportDetail.class)
+
+public class CoopBatchReportDetailVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     *
+     */
+    @ExcelProperty(value = "")
+    private Long id;
+    /**
+     * 统计报表头ID
+     */
+    private String reportId;
+    /**
+     * 鸡舍ID
+     */
+    @ExcelProperty(value = "鸡舍ID")
+    private Long coopId;
+
+    /**
+     * 批次号
+     */
+    @ExcelProperty(value = "批次号")
+    private String batchNum;
+
+    /**
+     * 上日存栏-公
+     */
+    @ExcelProperty(value = "上日存栏-公")
+    private Integer lastSave0;
+
+    /**
+     * 上日存栏-母
+     */
+    @ExcelProperty(value = "上日存栏-母")
+    private Integer lastSave1;
+
+    /**
+     * 本日存栏-公
+     */
+    @ExcelProperty(value = "本日存栏-公")
+    private Integer save0;
+
+    /**
+     * 本日存栏-母
+     */
+    @ExcelProperty(value = "本日存栏-母")
+    private Integer save1;
+
+    /**
+     * 本日淘汰数量-公
+     */
+    @ExcelProperty(value = "本日淘汰数量-公")
+    private Integer cull0;
+
+    /**
+     * 本日淘汰数量-母
+     */
+    @ExcelProperty(value = "本日淘汰数量-母")
+    private Integer cull1;
+
+    /**
+     * 本日转入-公
+     */
+    @ExcelProperty(value = "本日转入-公")
+    private Integer in0;
+
+    /**
+     * 本日转入-母
+     */
+    @ExcelProperty(value = "本日转入-母")
+    private Integer in1;
+
+    /**
+     * 本日转出-公
+     */
+    @ExcelProperty(value = "本日转出-公")
+    private Integer out0;
+
+    /**
+     * 本日转出-母
+     */
+    @ExcelProperty(value = "本日转出-母")
+    private Integer out1;
+
+    /**
+     * 日合格蛋数量
+     */
+    @ExcelProperty(value = "日合格蛋数量")
+    private Integer qualifiedEgg;
+
+    /**
+     * 日畸形蛋数量
+     */
+    @ExcelProperty(value = "日畸形蛋数量")
+    private Integer deformedEgg;
+
+    /**
+     * 日坏蛋数
+     */
+    @ExcelProperty(value = "日坏蛋数")
+    private Integer breakEgg;
+
+    /**
+     * 日产蛋率
+     */
+    @ExcelProperty(value = "日产蛋率")
+    private Float eggProductionRate;
+
+    /**
+     * 日产蛋合格率
+     */
+    @ExcelProperty(value = "日产蛋合格率")
+    private Float eggPassRate;
+
+    /**
+     * 公鸡数
+     */
+    @ExcelProperty(value = "公鸡数")
+    private Integer chicken0;
+
+    /**
+     * 母鸡数
+     */
+    @ExcelProperty(value = "母鸡数")
+    private Integer chicken1;
+
+    /**
+     * 淘汰率
+     */
+    @ExcelProperty(value = "淘汰率")
+    private Float cullRate;
+
+    /**
+     * 存活率
+     */
+    @ExcelProperty(value = "存活率")
+    private Float lifeRate;
+
+    /**
+     * 报表日期
+     */
+    @ExcelProperty(value = "报表日期")
+    private Date reportDate;
+
+    private String reportCycle;
+
+    /**
+     * 备注
+     */
+    @ExcelProperty(value = "备注")
+    private String remark;
+
+
+}
+
+          
+        

+ 206 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/CoopBatchReportVo.java

@@ -0,0 +1,206 @@
+
+
+package cn.vber.breeding.domain.vo;
+
+import cn.vber.breeding.domain.CoopBatchReport;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import cn.vber.common.excel.annotation.ExcelDictFormat;
+import cn.vber.common.excel.convert.ExcelDictConvert;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+
+/**
+ * 报表信息视图对象 f_coop_batch_report
+ *
+ * @author IwbY
+ * @date 2025-08-18
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = CoopBatchReport.class)
+
+public class CoopBatchReportVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     *
+     */
+    @ExcelProperty(value = "")
+    private String id;
+
+    /**
+     *
+     */
+    @ExcelProperty(value = "")
+    private String title;
+
+    /**
+     * 统计周期 (年:Y  月:M 日:D 季:Q)
+     */
+    @ExcelProperty(value = "统计周期 ", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "年=:Y,月=:M,日=:D,季=:Q")
+    private String reportCycle;
+
+    /**
+     * coop|egg (统计育成舍或产蛋舍)
+     */
+    @ExcelProperty(value = "coop|egg (统计育成舍或产蛋舍)")
+    private String reportType;
+
+    /**
+     * 年
+     */
+    @ExcelProperty(value = "年")
+    private Integer year;
+
+    /**
+     * 月
+     */
+    @ExcelProperty(value = "月")
+    private Integer month;
+
+    /**
+     * 日
+     */
+    @ExcelProperty(value = "日")
+    private Integer day;
+
+    /**
+     * 季度
+     */
+    @ExcelProperty(value = "季度")
+    private Integer quarter;
+
+    /**
+     * 上日存栏-公
+     */
+    @ExcelProperty(value = "上日存栏-公")
+    private Integer lastSave0;
+
+    /**
+     * 上日存栏-母
+     */
+    @ExcelProperty(value = "上日存栏-母")
+    private Integer lastSave1;
+
+    /**
+     * 本日存栏-公
+     */
+    @ExcelProperty(value = "本日存栏-公")
+    private Integer save0;
+
+    /**
+     * 本日存栏-母
+     */
+    @ExcelProperty(value = "本日存栏-母")
+    private Integer save1;
+
+    /**
+     * 本日淘汰数量-公
+     */
+    @ExcelProperty(value = "本日淘汰数量-公")
+    private Integer cull0;
+
+    /**
+     * 本日淘汰数量-母
+     */
+    @ExcelProperty(value = "本日淘汰数量-母")
+    private Integer cull1;
+
+    /**
+     * 本日转入-公
+     */
+    @ExcelProperty(value = "本日转入-公")
+    private Integer in0;
+
+    /**
+     * 本日转入-母
+     */
+    @ExcelProperty(value = "本日转入-母")
+    private Integer in1;
+
+    /**
+     * 本日转出-公
+     */
+    @ExcelProperty(value = "本日转出-公")
+    private Integer out0;
+
+    /**
+     * 本日转出-母
+     */
+    @ExcelProperty(value = "本日转出-母")
+    private Integer out1;
+
+    /**
+     * 日合格蛋数量
+     */
+    @ExcelProperty(value = "日合格蛋数量")
+    private Integer qualifiedEgg;
+
+    /**
+     * 日畸形蛋数量
+     */
+    @ExcelProperty(value = "日畸形蛋数量")
+    private Integer deformedEgg;
+
+    /**
+     * 日坏蛋数
+     */
+    @ExcelProperty(value = "日坏蛋数")
+    private Integer breakEgg;
+
+    /**
+     * 日产蛋率
+     */
+    @ExcelProperty(value = "日产蛋率")
+    private Float eggProductionRate;
+
+    /**
+     * 日产蛋合格率
+     */
+    @ExcelProperty(value = "日产蛋合格率")
+    private Float eggPassRate;
+
+    /**
+     * 公鸡数
+     */
+    @ExcelProperty(value = "公鸡数")
+    private Integer chicken0;
+
+    /**
+     * 母鸡数
+     */
+    @ExcelProperty(value = "母鸡数")
+    private Integer chicken1;
+
+    /**
+     * 存活率
+     */
+    @ExcelProperty(value = "存活率")
+    private Float lifeRate;
+
+    /**
+     * 淘汰率
+     */
+    @ExcelProperty(value = "淘汰率")
+    private Float cullRate;
+
+    /**
+     * 备注
+     */
+    @ExcelProperty(value = "备注")
+    private String remark;
+
+
+}
+
+          
+        

+ 21 - 6
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/MeasureDetailVo.java

@@ -4,6 +4,8 @@ package cn.vber.breeding.domain.vo;
 
 import java.util.Date;
 
+import cn.hutool.core.util.StrUtil;
+import cn.vber.common.json.utils.JsonUtils;
 import cn.vber.common.translation.annotation.Translation;
 import cn.vber.common.translation.constant.TransConstant;
 import com.fasterxml.jackson.annotation.JsonFormat;
@@ -14,10 +16,12 @@ import cn.vber.common.excel.annotation.ExcelDictFormat;
 import cn.vber.common.excel.convert.ExcelDictConvert;
 import io.github.linpeilie.annotations.AutoMapper;
 import lombok.Data;
+import lombok.Setter;
 
 import java.io.Serial;
 import java.io.Serializable;
 import java.util.Date;
+import java.util.List;
 
 
 /**
@@ -68,19 +72,19 @@ public class MeasureDetailVo implements Serializable {
      * 饲料量1
      */
     @ExcelProperty(value = "饲料量1")
-    private Long feedCount1;
+    private Float feedCount1;
 
     /**
      * 饲料量2
      */
     @ExcelProperty(value = "饲料量2")
-    private Long feedCount2;
+    private Float feedCount2;
 
     /**
      * 起始体重
      */
     @ExcelProperty(value = "起始体重")
-    private Long startWeight;
+    private Float startWeight;
 
     /**
      * 起始体重日期
@@ -92,13 +96,13 @@ public class MeasureDetailVo implements Serializable {
      * 起始体重日龄
      */
     @ExcelProperty(value = "起始体重日龄")
-    private Long startWeightAge;
+    private Integer startWeightAge;
 
     /**
      * 结束体重
      */
     @ExcelProperty(value = "结束体重")
-    private Long endWeight;
+    private Float endWeight;
 
     /**
      * 结束体重日期
@@ -110,7 +114,7 @@ public class MeasureDetailVo implements Serializable {
      * 结束体重日期
      */
     @ExcelProperty(value = "结束体重日期")
-    private Long endWeightAge;
+    private Integer endWeightAge;
 
     /**
      * 中途体重信息
@@ -118,6 +122,8 @@ public class MeasureDetailVo implements Serializable {
     @ExcelProperty(value = "中途体重信息")
     private String middleWeightInfo;
 
+
+
     /**
      * 笼号
      */
@@ -131,6 +137,15 @@ public class MeasureDetailVo implements Serializable {
     private String remark;
 
 
+    private List<MiddleWeightInfoVo> middleWeightInfoList;
+
+
+    public List<MiddleWeightInfoVo> getMiddleWeightInfoList(){
+        if(StrUtil.isEmpty(middleWeightInfo)){
+            return null;
+        }
+        return JsonUtils.parseArray(middleWeightInfo, MiddleWeightInfoVo.class);
+    }
 }
 
           

+ 15 - 2
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/MiddleWeightInfoVo.java

@@ -1,16 +1,27 @@
 package cn.vber.breeding.domain.vo;
 
+import lombok.AllArgsConstructor;
 import lombok.Data;
+import lombok.NoArgsConstructor;
 
 import java.io.Serial;
 import java.io.Serializable;
 import java.util.Date;
 
 @Data
+@AllArgsConstructor
+@NoArgsConstructor
 public class MiddleWeightInfoVo implements Serializable {
     @Serial
     private static final long serialVersionUID = 1L;
 
+    public MiddleWeightInfoVo(Date weightTime, Integer weightAge, float weightValue){
+        this.weightTime = weightTime;
+        this.weightAge = weightAge;
+        this.weightValue = weightValue;
+        this.createTime = new Date();
+    }
+
     /**
      * 体重日期
      */
@@ -19,12 +30,14 @@ public class MiddleWeightInfoVo implements Serializable {
     /**
      * 体重日龄
      */
-    private String weightAge;
+    private Integer weightAge;
 
     /**
      * 体重值
      */
-    private double weightValue;
+    private Float weightValue;
+
+    private Date createTime;
 
 
 }

+ 28 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/excel/ChickenMetatarsalImportVo.java

@@ -0,0 +1,28 @@
+package cn.vber.breeding.domain.vo.excel;
+
+import cn.idev.excel.annotation.ExcelIgnore;
+import cn.idev.excel.annotation.ExcelProperty;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+public class ChickenMetatarsalImportVo implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    @ExcelProperty(value = "鸡翅号")
+    private String wingTagNum;
+
+    @ExcelIgnore
+    private Long chickenId;
+
+    @ExcelProperty(value = "跖骨长(mm)")
+    private Float metatarsalLength;
+
+    //@ExcelProperty(value = "记录日期", converter = DateNumberConverter.class)
+    @ExcelIgnore
+    private Date recordDate;
+}

+ 28 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/excel/ChickenTibiaImportVo.java

@@ -0,0 +1,28 @@
+package cn.vber.breeding.domain.vo.excel;
+
+import cn.idev.excel.annotation.ExcelIgnore;
+import cn.idev.excel.annotation.ExcelProperty;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+public class ChickenTibiaImportVo implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    @ExcelProperty(value = "鸡翅号")
+    private String wingTagNum;
+
+    @ExcelIgnore
+    private Long chickenId;
+
+    @ExcelProperty(value = "胫骨长(mm)")
+    private Float tibiaLength;
+
+    //@ExcelProperty(value = "记录日期", converter = DateNumberConverter.class)
+    @ExcelIgnore
+    private Date recordDate;
+}

+ 2 - 2
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/excel/MeasureDetailImportVo.java

@@ -28,10 +28,10 @@ public class MeasureDetailImportVo  implements Serializable {
     private String wingTagNum;
 
     @ExcelProperty(value = "体重(g)")
-    private Double weight;
+    private Float weight;
 
     @ExcelProperty(value = "饲料量(g)")
-    private Double feedCount;
+    private Float feedCount;
 
     @ExcelProperty(value = "笼号")
     private String cageNum;

+ 17 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/report/CoopBatchReportDetailResult.java

@@ -0,0 +1,17 @@
+package cn.vber.breeding.domain.vo.report;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class CoopBatchReportDetailResult {
+
+    private Long coopId;
+
+    private String coopName;
+
+    private List<CoopBatchReportDetailView> data;
+
+    private CoopBatchReportDetailView total;
+}

+ 166 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/report/CoopBatchReportDetailView.java

@@ -0,0 +1,166 @@
+package cn.vber.breeding.domain.vo.report;
+
+import cn.vber.breeding.domain.CoopBatchReportDetail;
+import com.baomidou.mybatisplus.annotation.TableId;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+@AutoMapper(target = CoopBatchReportDetail.class)
+public class CoopBatchReportDetailView {
+    @TableId(value = "id")
+    private Long id;
+
+    private String reportId;
+
+    /**
+     * 鸡舍ID
+     */
+    private Long coopId;
+
+    /**
+     * 批次号
+     */
+    private String batchNum;
+
+    /**
+     * 上日存栏-公
+     */
+    private Integer lastSave0;
+
+    /**
+     * 上日存栏-母
+     */
+    private Integer lastSave1;
+
+    /**
+     * 本日存栏-公
+     */
+    private Integer save0;
+
+    /**
+     * 本日存栏-母
+     */
+    private Integer save1;
+
+    /**
+     * 本日淘汰数量-公
+     */
+    private Integer cull0;
+
+    /**
+     * 本日淘汰数量-母
+     */
+    private Integer cull1;
+
+    /**
+     * 本日转入-公
+     */
+    private Integer in0;
+
+    /**
+     * 本日转入-母
+     */
+    private Integer in1;
+
+    /**
+     * 本日转出-公
+     */
+    private Integer out0;
+
+    /**
+     * 本日转出-母
+     */
+    private Integer out1;
+
+    /**
+     * 日合格蛋数量
+     */
+    private Integer qualifiedEgg;
+
+    /**
+     * 日畸形蛋数量
+     */
+    private Integer deformedEgg;
+
+    /**
+     * 日坏蛋数
+     */
+    private Integer breakEgg;
+
+    /**
+     * 日产蛋率
+     */
+    private Float eggProductionRate;
+    private String eggProductionRateStr;
+
+    /**
+     * 日产蛋合格率
+     */
+    private Float eggPassRate;
+    private String eggPassRateStr;
+
+    /**
+     * 公鸡数
+     */
+    private Integer chicken0;
+
+    /**
+     * 母鸡数
+     */
+    private Integer chicken1;
+
+    /**
+     * 淘汰率
+     */
+    private Float cullRate;
+    private String cullRateStr;
+    /**
+     * 存活率
+     */
+    private Float lifeRate;
+    private String lifeRateStr;
+
+
+
+    /**
+     * 报表日期
+     */
+    private Date reportDate;
+
+    private String reportCycle;
+
+    private String batchName;
+    private String coopName;
+    private String coopNum;
+    private Integer coopType;
+    private Date hatchDate;
+
+    //末日龄
+    private Integer endAge;
+
+    public String getLifeRateStr(){
+        return convertFloatToStr(this.lifeRate);
+    }
+
+    public String getCullRateStr(){
+        return convertFloatToStr(this.cullRate);
+    }
+
+    public String getEggPassRateStr(){
+        return convertFloatToStr(this.eggPassRate);
+    }
+
+    public String getEggProductionRateStr(){
+        return convertFloatToStr(this.eggProductionRate);
+    }
+    private String convertFloatToStr(Float f){
+        if(f == null){
+            return "-";
+        }
+        return String.format("%.2f", f * 100) + "%";
+    }
+
+}

+ 15 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/report/CoopBatchReportResultVo.java

@@ -0,0 +1,15 @@
+package cn.vber.breeding.domain.vo.report;
+
+import cn.vber.breeding.domain.vo.CoopBatchReportVo;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class CoopBatchReportResultVo {
+
+    private List<CoopBatchReportDetailResult> data;
+
+    private CoopBatchReportVo totalData;
+
+}

+ 36 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/sop/SopBindLogVo.java

@@ -0,0 +1,36 @@
+package cn.vber.breeding.domain.vo.sop;
+
+
+import cn.idev.excel.annotation.ExcelProperty;
+import cn.vber.common.excel.annotation.ExcelDictFormat;
+import cn.vber.common.excel.convert.ExcelDictConvert;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+public class SopBindLogVo implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 批次ID(关联f_batch)
+     */
+    private String batchNum;
+
+    private Long ChickenId;
+
+    private String sopName;
+
+    private Long sopId;
+
+    private Date bindTime;
+
+    private Integer bindAge;
+
+    private Integer status;
+
+    private String typeName;
+}

+ 25 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/statistic/ChickenStatisticDayResultVo.java

@@ -0,0 +1,25 @@
+package cn.vber.breeding.domain.vo.statistic;
+
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class ChickenStatisticDayResultVo {
+
+    private Long coopId;
+
+    private String batchNum;
+
+    private Integer save0;
+
+    private Integer save1;
+
+    private Integer chicken0;
+
+    private Integer chicken1;
+
+    private Date reportDate;
+
+    private String reportCycle;
+}

+ 20 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/statistic/CoopBatchChickenStatisticResultVo.java

@@ -0,0 +1,20 @@
+package cn.vber.breeding.domain.vo.statistic;
+
+import lombok.Data;
+
+/**
+ * 统计鸡舍批次个体统计结果
+ */
+@Data
+public class CoopBatchChickenStatisticResultVo {
+
+    private Long coopId;
+
+    private String batchNum;
+
+    //公鸡/母鸡(0:公 1:母)
+    private Integer gender;
+
+    //母鸡数量
+    private Integer chickenCount;
+}

+ 16 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/statistic/CoopBatchCommonSta.java

@@ -0,0 +1,16 @@
+package cn.vber.breeding.domain.vo.statistic;
+
+import lombok.Data;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Data
+public class CoopBatchCommonSta {
+
+    private String batchNum;
+
+    private Long coopId;
+
+    private Map<String, Object> batch = new HashMap<>();
+}

+ 20 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/statistic/CoopBatchEggStatisticResultVo.java

@@ -0,0 +1,20 @@
+package cn.vber.breeding.domain.vo.statistic;
+
+import lombok.Data;
+
+/**
+ * 统计鸡舍批次产蛋数量
+ */
+@Data
+public class CoopBatchEggStatisticResultVo {
+
+    private Long coopId;
+
+    private String batchNum;
+
+    //蛋类型
+    private Integer eggType;
+    
+    //产蛋数量
+    private Integer eggCount;
+}

+ 13 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/statistic/StatisticLastDayResultDto.java

@@ -0,0 +1,13 @@
+package cn.vber.breeding.domain.vo.statistic;
+
+import lombok.Data;
+
+@Data
+public class StatisticLastDayResultDto {
+    private Long coopId;
+
+    private String batchNum;
+
+    private Integer lastSave0;
+    private Integer lastSave1;
+}

+ 86 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/statistic/StatisticTmpResultDto.java

@@ -0,0 +1,86 @@
+package cn.vber.breeding.domain.vo.statistic;
+
+import cn.vber.breeding.domain.vo.report.CoopBatchReportDetailView;
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class StatisticTmpResultDto {
+    private Long coopId;
+
+    private String batchNum;
+
+    private Integer lastSave0 = 0;
+    private Integer lastSave1 = 0;
+
+    private Integer save0 = 0;
+    private Integer save1 = 0;
+
+    private Integer cull0 = 0;
+    private Integer cull1 = 0;
+
+    private Integer in0 = 0;
+    private Integer in1 = 0;
+
+    private Integer out0 = 0;
+    private Integer out1 = 0;
+
+    private Integer chicken0 = 0;
+    private Integer chicken1 = 0;
+
+    //统计查询日期范围内母鸡每日总数之和
+    private Integer chickenAll1 = 0;
+
+    //好种蛋数量
+    private Integer eggCount0 = 0;
+    //好菜蛋数量
+    private Integer eggCount1 = 0;
+    //合格蛋数量(好种蛋+好菜蛋)
+    private Integer qualifiedEgg = 0;
+    private Integer deformedEgg = 0;
+    private Integer breakEgg = 0;
+    private Float eggProductionRate = 0F;
+    private String eggProductionRateStr= "-";
+    private Float eggPassRate = 0F;
+    private String eggPassRateStr= "-";
+
+    private Float cullRate = 0F;
+    private String cullRateStr= "-";
+    private Float lifeRate = 0F;
+    private String lifeRateStr= "-";
+
+    private Date reportDate;
+    private String reportCycle;
+
+
+    public CoopBatchReportDetailView convertDetailView(){
+        CoopBatchReportDetailView detailView = new CoopBatchReportDetailView();
+        detailView.setBatchNum(this.getBatchNum());
+        detailView.setCoopId(this.getCoopId());
+        detailView.setLastSave0(this.getLastSave0());
+        detailView.setLastSave1(this.getLastSave1());
+        detailView.setSave0(this.getSave0());
+        detailView.setSave1(this.getSave1());
+        detailView.setCull0(this.getCull0());
+        detailView.setCull1(this.getCull1());
+        detailView.setIn0(this.getIn0());
+        detailView.setIn1(this.getIn1());
+        detailView.setOut0(this.getOut0());
+        detailView.setOut1(this.getOut1());
+        detailView.setChicken0(this.getChicken0());
+        detailView.setChicken1(this.getChicken1());
+        detailView.setQualifiedEgg(this.getQualifiedEgg());
+        detailView.setDeformedEgg(this.getDeformedEgg());
+        detailView.setBreakEgg(this.getBreakEgg());
+        detailView.setEggPassRate(this.getEggPassRate());
+        detailView.setEggProductionRate(this.getEggProductionRate());
+        detailView.setLifeRate(this.getLifeRate());
+        detailView.setCullRate(this.getCullRate());
+        detailView.setEggPassRateStr(this.getEggPassRateStr());
+        detailView.setEggProductionRateStr(this.getEggProductionRateStr());
+        detailView.setLifeRateStr(this.getLifeRateStr());
+        detailView.setCullRateStr(this.getCullRateStr());
+        return detailView;
+    }
+}

+ 15 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/domain/vo/statistic/SumFemaleCountTmpDto.java

@@ -0,0 +1,15 @@
+package cn.vber.breeding.domain.vo.statistic;
+
+import lombok.Data;
+
+/**
+ * 临时存储每日母鸡总数的统计
+ */
+@Data
+public class SumFemaleCountTmpDto {
+    private Long coopId;
+
+    private String batchNum;
+
+    private Integer chickenAll1;
+}

+ 1 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/listener/BreedingEggImportListener.java

@@ -28,6 +28,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import jakarta.validation.ConstraintViolation;
 import jakarta.validation.ConstraintViolationException;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.util.*;
 

+ 14 - 5
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/listener/CageChangeImportListener.java

@@ -27,6 +27,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.List;
 import java.util.Optional;
 
@@ -35,7 +36,8 @@ public class CageChangeImportListener extends AnalysisEventListener<CageChangeIm
 
     private final IChickenService chickenService;
     private final ChickenMapper chickenMapper;
-    private final Boolean isUpdateSupport;
+    //private final Boolean isUpdateSupport;
+    private final Date bindDate;
     private final IChickenCageService chickenCageService;
     private final CageChangeMapper cageChangeMapper;
     private final ICommonService commonService;
@@ -56,8 +58,9 @@ public class CageChangeImportListener extends AnalysisEventListener<CageChangeIm
 
 
 
-    public CageChangeImportListener(Boolean isUpdateSupport){
-        this.isUpdateSupport = isUpdateSupport;
+    public CageChangeImportListener(Date bindDate){
+        //this.isUpdateSupport = isUpdateSupport;
+        this.bindDate = bindDate;
         this.chickenService = SpringUtils.getBean(IChickenService.class);
         this.chickenMapper = SpringUtils.getBean(ChickenMapper.class);
         this.chickenCageService = SpringUtils.getBean(IChickenCageService.class);
@@ -84,6 +87,9 @@ public class CageChangeImportListener extends AnalysisEventListener<CageChangeIm
 
     private void validate(CageChangeImportVo cageChangeImportVo) {
         // TODO 验证数据
+        if(this.bindDate == null || this.bindDate.after(new java.util.Date())){
+            throw new ServiceException("日期不能大于当前日期");
+        }
         //笼号,翅号不能为空!
         if (StrUtil.isEmpty(cageChangeImportVo.getTargetCageNum())
                 || StrUtil.isEmpty(cageChangeImportVo.getWingTagNum())) {
@@ -114,7 +120,6 @@ public class CageChangeImportListener extends AnalysisEventListener<CageChangeIm
 
 
     @Override
-    @Transactional(rollbackFor = Exception.class)
     public void invoke(CageChangeImportVo cageChangeImportVo, AnalysisContext analysisContext) {
         countNum++;
         try {
@@ -125,7 +130,7 @@ public class CageChangeImportListener extends AnalysisEventListener<CageChangeIm
 
             validate(cageChangeImportVo);
             CageChange entity = BeanUtil.toBean(cageChangeImportVo, CageChange.class);
-            entity.setBindTime(DateTime.now());
+            entity.setBindTime(this.bindDate);
             //判断源笼是否为空,为空直接变更笼号
             if(cageChangeImportVo.getSourceCageId()==null){
                 entity.setStatus(CageChangeStatusEnum.AUDITED.getCode());
@@ -136,6 +141,10 @@ public class CageChangeImportListener extends AnalysisEventListener<CageChangeIm
             }else{
                 entity.setStatus(CageChangeStatusEnum.CREATED.getCode());
             }
+            Boolean crossCoop = commonService.isCrossCoop(cageChangeImportVo.getSourceCageId(), cageChangeImportVo.getTargetCageId());
+            //是否是跨鸡舍
+            entity.setCrossCoop(crossCoop?1:0);
+
             importList.add(entity);
             if(importList.size() == batchSize || totalRows == countNum + 1 ){
                 int startRowNum =

+ 57 - 34
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/listener/ChickenImportListener.java

@@ -5,10 +5,7 @@ import cn.hutool.core.util.StrUtil;
 import cn.hutool.http.HtmlUtil;
 import cn.idev.excel.context.AnalysisContext;
 import cn.idev.excel.event.AnalysisEventListener;
-import cn.vber.base.enums.BatchStatusEnum;
-import cn.vber.base.enums.FamilyStatusEnum;
-import cn.vber.base.enums.WingTagStatusEnum;
-import cn.vber.base.enums.ChickenCageStatusEnum;
+import cn.vber.base.enums.*;
 import cn.vber.breeding.domain.Batch;
 import cn.vber.breeding.domain.Chicken;
 import cn.vber.breeding.domain.bo.*;
@@ -26,6 +23,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import jakarta.validation.ConstraintViolation;
 import jakarta.validation.ConstraintViolationException;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.ibatis.executor.BatchResult;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.util.ArrayList;
@@ -43,6 +41,7 @@ public class ChickenImportListener extends AnalysisEventListener<ChickenImportVo
     private final BatchVo batchVo;
     private final IWingTagService wingTagService;
     private final IChickenCageService chickenCageService;
+    private final ICommonService commonService;
     private final IFamilyService familyService;
     private final IBatchService batchService;
 
@@ -69,6 +68,7 @@ public class ChickenImportListener extends AnalysisEventListener<ChickenImportVo
         this.chickenCageService = SpringUtils.getBean(IChickenCageService.class);
         this.familyService = SpringUtils.getBean(IFamilyService.class);
         this.batchService = SpringUtils.getBean(IBatchService.class);
+        this.commonService = SpringUtils.getBean(ICommonService.class);
         initWingTagList();
         initCageList();
         initFamilyList();
@@ -100,10 +100,8 @@ public class ChickenImportListener extends AnalysisEventListener<ChickenImportVo
         chickenImportVo.setBatchNum(this.batchVo.getBatchNum());
 
         // TODO 验证数据
-
-        //笼号,翅号不能为空!
-        if (StrUtil.isEmpty(chickenImportVo.getCageNum())
-                || StrUtil.isEmpty(chickenImportVo.getWingTagNum())) {
+        //翅号不能为空!StrUtil.isEmpty(chickenImportVo.getCageNum())
+        if (StrUtil.isEmpty(chickenImportVo.getWingTagNum())) {
             throw new ServiceException("笼编号、翅号不能为空");
         }
         //不能被绑定的翅号,不能使用
@@ -119,20 +117,23 @@ public class ChickenImportListener extends AnalysisEventListener<ChickenImportVo
             }
             chickenImportVo.setFamilyId(familyVo.get().getId());
         }
-        //验证笼号是否正常!
-        Optional<ChickenCageVo> chickenCageVo = this.chickenCageList.stream().filter(chickenCage -> chickenCage.getCageNum().equals(chickenImportVo.getCageNum()))
-                .findFirst();
-        if (chickenCageVo.isEmpty()) {
-            throw new ServiceException(chickenImportVo.getCageNum()+"笼不存在或状态异常!");
+        if(!StrUtil.isEmpty(chickenImportVo.getCageNum())){
+            //验证笼号是否正常!
+            Optional<ChickenCageVo> chickenCageVo = this.chickenCageList.stream().filter(chickenCage -> chickenCage.getCageNum().equals(chickenImportVo.getCageNum()))
+                    .findFirst();
+            if (chickenCageVo.isEmpty()) {
+                throw new ServiceException(chickenImportVo.getCageNum()+"笼不存在或状态异常!");
+            }
+            chickenImportVo.setCageId(chickenCageVo.get().getId());
         }
-        chickenImportVo.setCageId(chickenCageVo.get().getId());
+
     }
     int countNum = 0;
     int batchSize = 50;
     List<Chicken> importList = new ArrayList<>();
 
     @Override
-    @Transactional(rollbackFor = Exception.class)
+    //@Transactional(rollbackFor = Exception.class)
     public void invoke(ChickenImportVo chickenImportVo, AnalysisContext analysisContext) {
         countNum++;
         try {
@@ -146,27 +147,47 @@ public class ChickenImportListener extends AnalysisEventListener<ChickenImportVo
             Chicken entity = BeanUtil.toBean(chickenImportVo, Chicken.class);
             entity.setHatchDate(this.batchVo.getHatchDate());
             entity.setStatus(ChickenCageStatusEnum.NORMAL.getCode());
-            importList.add(entity);
-            if(importList.size()==batchSize || totalRows==countNum+1 ){
-                int startRowNum =
-                        totalRows == countNum+1 ? totalRows-(countNum%batchSize):(countNum-batchSize)+1;
-                try {
-                    //开始插入的行数
-                    System.out.println("startRowNum:"+startRowNum+"---countNum:"+countNum);
-                    chickenMapper.insertBatch(importList);
-                    changeWingTagStatus(importList);//绑定翅号,更新翅号状态
-                    //全部行数执行结束后,将批次状态置为育成中
-                    if(totalRows==countNum+1 ){
-                        BatchBo batchBo = BeanUtil.toBean(this.batchVo, BatchBo.class);
-                        batchBo.setStatus(BatchStatusEnum.GROWING.getCode());
-                        this.batchService.updateByBo(batchBo);
-                    }
-                }catch (Exception e){
-                    System.out.println(StrUtil.format("第{}行开始插入数据库失败:{})",startRowNum,e.getMessage()));
-                    log.error(StrUtil.format("第{}行开始插入数据库失败:{})",startRowNum,e.getMessage()));
+            try {
+                //开始插入的行数
+                System.out.println("startRowNum:"+countNum);
+                chickenMapper.insert(entity);
+                //变更绑定的翅号状态
+                wingTagService.updateStatus(List.of(entity.getWingTagNum()), WingTagStatusEnum.BOUND.getCode());
+                //添加 cage change记录
+                if(entity.getCageId()!=null){
+                    this.commonService.addChickenCageChange(entity.getId(), entity.getCageId(), null, CageChangeStatusEnum.AUDITED.getCode());
                 }
-                importList.clear();
+                //全部行数执行结束后,将批次状态置为育成中
+//                if(totalRows==countNum+1 ){
+//                    BatchBo batchBo = BeanUtil.toBean(this.batchVo, BatchBo.class);
+//                    batchBo.setStatus(BatchStatusEnum.GROWING.getCode());
+//                    this.batchService.updateByBo(batchBo);
+//                }
+            }catch (Exception e){
+                System.out.println(StrUtil.format("第{}行开始插入数据库失败:{})",countNum,e.getMessage()));
+                log.error(StrUtil.format("第{}行开始插入数据库失败:{})",countNum,e.getMessage()));
             }
+//            importList.add(entity);
+//            if(importList.size()==batchSize || totalRows==countNum+1 ){
+//                int startRowNum =
+//                        totalRows == countNum+1 ? totalRows-(countNum%batchSize):(countNum-batchSize)+1;
+//                try {
+//                    //开始插入的行数
+//                    System.out.println("startRowNum:"+startRowNum+"---countNum:"+countNum);
+//                    chickenMapper.insertBatch(importList);
+//                    changeWingTagStatus(importList);//绑定翅号,更新翅号状态
+//                    //全部行数执行结束后,将批次状态置为育成中
+//                    if(totalRows==countNum+1 ){
+//                        BatchBo batchBo = BeanUtil.toBean(this.batchVo, BatchBo.class);
+//                        batchBo.setStatus(BatchStatusEnum.GROWING.getCode());
+//                        this.batchService.updateByBo(batchBo);
+//                    }
+//                }catch (Exception e){
+//                    System.out.println(StrUtil.format("第{}行开始插入数据库失败:{})",startRowNum,e.getMessage()));
+//                    log.error(StrUtil.format("第{}行开始插入数据库失败:{})",startRowNum,e.getMessage()));
+//                }
+//                importList.clear();
+//            }
 
         } catch (Exception e) {
             failureNum++;
@@ -180,10 +201,12 @@ public class ChickenImportListener extends AnalysisEventListener<ChickenImportVo
         }
     }
 
+
     private void changeWingTagStatus(List<Chicken> importList ) {
         List<String> wingTagNumList = importList.stream().map(Chicken::getWingTagNum).toList();
         wingTagService.updateStatus(wingTagNumList, WingTagStatusEnum.BOUND.getCode());
     }
+
     @Override
     public void doAfterAllAnalysed(AnalysisContext analysisContext) {
 

+ 152 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/listener/ChickenMetatarsalImportListener.java

@@ -0,0 +1,152 @@
+package cn.vber.breeding.listener;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.HtmlUtil;
+import cn.idev.excel.context.AnalysisContext;
+import cn.idev.excel.event.AnalysisEventListener;
+import cn.vber.breeding.domain.ChickenMetatarsal;
+import cn.vber.breeding.domain.ChickenWeight;
+import cn.vber.breeding.domain.vo.ChickenVo;
+import cn.vber.breeding.domain.vo.excel.ChickenMetatarsalImportVo;
+import cn.vber.breeding.domain.vo.excel.ChickenWeightImportVo;
+import cn.vber.breeding.mapper.ChickenMetatarsalMapper;
+import cn.vber.breeding.mapper.ChickenWeightMapper;
+import cn.vber.breeding.service.IChickenService;
+import cn.vber.common.core.exception.ServiceException;
+import cn.vber.common.core.utils.SpringUtils;
+import cn.vber.common.core.utils.StreamUtils;
+import cn.vber.common.excel.core.ExcelListener;
+import cn.vber.common.excel.core.ExcelResult;
+import jakarta.validation.ConstraintViolation;
+import jakarta.validation.ConstraintViolationException;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Optional;
+
+@Slf4j
+public class ChickenMetatarsalImportListener  extends AnalysisEventListener<ChickenMetatarsalImportVo> implements ExcelListener<ChickenMetatarsalImportVo> {
+    private final IChickenService chickenService;
+
+    private final ChickenMetatarsalMapper chickenMetatarsalMapper;
+    private final Date recordDate;
+
+    private final StringBuilder successMsg = new StringBuilder();
+    private final StringBuilder failureMsg = new StringBuilder();
+    private int successNum = 0;
+    private int failureNum = 0;
+    List<ChickenVo> chickenVos = new ArrayList<>();
+
+    public ChickenMetatarsalImportListener(  Date recordDate ) {
+        this.recordDate = recordDate;
+        this.chickenMetatarsalMapper = SpringUtils.getBean(ChickenMetatarsalMapper.class);
+        this.chickenService = SpringUtils.getBean(IChickenService.class);
+        this.chickenVos = CommonImportUtil.initChickenList(this.chickenService);
+    }
+    private void validate(ChickenMetatarsalImportVo chickenMetatarsalImportVo) {
+
+        // TODO 验证数据
+        // 添加外拉不能大于当日日期的验证
+        if (this.recordDate == null || this.recordDate.after(new Date())) {
+            throw new ServiceException("日期不能大于当前日期");
+        }
+        chickenMetatarsalImportVo.setRecordDate(new java.util.Date());
+        //不能被绑定的翅号,不能使用
+        if (chickenMetatarsalImportVo.getMetatarsalLength() == null||chickenMetatarsalImportVo.getMetatarsalLength().isNaN() ||   chickenMetatarsalImportVo.getMetatarsalLength() <= 0.0F) {
+            throw new ServiceException(chickenMetatarsalImportVo.getWingTagNum()+":体重数据异常!");
+        }
+        // 添加recordDate不能大于当日日期的验证
+//        if (chickenWeightImportVo.getRecordDate() != null && chickenWeightImportVo.getRecordDate().after(new java.util.Date())) {
+//            throw new ServiceException("记录日期不能大于当前日期");
+//        }else if (chickenWeightImportVo.getRecordDate() == null) {
+//            chickenWeightImportVo.setRecordDate(new java.util.Date());
+//        }
+        //翅号不能为空!
+        if (StrUtil.isEmpty(chickenMetatarsalImportVo.getWingTagNum())) {
+            throw new ServiceException("翅号信息不能为空");
+        }
+        Optional<ChickenVo> vo = this.chickenVos.stream().filter(chicken -> chicken
+                        .getWingTagNum()
+                        .equals(chickenMetatarsalImportVo.getWingTagNum()))
+                .findFirst();
+        if (vo.isEmpty()) {
+            throw new ServiceException("该个体不存在或状态异常!");
+        }
+        chickenMetatarsalImportVo.setChickenId(vo.get().getId());
+    }
+    int countNum = 0;
+    int batchSize = 50;
+    List<ChickenMetatarsal> importList = new ArrayList<>();
+
+
+    @Override
+    public void invoke(ChickenMetatarsalImportVo chickenMetatarsalImportVo, AnalysisContext analysisContext) {
+        countNum++;
+        try {
+            int totalRows = 0;
+            if (analysisContext.readSheetHolder() != null) {
+                totalRows = analysisContext.readSheetHolder().getApproximateTotalRowNumber();
+            }
+            validate(chickenMetatarsalImportVo);
+            ChickenMetatarsal entity = BeanUtil.toBean(chickenMetatarsalImportVo, ChickenMetatarsal.class);
+            importList.add(entity);
+            if(importList.size() == batchSize || totalRows == countNum + 1 ){
+                int startRowNum =
+                        totalRows == countNum + 1 ? totalRows-(countNum%batchSize):(countNum-batchSize)+1;
+                try {
+                    //开始插入的行数
+                    System.out.println("startRowNum:"+startRowNum+"---countNum:"+countNum);
+                    chickenMetatarsalMapper.insertBatch(importList);
+                }catch (Exception e){
+                    System.out.println(StrUtil.format("第{}行开始插入数据库失败:{})",startRowNum,e.getMessage()));
+                    log.error(StrUtil.format("第{}行开始插入数据库失败:{})",startRowNum,e.getMessage()));
+                }
+                importList.clear();
+            }
+
+        } catch (Exception e) {
+            failureNum++;
+            String msg = "<br/>第"+countNum+"行报错!<br/>" + failureNum + "、翅号 " + HtmlUtil.cleanHtmlTag(chickenMetatarsalImportVo.getWingTagNum()) + " 导入失败:";
+            String message = e.getMessage();
+            if (e instanceof ConstraintViolationException cvException) {
+                message = StreamUtils.join(cvException.getConstraintViolations(), ConstraintViolation::getMessage, ", ");
+            }
+            failureMsg.append(msg).append(message);
+            log.error(msg, e);
+        }
+    }
+
+    @Override
+    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
+
+    }
+    @Override
+    public ExcelResult<ChickenMetatarsalImportVo> getExcelResult() {
+        return new ExcelResult<>() {
+
+            @Override
+            public String getAnalysis() {
+                if (failureNum > 0) {
+                    failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
+                    throw new ServiceException(failureMsg.toString());
+                } else {
+                    successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + countNum + " 条,数据如下:");
+                }
+                return successMsg.toString();
+            }
+
+            @Override
+            public List<ChickenMetatarsalImportVo> getList() {
+                return null;
+            }
+
+            @Override
+            public List<String> getErrorList() {
+                return null;
+            }
+        };
+    }
+}

+ 149 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/listener/ChickenTibiaImportListener.java

@@ -0,0 +1,149 @@
+package cn.vber.breeding.listener;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.HtmlUtil;
+import cn.idev.excel.context.AnalysisContext;
+import cn.idev.excel.event.AnalysisEventListener;
+import cn.vber.breeding.domain.ChickenTibia;
+import cn.vber.breeding.domain.vo.ChickenVo;
+import cn.vber.breeding.domain.vo.excel.ChickenTibiaImportVo;
+import cn.vber.breeding.mapper.ChickenTibiaMapper;
+import cn.vber.breeding.service.IChickenService;
+import cn.vber.common.core.exception.ServiceException;
+import cn.vber.common.core.utils.SpringUtils;
+import cn.vber.common.core.utils.StreamUtils;
+import cn.vber.common.excel.core.ExcelListener;
+import cn.vber.common.excel.core.ExcelResult;
+import jakarta.validation.ConstraintViolation;
+import jakarta.validation.ConstraintViolationException;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Optional;
+
+@Slf4j
+public class ChickenTibiaImportListener extends AnalysisEventListener<ChickenTibiaImportVo> implements ExcelListener<ChickenTibiaImportVo> {
+    private final IChickenService chickenService;
+     
+    private final ChickenTibiaMapper chickenTibiaMapper;
+    private final Date recordDate;
+
+    private final StringBuilder successMsg = new StringBuilder();
+    private final StringBuilder failureMsg = new StringBuilder();
+    private int successNum = 0;
+    private int failureNum = 0;
+    List<ChickenVo> chickenVos = new ArrayList<>();
+
+    public ChickenTibiaImportListener(Date recordDate ) {
+        this.recordDate = recordDate;
+        this.chickenTibiaMapper = SpringUtils.getBean(ChickenTibiaMapper.class);
+        this.chickenService = SpringUtils.getBean(IChickenService.class);
+        this.chickenVos = CommonImportUtil.initChickenList(this.chickenService);
+    }
+    private void validate(ChickenTibiaImportVo chickenTibiaImportVo) {
+
+        // TODO 验证数据
+        // 添加外拉不能大于当日日期的验证
+        if (this.recordDate == null || this.recordDate.after(new Date())) {
+            throw new ServiceException("日期不能大于当前日期");
+        }
+        chickenTibiaImportVo.setRecordDate(new Date());
+        //不能被绑定的翅号,不能使用
+        if (chickenTibiaImportVo.getTibiaLength() == null||chickenTibiaImportVo.getTibiaLength().isNaN() ||   chickenTibiaImportVo.getTibiaLength() <= 0.0F) {
+            throw new ServiceException(chickenTibiaImportVo.getWingTagNum()+":体重数据异常!");
+        }
+        // 添加recordDate不能大于当日日期的验证
+//        if (chickenWeightImportVo.getRecordDate() != null && chickenWeightImportVo.getRecordDate().after(new java.util.Date())) {
+//            throw new ServiceException("记录日期不能大于当前日期");
+//        }else if (chickenWeightImportVo.getRecordDate() == null) {
+//            chickenWeightImportVo.setRecordDate(new java.util.Date());
+//        }
+        //翅号不能为空!
+        if (StrUtil.isEmpty(chickenTibiaImportVo.getWingTagNum())) {
+            throw new ServiceException("翅号信息不能为空");
+        }
+        Optional<ChickenVo> vo = this.chickenVos.stream().filter(chicken -> chicken
+                        .getWingTagNum()
+                        .equals(chickenTibiaImportVo.getWingTagNum()))
+                .findFirst();
+        if (vo.isEmpty()) {
+            throw new ServiceException("该个体不存在或状态异常!");
+        }
+        chickenTibiaImportVo.setChickenId(vo.get().getId());
+    }
+    int countNum = 0;
+    int batchSize = 50;
+    List<ChickenTibia> importList = new ArrayList<>();
+
+
+    @Override
+    public void invoke(ChickenTibiaImportVo chickenTibiaImportVo, AnalysisContext analysisContext) {
+        countNum++;
+        try {
+            int totalRows = 0;
+            if (analysisContext.readSheetHolder() != null) {
+                totalRows = analysisContext.readSheetHolder().getApproximateTotalRowNumber();
+            }
+            validate(chickenTibiaImportVo);
+            ChickenTibia entity = BeanUtil.toBean(chickenTibiaImportVo, ChickenTibia.class);
+            importList.add(entity);
+            if(importList.size() == batchSize || totalRows == countNum + 1 ){
+                int startRowNum =
+                        totalRows == countNum + 1 ? totalRows-(countNum%batchSize):(countNum-batchSize)+1;
+                try {
+                    //开始插入的行数
+                    System.out.println("startRowNum:"+startRowNum+"---countNum:"+countNum);
+                    chickenTibiaMapper.insertBatch(importList);
+                }catch (Exception e){
+                    System.out.println(StrUtil.format("第{}行开始插入数据库失败:{})",startRowNum,e.getMessage()));
+                    log.error(StrUtil.format("第{}行开始插入数据库失败:{})",startRowNum,e.getMessage()));
+                }
+                importList.clear();
+            }
+
+        } catch (Exception e) {
+            failureNum++;
+            String msg = "<br/>第"+countNum+"行报错!<br/>" + failureNum + "、翅号 " + HtmlUtil.cleanHtmlTag(chickenTibiaImportVo.getWingTagNum()) + " 导入失败:";
+            String message = e.getMessage();
+            if (e instanceof ConstraintViolationException cvException) {
+                message = StreamUtils.join(cvException.getConstraintViolations(), ConstraintViolation::getMessage, ", ");
+            }
+            failureMsg.append(msg).append(message);
+            log.error(msg, e);
+        }
+    }
+
+    @Override
+    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
+
+    }
+    @Override
+    public ExcelResult<ChickenTibiaImportVo> getExcelResult() {
+        return new ExcelResult<>() {
+
+            @Override
+            public String getAnalysis() {
+                if (failureNum > 0) {
+                    failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
+                    throw new ServiceException(failureMsg.toString());
+                } else {
+                    successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + countNum + " 条,数据如下:");
+                }
+                return successMsg.toString();
+            }
+
+            @Override
+            public List<ChickenTibiaImportVo> getList() {
+                return null;
+            }
+
+            @Override
+            public List<String> getErrorList() {
+                return null;
+            }
+        };
+    }
+}

+ 234 - 17
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/listener/MeasureDetailImportListener.java

@@ -3,23 +3,34 @@ package cn.vber.breeding.listener;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.http.HtmlUtil;
+import cn.hutool.json.JSONObject;
 import cn.idev.excel.context.AnalysisContext;
 import cn.idev.excel.event.AnalysisEventListener;
+import cn.vber.base.enums.CageChangeStatusEnum;
+import cn.vber.base.enums.ChickenCageStatusEnum;
 import cn.vber.base.enums.MeasureDetailStatusEnum;
-import cn.vber.breeding.domain.ChickenWeight;
-import cn.vber.breeding.domain.MeasureDetail;
+import cn.vber.breeding.domain.*;
+import cn.vber.breeding.domain.bo.ChickenCageBo;
+import cn.vber.breeding.domain.vo.ChickenCageVo;
 import cn.vber.breeding.domain.vo.ChickenVo;
 import cn.vber.breeding.domain.vo.MeasureDetailVo;
+import cn.vber.breeding.domain.vo.MiddleWeightInfoVo;
+import cn.vber.breeding.domain.vo.excel.CageChangeImportVo;
 import cn.vber.breeding.domain.vo.excel.ChickenWeightImportVo;
 import cn.vber.breeding.domain.vo.excel.MeasureDetailImportVo;
-import cn.vber.breeding.mapper.ChickenWeightMapper;
-import cn.vber.breeding.mapper.MeasureDetailMapper;
+import cn.vber.breeding.mapper.*;
+import cn.vber.breeding.service.IChickenCageService;
 import cn.vber.breeding.service.IChickenService;
+import cn.vber.breeding.service.ICommonService;
+import cn.vber.breeding.service.IStatisticsService;
+import cn.vber.common.core.constant.CacheNames;
 import cn.vber.common.core.exception.ServiceException;
+import cn.vber.common.core.utils.ChickenCalcUtils;
 import cn.vber.common.core.utils.SpringUtils;
 import cn.vber.common.core.utils.StreamUtils;
 import cn.vber.common.excel.core.ExcelListener;
 import cn.vber.common.excel.core.ExcelResult;
+import cn.vber.common.json.utils.JsonUtils;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import jakarta.validation.ConstraintViolation;
 import jakarta.validation.ConstraintViolationException;
@@ -30,11 +41,21 @@ import java.util.*;
 @Slf4j
 public class MeasureDetailImportListener extends AnalysisEventListener<MeasureDetailImportVo> implements ExcelListener<MeasureDetailImportVo> {
     private final IChickenService chickenService;
+    private final ChickenMapper chickenMapper;
+    private final MeasureMapper measureMapper;
     private final MeasureDetailMapper measureDetailMapper;
+    private final ChickenWeightMapper chickenWeightMapper;
+    private final BatchMapper batchMapper;
+    private final CageChangeMapper cageChangeMapper;
+    private final IChickenCageService chickenCageService;
+    private final ICommonService commonService;
+    private final IStatisticsService statisticsService;
 
     private final Date uploadDate;
     private final String measureStage;
     private final Long measureId;
+    private Batch batch;
+    private Measure measure;
 
     private final StringBuilder successMsg = new StringBuilder();
     private final StringBuilder failureMsg = new StringBuilder();
@@ -43,24 +64,71 @@ public class MeasureDetailImportListener extends AnalysisEventListener<MeasureDe
     List<ChickenVo> chickenVos = new ArrayList<>();
     //如果是中途或结束导入,先查出本次测定中所有个体的测定信息
     List<MeasureDetailVo> existDetailList = new ArrayList<>();
+    //鸡笼列表
+    List<ChickenCageVo> chickenCageList = new ArrayList<>();
 
     public MeasureDetailImportListener(Date uploadDate,String measureStage,Long measureId ) {
         this.measureId = measureId;
         this.measureStage = measureStage;
         this.uploadDate = uploadDate;
         this.measureDetailMapper = SpringUtils.getBean(MeasureDetailMapper.class);
+        this.batchMapper = SpringUtils.getBean(BatchMapper.class);
+        this.measureMapper = SpringUtils.getBean(MeasureMapper.class);
+        this.cageChangeMapper = SpringUtils.getBean(CageChangeMapper.class);
+        this.chickenMapper = SpringUtils.getBean(ChickenMapper.class);
+        this.chickenWeightMapper = SpringUtils.getBean(ChickenWeightMapper.class);
         this.chickenService = SpringUtils.getBean(IChickenService.class);
+        this.chickenCageService = SpringUtils.getBean(IChickenCageService.class);
+        this.statisticsService = SpringUtils.getBean(IStatisticsService.class);
+        this.commonService = SpringUtils.getBean(ICommonService.class);
+        initData();
+    }
+    /**
+     * 初始化数据 获取测定的批次信息和测定信息
+     */
+    private void  initData(){
         this.chickenVos = CommonImportUtil.initChickenList(this.chickenService);
         this.existDetailList = queryExistDetailList();
+        this.measure = this.measureMapper.selectOne(new LambdaQueryWrapper<>(Measure.class)
+                .eq(Measure::getId, this.measureId));
+        this.batch = this.batchMapper.selectOne(new LambdaQueryWrapper<>(Batch.class)
+                .eq(Batch::getBatchNum, this.measure.getBatchNum()));
+        this.initCageList();
     }
-
+    private void initCageList(){
+        ChickenCageBo chickenCageBo = new ChickenCageBo();
+        chickenCageBo.setStatus(ChickenCageStatusEnum.NORMAL.getCode());
+        this.chickenCageList = chickenCageService.queryList(chickenCageBo);
+    }
+    /**
+     * 查询本次测定中已存在的详情记录
+     * @return List<MeasureDetailVo>
+     */
     private List<MeasureDetailVo> queryExistDetailList(){
         return this.measureDetailMapper.selectVoList(new LambdaQueryWrapper<>(MeasureDetail.class)
                 .eq(MeasureDetail::getMeasureId,this.measureId));
     }
+
+    /**
+     * 根据详情id查询已存在的详情记录
+     * @param id
+     * @return
+     */
+    private MeasureDetail getExistDetail(Long id){
+        MeasureDetailVo measureDetailVo = existDetailList.stream().filter(detail -> detail.getId().equals(id))
+                .findFirst().orElse(null);
+        if (measureDetailVo == null) {
+            return null;
+        }
+        if(measureDetailVo.getStatus().equals(MeasureDetailStatusEnum.END.getCode())
+                || measureDetailVo.getStatus().equals(MeasureDetailStatusEnum.CULLED.getCode())){
+            throw new ServiceException("id:"+id+"该详情已结束或淘汰,请勿继续导入!");
+        }
+        return  BeanUtil.copyProperties(measureDetailVo, MeasureDetail.class);
+    }
     private void validate(MeasureDetailImportVo measureDetailImportVo) {
-        // TODO 验证数据
-        // 添加外拉不能大于当日日期的验证
+        // 验证数据
+        // 上传的日期不能大于当日日期
         if (this.uploadDate == null || this.uploadDate.after(new Date())) {
             throw new ServiceException("日期不能大于当前日期");
         }
@@ -77,6 +145,11 @@ public class MeasureDetailImportListener extends AnalysisEventListener<MeasureDe
             throw new ServiceException("该个体不存在或状态异常!");
         }
         ChickenVo chickenVo = vo.get();
+        String batchNum = chickenVo.getBatchNum();
+        //校验批次号
+        if (!this.batch.getBatchNum().equals(batchNum)) {
+            throw new ServiceException("该个体的批次号与导入批次号不一致!");
+        }
         measureDetailImportVo.setChickenId(chickenVo.getId());
         Optional<MeasureDetailVo> first = this.existDetailList.stream().filter(detail -> detail.getChickenId().equals(chickenVo.getId())).findFirst();
         if(this.measureStage.equals("middle") || this.measureStage.equals("end")){
@@ -93,22 +166,158 @@ public class MeasureDetailImportListener extends AnalysisEventListener<MeasureDe
             }
         }
     }
+
+    /**
+     * 中途或结束的记录序列化中间信息
+     * @param measureDetailImportVo 导入信息
+     * @param middleInfo 中途信息
+     * @return json字符串
+     */
+    private String serializationMiddleInfo(MeasureDetailImportVo measureDetailImportVo,String middleInfo) {
+        List<MiddleWeightInfoVo> ts = new ArrayList<>();
+        if(StrUtil.isNotEmpty(middleInfo)){
+           ts =  JsonUtils.parseArray(middleInfo, MiddleWeightInfoVo.class);
+        }
+        MiddleWeightInfoVo middleWeightInfoVo = new MiddleWeightInfoVo(this.uploadDate,
+                ChickenCalcUtils.calcChickenAge(this.uploadDate, this.batch.getHatchDate()),
+                measureDetailImportVo.getWeight());
+        ts.add(middleWeightInfoVo);
+        return JsonUtils.toJsonString(ts);
+
+    }
+
+    /**
+     * 执行换笼操作
+     * @param cageNum 笼号
+     * @param chickenId 个体id
+     */
+    private void changeCage(String cageNum,Long chickenId){
+        ChickenCageVo chickenCageVo = this.chickenCageList.stream().filter(cage -> cage.getCageNum().equals(cageNum)).findFirst().orElse(null);
+        if(chickenCageVo == null){
+            //throw new ServiceException("该笼不存在!");
+            log.error("该笼号{}不存在!", cageNum);
+            return;
+        }
+        Optional<ChickenVo> first = this.chickenVos.stream().filter(chicken -> chicken.getId().equals(chickenId)).findFirst();
+        if(first.isEmpty()){
+            throw new ServiceException("该个体不存在!");
+        }
+        ChickenVo chickenVo = first.get();
+        CageChange entity = new CageChange();
+        entity.setBindTime(this.uploadDate);
+        entity.setChickenId(chickenId);
+        if(Objects.equals(chickenCageVo.getId(), chickenVo.getCageId())){
+            return;
+        }
+        entity.setSourceCageId(chickenVo.getCageId());
+        entity.setTargetCageId(chickenCageVo.getId());
+        entity.setStatus(CageChangeStatusEnum.AUDITED.getCode());
+        //是否为同鸡舍
+        entity.setCrossCoop(this.commonService.isCrossCoop(chickenVo.getCageId(), chickenCageVo.getId())?1:0);
+        this.cageChangeMapper.insert(entity);
+        changeChickenCage(chickenVo, chickenCageVo.getId());
+    }
+
+    /**
+     * 更新个体的笼信息
+     * @param chickenVo 个体信息
+     * @param cageId 笼id
+     */
+    private void changeChickenCage(ChickenVo chickenVo, Long cageId) {
+        chickenVo.setCageId(cageId);
+        Chicken chicken = BeanUtil.copyProperties(chickenVo, Chicken.class);
+        this.chickenMapper.updateById(chicken);
+        this.commonService.clearCache(CacheNames.CHICKEN_ID_INFO);
+    }
+
+    /**
+     * 转换导入信息为实体
+     * @param measureDetailImportVo
+     * @return
+     */
     private MeasureDetail ConvertToEntity(MeasureDetailImportVo measureDetailImportVo) {
-        MeasureDetail entity = new MeasureDetail();
-        BeanUtil.copyProperties(measureDetailImportVo, entity);
         if(Objects.equals(this.measureStage, "start")){
-            entity.setCageNum(measureDetailImportVo.getCageNum());
-            //todo 执行换笼操作
-
+            MeasureDetail entity = new MeasureDetail();
+            entity.setChickenId(measureDetailImportVo.getChickenId());
+            entity.setMeasureId(this.measureId);
             entity.setStatus(MeasureDetailStatusEnum.TESTING.getCode());
+            entity.setStartWeight(measureDetailImportVo.getWeight());
+            entity.setStartWeightTime(this.uploadDate);
+            entity.setStartWeightAge(ChickenCalcUtils.calcChickenAge(this.uploadDate,this.batch.getHatchDate()));
+            entity.setFeedCount1(measureDetailImportVo.getFeedCount()==null?0:measureDetailImportVo.getFeedCount());
+            if(!StrUtil.isEmpty(measureDetailImportVo.getCageNum())){
+                entity.setCageNum(measureDetailImportVo.getCageNum());
+                //执行换笼操作
+                this.changeCage(measureDetailImportVo.getCageNum(), measureDetailImportVo.getChickenId());
+            }
+            return entity;
+        }
+        if(Objects.equals(this.measureStage, "middle")){
+            MeasureDetail entity = getExistDetail(measureDetailImportVo.getId());
+            if(entity == null){
+                throw new ServiceException("该个体没有进行开始测定!");
+            }
+            String middleInfoStr = this.serializationMiddleInfo(measureDetailImportVo, entity.getMiddleWeightInfo());
+            entity.setMiddleWeightInfo(middleInfoStr);
+            return entity;
         }
-        return entity;
+        if(Objects.equals(this.measureStage, "end")){
+            MeasureDetail entity = getExistDetail(measureDetailImportVo.getId());
+            if(entity == null){
+                throw new ServiceException("该个体没有进行开始测定!");
+            }
+            entity.setStatus(MeasureDetailStatusEnum.END.getCode());
+            entity.setEndWeight(measureDetailImportVo.getWeight());
+            entity.setEndWeightTime(this.uploadDate);
+            entity.setEndWeightAge(ChickenCalcUtils.calcChickenAge(this.uploadDate,this.batch.getHatchDate()));
+            entity.setFeedCount2(measureDetailImportVo.getFeedCount()==null?0:measureDetailImportVo.getFeedCount());
+            return entity;
+        }
+        return null;
     }
 
     int countNum = 0;
     int batchSize = 50;
     List<MeasureDetail> importList = new ArrayList<>();
 
+    /**
+     * 获取中间体重信息
+     * @param middleInfo 中间信息
+     * @return 最新的中间信息
+     */
+    private MiddleWeightInfoVo getMiddleWeightInfoVo(String middleInfo) {
+        List<MiddleWeightInfoVo> ts = JsonUtils.parseArray(middleInfo, MiddleWeightInfoVo.class);
+        //根据创建时间获取中间最新创建的中间信息
+        return ts.stream().max(Comparator.comparing(MiddleWeightInfoVo::getCreateTime))
+                .orElse(null);
+    }
+
+    /**
+     * 批量插入鸡体重信息
+     * @param list 转换后的测定数据
+     */
+    private void insertChickenWeight(List<MeasureDetail> list){
+        List<ChickenWeight> chickenWeights = new ArrayList<>();
+        for (MeasureDetail measureDetail : list) {
+            ChickenWeight chickenWeight = new ChickenWeight();
+            chickenWeight.setChickenId(measureDetail.getChickenId());
+            chickenWeight.setRecordDate(this.uploadDate);
+            if(Objects.equals(this.measureStage, "start")){
+                chickenWeight.setWeightValue(measureDetail.getStartWeight());
+            }else if (Objects.equals(this.measureStage, "middle")){
+                MiddleWeightInfoVo middleWeightInfoVo = getMiddleWeightInfoVo(measureDetail.getMiddleWeightInfo());
+                if(middleWeightInfoVo != null){
+                    chickenWeight.setWeightValue(middleWeightInfoVo.getWeightValue());
+                }
+            }else{
+                chickenWeight.setWeightValue(measureDetail.getEndWeight());
+            }
+            chickenWeights.add(chickenWeight);
+        }
+        if(!chickenWeights.isEmpty()){
+            this.chickenWeightMapper.insertBatch(chickenWeights);
+        }
+    }
 
     @Override
     public void invoke(MeasureDetailImportVo measureDetailImportVo, AnalysisContext analysisContext) {
@@ -119,7 +328,7 @@ public class MeasureDetailImportListener extends AnalysisEventListener<MeasureDe
                 totalRows = analysisContext.readSheetHolder().getApproximateTotalRowNumber();
             }
             validate(measureDetailImportVo);
-            //ChickenWeight entity = BeanUtil.toBean(chickenWeightImportVo, ChickenWeight.class);
+            MeasureDetail entity = ConvertToEntity(measureDetailImportVo);
             importList.add(entity);
             if(importList.size() == batchSize || totalRows == countNum + 1 ){
                 int startRowNum =
@@ -127,15 +336,23 @@ public class MeasureDetailImportListener extends AnalysisEventListener<MeasureDe
                 try {
                     //开始插入的行数
                     System.out.println("startRowNum:"+startRowNum+"---countNum:"+countNum);
-                    //chickenWeightMapper.insertBatch(importList);
-
+                    if(this.measureStage.equals("start")){
+                        this.measureDetailMapper.insertBatch(importList);
+                    }else{
+                        this.measureDetailMapper.updateBatchById(importList);
+                    }
+                    //插入鸡体重数据
+                    insertChickenWeight(importList);
                 }catch (Exception e){
                     System.out.println(StrUtil.format("第{}行开始插入数据库失败:{})",startRowNum,e.getMessage()));
                     log.error(StrUtil.format("第{}行开始插入数据库失败:{})",startRowNum,e.getMessage()));
                 }
                 importList.clear();
             }
-
+            //执行结束上传动作之后统计该测定批次的淘汰数量
+            if(this.measureStage.equals("end")){
+                this.statisticsService.statisticsMeasure(this.measureId);
+            }
         } catch (Exception e) {
             failureNum++;
             String msg = "<br/>第"+countNum+"行报错!<br/>" + failureNum + "、翅号 " + HtmlUtil.cleanHtmlTag(measureDetailImportVo.getWingTagNum()) + " 导入失败:";

+ 4 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/mapper/BatchFeedMapper.java

@@ -5,6 +5,8 @@ package cn.vber.breeding.mapper;
 import cn.vber.common.mybatis.core.mapper.BaseMapperPlus;
 import cn.vber.breeding.domain.BatchFeed;
 import cn.vber.breeding.domain.vo.BatchFeedVo;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.SelectProvider;
 import org.springframework.stereotype.Repository;
 
 /**
@@ -16,6 +18,8 @@ import org.springframework.stereotype.Repository;
 @Repository
 public interface BatchFeedMapper extends BaseMapperPlus<BatchFeed, BatchFeedVo> {
 
+
+
 }
 
           

+ 22 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/mapper/ChickenCoopMapper.java

@@ -2,11 +2,17 @@
 
 package cn.vber.breeding.mapper;
 
+import cn.vber.common.mybatis.annotation.DataColumn;
+import cn.vber.common.mybatis.annotation.DataPermission;
 import cn.vber.common.mybatis.core.mapper.BaseMapperPlus;
 import cn.vber.breeding.domain.ChickenCoop;
 import cn.vber.breeding.domain.vo.ChickenCoopVo;
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import org.springframework.stereotype.Repository;
 
+import java.util.List;
+
 /**
  * 鸡舍管理Mapper接口
  *
@@ -16,6 +22,22 @@ import org.springframework.stereotype.Repository;
 @Repository
 public interface ChickenCoopMapper extends BaseMapperPlus<ChickenCoop, ChickenCoopVo> {
 
+
+    @DataPermission({
+            @DataColumn(key = "orgName", value = "create_org"),
+            @DataColumn(key = "userName", value = "manager")
+    })
+    default Page<ChickenCoopVo> selectPageList(Page<ChickenCoop> page, Wrapper<ChickenCoop> queryWrapper) {
+        return this.selectVoPage(page, queryWrapper);
+    }
+
+    @DataPermission({
+            @DataColumn(key = "orgName", value = "create_org"),
+            @DataColumn(key = "userName", value = "manager")
+    })
+    default List<ChickenCoopVo> selectListVo(Wrapper<ChickenCoop> queryWrapper) {
+        return this.selectVoList(queryWrapper);
+    }
 }
 
           

+ 22 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/mapper/ChickenMetatarsalMapper.java

@@ -0,0 +1,22 @@
+
+
+package cn.vber.breeding.mapper;
+
+import cn.vber.common.mybatis.core.mapper.BaseMapperPlus;
+import cn.vber.breeding.domain.ChickenMetatarsal;
+import cn.vber.breeding.domain.vo.ChickenMetatarsalVo;
+import org.springframework.stereotype.Repository;
+
+/**
+ * 跖骨长管理Mapper接口
+ *
+ * @author IwbY
+ * @date 2025-08-14
+ */
+@Repository
+public interface ChickenMetatarsalMapper extends BaseMapperPlus<ChickenMetatarsal, ChickenMetatarsalVo> {
+
+}
+
+          
+        

+ 22 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/mapper/ChickenTibiaMapper.java

@@ -0,0 +1,22 @@
+
+
+package cn.vber.breeding.mapper;
+
+import cn.vber.common.mybatis.core.mapper.BaseMapperPlus;
+import cn.vber.breeding.domain.ChickenTibia;
+import cn.vber.breeding.domain.vo.ChickenTibiaVo;
+import org.springframework.stereotype.Repository;
+
+/**
+ * 胫骨长管理Mapper接口
+ *
+ * @author IwbY
+ * @date 2025-08-14
+ */
+@Repository
+public interface ChickenTibiaMapper extends BaseMapperPlus<ChickenTibia, ChickenTibiaVo> {
+
+}
+
+          
+        

+ 56 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/mapper/CoopBatchReportDetailMapper.java

@@ -0,0 +1,56 @@
+
+
+package cn.vber.breeding.mapper;
+
+import cn.vber.breeding.domain.bo.statistic.QueryStaScopeParam;
+import cn.vber.breeding.domain.vo.report.CoopBatchReportDetailView;
+import cn.vber.breeding.domain.vo.statistic.ChickenStatisticDayResultVo;
+import cn.vber.breeding.domain.vo.statistic.CoopBatchChickenStatisticResultVo;
+import cn.vber.breeding.domain.vo.statistic.CoopBatchEggStatisticResultVo;
+import cn.vber.common.mybatis.core.mapper.BaseMapperPlus;
+import cn.vber.breeding.domain.CoopBatchReportDetail;
+import cn.vber.breeding.domain.vo.CoopBatchReportDetailVo;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+/**
+ * 统计报表详情信息Mapper接口
+ *
+ * @author IwbY
+ * @date 2025-08-18
+ */
+@Repository
+public interface CoopBatchReportDetailMapper extends BaseMapperPlus<CoopBatchReportDetail, CoopBatchReportDetailVo> {
+
+    // and coop.coop_type = #{coopType} and coop.factory = #{factory}
+
+    //统计鸡舍中不同批次各性别的淘汰数
+    List<CoopBatchChickenStatisticResultVo> selectCullCount(QueryStaScopeParam queryScopeParam);
+
+    //统计鸡舍中不同批次各性别的鸡数量
+    List<CoopBatchChickenStatisticResultVo> selectChickenCount(QueryStaScopeParam queryScopeParam);
+
+    //统计鸡舍中不同批次各性别的转入数
+    List<CoopBatchChickenStatisticResultVo> selectChickenIn(QueryStaScopeParam queryScopeParam);
+
+    //统计鸡舍中不同批次各性别的转出数
+    List<CoopBatchChickenStatisticResultVo> selectChickenOut(QueryStaScopeParam queryScopeParam);
+
+    //从日统计详情表中查出鸡舍中不同批次各性别的日统计数
+    List<ChickenStatisticDayResultVo> selectChickenCountDay(QueryStaScopeParam queryScopeParam);
+
+    //统计鸡舍中不同批次产蛋数量
+    List<CoopBatchEggStatisticResultVo> selectStatisticEgg(QueryStaScopeParam queryScopeParam);
+
+
+
+    List<CoopBatchReportDetailView> selectCoopBatchReportDetail(@Param("report_id") String reportId, @Param("coop_type") Integer coopType);
+
+
+
+}
+
+          
+        

+ 22 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/mapper/CoopBatchReportMapper.java

@@ -0,0 +1,22 @@
+
+
+package cn.vber.breeding.mapper;
+
+import cn.vber.common.mybatis.core.mapper.BaseMapperPlus;
+import cn.vber.breeding.domain.CoopBatchReport;
+import cn.vber.breeding.domain.vo.CoopBatchReportVo;
+import org.springframework.stereotype.Repository;
+
+/**
+ * 报表信息Mapper接口
+ *
+ * @author IwbY
+ * @date 2025-08-18
+ */
+@Repository
+public interface CoopBatchReportMapper extends BaseMapperPlus<CoopBatchReport, CoopBatchReportVo> {
+
+}
+
+          
+        

+ 0 - 22
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/mapper/CoopEggDayMapper.java

@@ -1,22 +0,0 @@
-
-
-package cn.vber.breeding.mapper;
-
-import cn.vber.common.mybatis.core.mapper.BaseMapperPlus;
-import cn.vber.breeding.domain.CoopEggDay;
-import cn.vber.breeding.domain.vo.CoopEggDayVo;
-import org.springframework.stereotype.Repository;
-
-/**
- * 鸡舍日产蛋记录Mapper接口
- *
- * @author IwbY
- * @date 2025-07-31
- */
-@Repository
-public interface CoopEggDayMapper extends BaseMapperPlus<CoopEggDay, CoopEggDayVo> {
-
-}
-
-          
-        

+ 2 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/IBatchService.java

@@ -54,6 +54,8 @@ public interface IBatchService {
      * 淘汰批次信息
      */
     Boolean cull(CullBatchBo bo);
+
+    int changeBatchStatus(Batch batch, Integer status);
 }
 
           

+ 54 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/IChickenMetatarsalService.java

@@ -0,0 +1,54 @@
+
+
+package cn.vber.breeding.service;
+
+import cn.vber.breeding.domain.ChickenMetatarsal;
+import cn.vber.breeding.domain.vo.ChickenMetatarsalVo;
+import cn.vber.breeding.domain.bo.ChickenMetatarsalBo;
+import cn.vber.common.mybatis.core.page.TableDataInfo;
+import cn.vber.common.mybatis.core.page.PageQuery;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 跖骨长管理Service接口
+ *
+ * @author IwbY
+ * @date 2025-08-14
+ */
+public interface IChickenMetatarsalService {
+
+    /**
+     * 查询跖骨长管理
+     */
+    ChickenMetatarsalVo queryById(Long id);
+
+    /**
+     * 查询跖骨长管理列表
+     */
+    TableDataInfo<ChickenMetatarsalVo> queryPageList(ChickenMetatarsalBo bo, PageQuery pageQuery);
+
+    /**
+     * 查询跖骨长管理列表
+     */
+    List<ChickenMetatarsalVo> queryList(ChickenMetatarsalBo bo);
+
+    /**
+     * 新增跖骨长管理
+     */
+    Boolean insertByBo(ChickenMetatarsalBo bo);
+
+    /**
+     * 修改跖骨长管理
+     */
+    Boolean updateByBo(ChickenMetatarsalBo bo);
+
+    /**
+     * 校验并批量删除跖骨长管理信息
+     */
+    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+}
+
+          
+        

+ 54 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/IChickenTibiaService.java

@@ -0,0 +1,54 @@
+
+
+package cn.vber.breeding.service;
+
+import cn.vber.breeding.domain.ChickenTibia;
+import cn.vber.breeding.domain.vo.ChickenTibiaVo;
+import cn.vber.breeding.domain.bo.ChickenTibiaBo;
+import cn.vber.common.mybatis.core.page.TableDataInfo;
+import cn.vber.common.mybatis.core.page.PageQuery;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 胫骨长管理Service接口
+ *
+ * @author IwbY
+ * @date 2025-08-14
+ */
+public interface IChickenTibiaService {
+
+    /**
+     * 查询胫骨长管理
+     */
+    ChickenTibiaVo queryById(Long id);
+
+    /**
+     * 查询胫骨长管理列表
+     */
+    TableDataInfo<ChickenTibiaVo> queryPageList(ChickenTibiaBo bo, PageQuery pageQuery);
+
+    /**
+     * 查询胫骨长管理列表
+     */
+    List<ChickenTibiaVo> queryList(ChickenTibiaBo bo);
+
+    /**
+     * 新增胫骨长管理
+     */
+    Boolean insertByBo(ChickenTibiaBo bo);
+
+    /**
+     * 修改胫骨长管理
+     */
+    Boolean updateByBo(ChickenTibiaBo bo);
+
+    /**
+     * 校验并批量删除胫骨长管理信息
+     */
+    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+}
+
+          
+        

+ 20 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/ICommonService.java

@@ -1,5 +1,7 @@
 package cn.vber.breeding.service;
 
+import cn.vber.breeding.domain.bo.statistic.QueryStaBo;
+import cn.vber.breeding.domain.bo.statistic.QueryStaScopeParam;
 import cn.vber.breeding.domain.vo.BatchVo;
 import cn.vber.breeding.domain.vo.ChickenVo;
 import cn.vber.breeding.domain.vo.FamilyVo;
@@ -15,4 +17,22 @@ public interface ICommonService {
     FamilyVo queryFamilyByFemaleId(Long chickenId);
 
     void cancelFamilyByFemaleId(Long chickenId);
+
+    void cullMeasureDetail(Long chickenId);
+
+    Boolean isCrossCoop(Long sourceCageId, Long targetCageId);
+
+    void addChickenCageChange(Long chickenId, Long sourceCageId, Long targetCageId,Integer status);
+
+    boolean checkWingTagNumIsBind(String wingTagNum);
+
+    void changeWingStatus(String wingTagNum, Integer Status);
+
+
+    QueryStaScopeParam convertQueryStaToParam(QueryStaBo bo);
+
+    QueryStaScopeParam convertQueryStaByCurrentTime(String reportCycle);
+    QueryStaBo convertQueryStaBoByCurrentTime(String reportCycle);
+    QueryStaBo getLastCycle(String startDateStr, String cycleType);
+
 }

+ 61 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/ICoopBatchReportDetailService.java

@@ -0,0 +1,61 @@
+
+
+package cn.vber.breeding.service;
+
+import cn.vber.breeding.domain.CoopBatchReportDetail;
+import cn.vber.breeding.domain.bo.statistic.QueryStaScopeParam;
+import cn.vber.breeding.domain.vo.CoopBatchReportDetailVo;
+import cn.vber.breeding.domain.bo.CoopBatchReportDetailBo;
+import cn.vber.breeding.domain.vo.report.CoopBatchReportDetailResult;
+import cn.vber.breeding.domain.vo.report.CoopBatchReportDetailView;
+import cn.vber.common.mybatis.core.page.TableDataInfo;
+import cn.vber.common.mybatis.core.page.PageQuery;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 统计报表详情信息Service接口
+ *
+ * @author IwbY
+ * @date 2025-08-18
+ */
+public interface ICoopBatchReportDetailService {
+
+    /**
+     * 查询统计报表详情信息
+     */
+    CoopBatchReportDetailVo queryById(Long id);
+
+    /**
+     * 查询统计报表详情信息列表
+     */
+    TableDataInfo<CoopBatchReportDetailVo> queryPageList(CoopBatchReportDetailBo bo, PageQuery pageQuery);
+
+    /**
+     * 查询统计报表详情信息列表
+     */
+    List<CoopBatchReportDetailVo> queryList(CoopBatchReportDetailBo bo);
+
+    /**
+     * 新增统计报表详情信息
+     */
+    Boolean insertByBo(CoopBatchReportDetailBo bo);
+
+    /**
+     * 修改统计报表详情信息
+     */
+    Boolean updateByBo(CoopBatchReportDetailBo bo);
+
+    /**
+     * 校验并批量删除统计报表详情信息信息
+     */
+    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+    /**
+     * 查询统计报表详情信息列表
+     */
+    List<CoopBatchReportDetailResult> queryListViewByReportId(String reportId, QueryStaScopeParam param);
+}
+
+          
+        

+ 57 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/ICoopBatchReportService.java

@@ -0,0 +1,57 @@
+
+
+package cn.vber.breeding.service;
+
+import cn.vber.breeding.domain.CoopBatchReport;
+import cn.vber.breeding.domain.bo.statistic.QueryStaBo;
+import cn.vber.breeding.domain.vo.CoopBatchReportVo;
+import cn.vber.breeding.domain.bo.CoopBatchReportBo;
+import cn.vber.common.mybatis.core.page.TableDataInfo;
+import cn.vber.common.mybatis.core.page.PageQuery;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 报表信息Service接口
+ *
+ * @author IwbY
+ * @date 2025-08-18
+ */
+public interface ICoopBatchReportService {
+
+    /**
+     * 查询报表信息
+     */
+    CoopBatchReportVo queryById(Long id);
+
+    /**
+     * 查询报表信息列表
+     */
+    TableDataInfo<CoopBatchReportVo> queryPageList(CoopBatchReportBo bo, PageQuery pageQuery);
+
+    /**
+     * 查询报表信息列表
+     */
+    List<CoopBatchReportVo> queryList(CoopBatchReportBo bo);
+
+    /**
+     * 新增报表信息
+     */
+    Boolean insertByBo(CoopBatchReportBo bo);
+
+    /**
+     * 修改报表信息
+     */
+    Boolean updateByBo(CoopBatchReportBo bo);
+
+    /**
+     * 校验并批量删除报表信息信息
+     */
+    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+
+    CoopBatchReportVo queryByStaParam(QueryStaBo bo);
+}
+
+          
+        

+ 0 - 54
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/ICoopEggDayService.java

@@ -1,54 +0,0 @@
-
-
-package cn.vber.breeding.service;
-
-import cn.vber.breeding.domain.CoopEggDay;
-import cn.vber.breeding.domain.vo.CoopEggDayVo;
-import cn.vber.breeding.domain.bo.CoopEggDayBo;
-import cn.vber.common.mybatis.core.page.TableDataInfo;
-import cn.vber.common.mybatis.core.page.PageQuery;
-
-import java.util.Collection;
-import java.util.List;
-
-/**
- * 鸡舍日产蛋记录Service接口
- *
- * @author IwbY
- * @date 2025-07-31
- */
-public interface ICoopEggDayService {
-
-    /**
-     * 查询鸡舍日产蛋记录
-     */
-    CoopEggDayVo queryById(Long id);
-
-    /**
-     * 查询鸡舍日产蛋记录列表
-     */
-    TableDataInfo<CoopEggDayVo> queryPageList(CoopEggDayBo bo, PageQuery pageQuery);
-
-    /**
-     * 查询鸡舍日产蛋记录列表
-     */
-    List<CoopEggDayVo> queryList(CoopEggDayBo bo);
-
-    /**
-     * 新增鸡舍日产蛋记录
-     */
-    Boolean insertByBo(CoopEggDayBo bo);
-
-    /**
-     * 修改鸡舍日产蛋记录
-     */
-    Boolean updateByBo(CoopEggDayBo bo);
-
-    /**
-     * 校验并批量删除鸡舍日产蛋记录信息
-     */
-    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
-}
-
-          
-        

+ 14 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/ISopService.java

@@ -0,0 +1,14 @@
+package cn.vber.breeding.service;
+
+import cn.vber.breeding.domain.vo.sop.SopBindLogVo;
+
+import java.util.List;
+
+public interface ISopService {
+
+    List<SopBindLogVo> queryChickenFeedRecord(Long chickenId, String batchNum);
+
+    List<SopBindLogVo> queryChickenDrugRecord(Long chickenId, String batchNum);
+
+    List<SopBindLogVo> queryChickenVaccineRecord(Long chickenId, String batchNum);
+}

+ 32 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/IStatisticsHelperService.java

@@ -0,0 +1,32 @@
+package cn.vber.breeding.service;
+
+import cn.vber.breeding.domain.bo.statistic.QueryStaBo;
+import cn.vber.breeding.domain.bo.statistic.QueryStaScopeParam;
+import cn.vber.breeding.domain.bo.statistic.QueryStaScopeParamBo;
+import cn.vber.breeding.domain.vo.statistic.ChickenStatisticDayResultVo;
+import cn.vber.breeding.domain.vo.statistic.CoopBatchChickenStatisticResultVo;
+import cn.vber.breeding.domain.vo.statistic.CoopBatchEggStatisticResultVo;
+import cn.vber.breeding.domain.vo.statistic.StatisticTmpResultDto;
+
+public interface IStatisticsHelperService {
+
+
+//    CoopBatchChickenStatisticResultVo queryChickenCull(QueryStaScopeParamBo queryScopeParam);
+//
+//    CoopBatchEggStatisticResultVo queryEggStatistic(QueryStaScopeParamBo queryScopeParam);
+//
+//    CoopBatchChickenStatisticResultVo queryChickenStatistic(QueryStaScopeParamBo queryScopeParam);
+//
+//    CoopBatchChickenStatisticResultVo queryChickenIn(QueryStaScopeParamBo queryScopeParam);
+//
+//    CoopBatchChickenStatisticResultVo queryChickenOut(QueryStaScopeParamBo queryScopeParam);
+//
+//    ChickenStatisticDayResultVo queryChickenCountByDay(QueryStaScopeParamBo queryScopeParam);
+
+    void statisticDay(QueryStaBo input);
+
+    void statisticMonthOrYearOrQuarter(QueryStaBo input);
+
+    void calcCommon(StatisticTmpResultDto tmpResult);
+
+}

+ 10 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/IStatisticsService.java

@@ -0,0 +1,10 @@
+package cn.vber.breeding.service;
+
+import java.util.Map;
+
+public interface IStatisticsService {
+
+    Map<String, Integer> statisticsChickenCullByBatch(String batchNum);
+
+    Boolean statisticsMeasure(Long measureId);
+}

+ 15 - 2
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/impl/BatchServiceImpl.java

@@ -4,9 +4,9 @@ package cn.vber.breeding.service.impl;
 
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.date.DateUtil;
-import cn.hutool.core.util.NumberUtil;
 import cn.vber.base.enums.ChickenGenderEnum;
 import cn.vber.base.enums.ChickenStatusEnum;
+import cn.vber.base.enums.WingTagStatusEnum;
 import cn.vber.breeding.domain.Chicken;
 import cn.vber.breeding.domain.bo.batchSop.CullBatchBo;
 import cn.vber.breeding.domain.vo.ChickenVo;
@@ -37,7 +37,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Collection;
 import java.util.Objects;
-import java.util.stream.Collectors;
 
 /**
  * 批次信息Service业务层处理
@@ -194,6 +193,9 @@ public class BatchServiceImpl implements IBatchService {
                 if(chickenVo.getGender().equals(ChickenGenderEnum.FEMALE.getCode())){
                     commonService.cancelFamilyByFemaleId(chickenVo.getId());
                 }
+                commonService.cullMeasureDetail(chickenVo.getId());
+                //释放翅号
+                commonService.changeWingStatus(chickenVo.getWingTagNum(), WingTagStatusEnum.IDLE.getCode());
 
             }
             Batch batch = baseMapper.selectById(bo.getBatchNum());
@@ -208,6 +210,17 @@ public class BatchServiceImpl implements IBatchService {
         }
     }
 
+    @Override
+    public int changeBatchStatus(Batch batch, Integer status) {
+        if (batch != null){
+            batch.setStatus(status);
+
+            //清理批次缓存
+            commonService.clearCache(CacheNames.BATCH_NUM_INFO);
+            return baseMapper.updateById(batch);
+        }
+        return 0;
+    }
 
 }
 

+ 6 - 2
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/impl/CageChangeServiceImpl.java

@@ -7,6 +7,7 @@ import cn.vber.breeding.mapper.ChickenMapper;
 import cn.vber.breeding.service.ICommonService;
 import cn.vber.common.core.constant.CacheNames;
 import cn.vber.common.core.exception.ServiceException;
+import cn.vber.common.core.utils.DateUtils;
 import cn.vber.common.core.utils.MapstructUtils;
 import cn.vber.common.core.utils.StringUtils;
 import cn.vber.common.mybatis.core.page.TableDataInfo;
@@ -126,9 +127,10 @@ public class CageChangeServiceImpl implements ICageChangeService {
         }
         Chicken chicken = chickens.get(0);
         entity.setSourceCageId(chicken.getCageId());
-        entity.setStatus(CageChangeStatusEnum.CREATED.getCode());
+        //entity.setStatus(CageChangeStatusEnum.CREATED.getCode());
+        entity.setStatus(CageChangeStatusEnum.AUDITED.getCode());
         if(entity.getSourceCageId() == null){
-            entity.setStatus(CageChangeStatusEnum.AUDITED.getCode());
+            //entity.setStatus(CageChangeStatusEnum.AUDITED.getCode());
             //cageId如果为空,就更新个体笼号
             chicken.setCageId(entity.getTargetCageId());
             chickenMapper.updateById(chicken);
@@ -136,6 +138,7 @@ public class CageChangeServiceImpl implements ICageChangeService {
         if(chicken.getCageId().equals(entity.getTargetCageId())){
             entity.setStatus(CageChangeStatusEnum.CANCELLED.getCode());
         }
+        entity.setCrossCoop(commonService.isCrossCoop(entity.getSourceCageId(), entity.getTargetCageId())?1:0);
     }
 
     /**
@@ -163,6 +166,7 @@ public class CageChangeServiceImpl implements ICageChangeService {
         for (CageChange cageChange : cageChanges) {
             // 更新换笼状态为已审核
             cageChange.setStatus(CageChangeStatusEnum.AUDITED.getCode());
+            cageChange.setBindTime(DateUtils.getNowDate());
             baseMapper.updateById(cageChange);
 
             // 更新鸡只的笼号信息

+ 3 - 2
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/impl/ChickenCoopServiceImpl.java

@@ -52,7 +52,7 @@ public class ChickenCoopServiceImpl implements IChickenCoopService, ChickenCoopS
     @Override
     public TableDataInfo<ChickenCoopVo> queryPageList(ChickenCoopBo bo, PageQuery pageQuery) {
         LambdaQueryWrapper<ChickenCoop> lqw = buildQueryWrapper(bo);
-        Page<ChickenCoopVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        Page<ChickenCoopVo> result = baseMapper.selectPageList(pageQuery.build(), lqw);
         return TableDataInfo.build(result);
     }
 
@@ -62,7 +62,7 @@ public class ChickenCoopServiceImpl implements IChickenCoopService, ChickenCoopS
     @Override
     public List<ChickenCoopVo> queryList(ChickenCoopBo bo) {
         LambdaQueryWrapper<ChickenCoop> lqw = buildQueryWrapper(bo);
-        return baseMapper.selectVoList(lqw);
+        return baseMapper.selectListVo(lqw);
     }
 
     private LambdaQueryWrapper<ChickenCoop> buildQueryWrapper(ChickenCoopBo bo) {
@@ -71,6 +71,7 @@ public class ChickenCoopServiceImpl implements IChickenCoopService, ChickenCoopS
         lqw.eq(StringUtils.isNotBlank(bo.getFactory()), ChickenCoop::getFactory, bo.getFactory());
         lqw.like(StringUtils.isNotBlank(bo.getCoopName()), ChickenCoop::getCoopName, bo.getCoopName());
         lqw.eq(bo.getStatus() != null, ChickenCoop::getStatus, bo.getStatus());
+        lqw.eq(bo.getCoopType() != null, ChickenCoop::getCoopType, bo.getCoopType());
         lqw.eq(bo.getManager() != null, ChickenCoop::getManager, bo.getManager());
         return lqw;
     }

+ 117 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/impl/ChickenMetatarsalServiceImpl.java

@@ -0,0 +1,117 @@
+
+
+package cn.vber.breeding.service.impl;
+
+import cn.vber.breeding.domain.ChickenWeight;
+import cn.vber.common.core.utils.MapstructUtils;
+import cn.vber.common.core.utils.StringUtils;
+import cn.vber.common.mybatis.core.page.TableDataInfo;
+import cn.vber.common.mybatis.core.page.PageQuery;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import cn.vber.breeding.domain.bo.ChickenMetatarsalBo;
+import cn.vber.breeding.domain.vo.ChickenMetatarsalVo;
+import cn.vber.breeding.domain.ChickenMetatarsal;
+import cn.vber.breeding.mapper.ChickenMetatarsalMapper;
+import cn.vber.breeding.service.IChickenMetatarsalService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 跖骨长管理Service业务层处理
+ *
+ * @author IwbY
+ * @date 2025-08-14
+ */
+@RequiredArgsConstructor
+@Service
+public class ChickenMetatarsalServiceImpl implements IChickenMetatarsalService {
+
+    private final ChickenMetatarsalMapper baseMapper;
+
+    /**
+     * 查询跖骨长管理
+     */
+    @Override
+    public ChickenMetatarsalVo queryById(Long id) {
+        return baseMapper.selectVoById(id);
+    }
+
+    /**
+     * 查询跖骨长管理列表
+     */
+    @Override
+    public TableDataInfo<ChickenMetatarsalVo> queryPageList(ChickenMetatarsalBo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<ChickenMetatarsal> lqw = buildQueryWrapper(bo);
+        Page<ChickenMetatarsalVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        return TableDataInfo.build(result);
+    }
+
+    /**
+     * 查询跖骨长管理列表
+     */
+    @Override
+    public List<ChickenMetatarsalVo> queryList(ChickenMetatarsalBo bo) {
+        LambdaQueryWrapper<ChickenMetatarsal> lqw = buildQueryWrapper(bo);
+        return baseMapper.selectVoList(lqw);
+    }
+
+    private LambdaQueryWrapper<ChickenMetatarsal> buildQueryWrapper(ChickenMetatarsalBo bo) {
+        Map<String, Object> params = bo.getParams();
+        LambdaQueryWrapper<ChickenMetatarsal> lqw = Wrappers.lambdaQuery();
+        lqw.eq(bo.getChickenId() != null, ChickenMetatarsal::getChickenId, bo.getChickenId());
+        lqw.between(StringUtils.isNotEmpty(params.get("beginRecordDate")) && StringUtils.isNotEmpty(params.get("endRecordDate")),
+                ChickenMetatarsal::getRecordDate , params.get("beginRecordDate"), params.get("endRecordDate"));
+        return lqw;
+    }
+
+    /**
+     * 新增跖骨长管理
+     */
+    @Override
+    public Boolean insertByBo(ChickenMetatarsalBo bo) {
+        ChickenMetatarsal add = MapstructUtils.convert(bo, ChickenMetatarsal. class);
+        validEntityBeforeSave(add);
+        boolean flag = baseMapper.insert(add) > 0;
+        if (flag) {
+            bo.setId(add.getId());
+        }
+        return flag;
+    }
+
+    /**
+     * 修改跖骨长管理
+     */
+    @Override
+    public Boolean updateByBo(ChickenMetatarsalBo bo) {
+        ChickenMetatarsal update = MapstructUtils.convert(bo, ChickenMetatarsal. class);
+        validEntityBeforeSave(update);
+        return baseMapper.updateById(update) > 0;
+    }
+
+    /**
+     * 保存前的数据校验
+     */
+    private void validEntityBeforeSave(ChickenMetatarsal entity) {
+        //TODO 做一些数据校验,如唯一约束
+    }
+
+    /**
+     * 批量删除跖骨长管理
+     */
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if (isValid) {
+            //TODO 做一些业务上的校验,判断是否需要校验
+        }
+        return baseMapper.deleteByIds(ids) > 0;
+    }
+}
+
+          
+        

+ 26 - 14
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/impl/ChickenServiceImpl.java

@@ -11,6 +11,7 @@ import cn.vber.breeding.domain.bo.chicken.CullChickenBo;
 import cn.vber.breeding.mapper.BatchMapper;
 import cn.vber.breeding.mapper.FamilyMapper;
 import cn.vber.breeding.mapper.WingTagMapper;
+import cn.vber.breeding.service.IBatchService;
 import cn.vber.breeding.service.ICommonService;
 import cn.vber.common.core.constant.CacheNames;
 import cn.vber.common.core.exception.ServiceException;
@@ -52,6 +53,7 @@ public class ChickenServiceImpl implements IChickenService, ChickenService {
     private final FamilyMapper familyMapper;
     private final WingTagMapper wingTagMapper;
     private final BatchMapper batchMapper;
+    private final IBatchService batchService;
     private final ICommonService commonService;
 
     /**
@@ -114,20 +116,29 @@ public class ChickenServiceImpl implements IChickenService, ChickenService {
         if (flag) {
             bo.setId(add.getId());
             // 绑定翅号,更新绑定翅号的状态
-            changeWingStatus(bo.getWingTagNum(),WingTagStatusEnum.BOUND.getCode());
+            if(commonService.checkWingTagNumIsBind(bo.getWingTagNum())){
+                throw new ServiceException("该翅号已绑定!");
+            }
+            commonService.changeWingStatus(bo.getWingTagNum(),WingTagStatusEnum.BOUND.getCode());
             String batchNum = bo.getBatchNum();
             Batch batch = batchMapper.selectById(batchNum);
             if (batch != null && Objects.equals(batch.getStatus(), BatchStatusEnum.CREATED.getCode())) {
                 //批次状态改为育成中
-                batch.setStatus(BatchStatusEnum.GROWING.getCode());
-                batchMapper.updateById(batch);
-                //清理批次缓存
-                commonService.clearCache(CacheNames.BATCH_NUM_INFO);
+                batchService.changeBatchStatus(batch, BatchStatusEnum.GROWING.getCode());
+//                //批次状态改为育成中
+//                batch.setStatus(BatchStatusEnum.GROWING.getCode());
+//                batchMapper.updateById(batch);
+            }
+            //创建的个体如果存在笼号,则添加笼位变更记录
+            if(bo.getCageId()!=null && bo.getCageId()>0){
+                this.commonService.addChickenCageChange(bo.getId(),null,bo.getCageId(),CageChangeStatusEnum.AUDITED.getCode());
             }
         }
         return flag;
     }
 
+
+
     /**
      * 修改鸡只个体信息
      */
@@ -184,19 +195,20 @@ public class ChickenServiceImpl implements IChickenService, ChickenService {
                 commonService.cancelFamilyByFemaleId(chicken.getId());
             }
             //changeWingStatus(chicken.getWingTagNum(), WingTagStatusEnum.IDLE.getCode());
+            commonService.cullMeasureDetail(chicken.getId());
         }
         return baseMapper.updateBatchById(chickens);
     }
 
-    private void changeWingStatus(String wingTagNum, Integer Status){
-        try {
-            WingTag wingTag = wingTagMapper.selectOne(new LambdaQueryWrapper<WingTag>().eq(WingTag::getWingTagNum, wingTagNum));
-            wingTag.setStatus(Status);
-            wingTagMapper.updateById(wingTag);
-        } catch (Exception e) {
-            throw new ServiceException(StrUtil.format("修改鸡翅{}状态失败", wingTagNum));
-        }
-    }
+//    private void changeWingStatus(String wingTagNum, Integer Status){
+//        try {
+//            WingTag wingTag = wingTagMapper.selectOne(new LambdaQueryWrapper<WingTag>().eq(WingTag::getWingTagNum, wingTagNum));
+//            wingTag.setStatus(Status);
+//            wingTagMapper.updateById(wingTag);
+//        } catch (Exception e) {
+//            throw new ServiceException(StrUtil.format("修改鸡翅{}状态失败", wingTagNum));
+//        }
+//    }
     private void changeFamilyStatus(Long femaleChickenId, Integer Status) {
         try {
             LambdaQueryWrapper<Family> lqw = new LambdaQueryWrapper<Family>().eq(Family::getFemaleChickenId, femaleChickenId)

+ 15 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/impl/ChickenSopServiceImpl.java

@@ -1,18 +1,27 @@
 package cn.vber.breeding.service.impl;
 
+import cn.vber.base.domain.vo.FeedSopVo;
 import cn.vber.base.enums.SopStatusEnum;
 import cn.vber.base.mapper.DrugSopMapper;
 import cn.vber.base.mapper.FeedSopMapper;
 import cn.vber.base.mapper.VaccineSopMapper;
 import cn.vber.breeding.domain.*;
+import cn.vber.breeding.domain.vo.ChickenDrugVo;
+import cn.vber.breeding.domain.vo.ChickenFeedVo;
+import cn.vber.breeding.domain.vo.ChickenVaccineVo;
+import cn.vber.breeding.domain.vo.ChickenVo;
+import cn.vber.breeding.domain.vo.sop.SopBindLogVo;
 import cn.vber.breeding.mapper.*;
 
 import cn.vber.common.core.service.ChickenSopService;
+import cn.vber.common.core.utils.ChickenCalcUtils;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
 
+import java.util.ArrayList;
 import java.util.List;
+import java.util.Optional;
 
 @RequiredArgsConstructor
 @Service
@@ -20,9 +29,13 @@ public class ChickenSopServiceImpl implements ChickenSopService {
     private final ChickenFeedMapper chickenFeedMapper;
     private final ChickenDrugMapper chickenDrugMapper;
     private final ChickenVaccineMapper chickenVaccineMapper;
+    private final BatchFeedMapper batchFeedMapper;
+    private final BatchDrugMapper batchDrugMapper;
+    private final BatchVaccineMapper batchVaccineMapper;
     private final DrugSopMapper drugSopMapper;
     private final VaccineSopMapper vaccineSopMapper;
     private final FeedSopMapper feedSopMapper;
+    private final BatchMapper batchMapper;
     @Override
     public String querySopNameByChickenId(Long chickenId, String sopType) {
 
@@ -59,4 +72,6 @@ public class ChickenSopServiceImpl implements ChickenSopService {
     }
 
 
+
+
 }

+ 117 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/impl/ChickenTibiaServiceImpl.java

@@ -0,0 +1,117 @@
+
+
+package cn.vber.breeding.service.impl;
+
+import cn.vber.breeding.domain.ChickenMetatarsal;
+import cn.vber.common.core.utils.MapstructUtils;
+import cn.vber.common.core.utils.StringUtils;
+import cn.vber.common.mybatis.core.page.TableDataInfo;
+import cn.vber.common.mybatis.core.page.PageQuery;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import cn.vber.breeding.domain.bo.ChickenTibiaBo;
+import cn.vber.breeding.domain.vo.ChickenTibiaVo;
+import cn.vber.breeding.domain.ChickenTibia;
+import cn.vber.breeding.mapper.ChickenTibiaMapper;
+import cn.vber.breeding.service.IChickenTibiaService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 胫骨长管理Service业务层处理
+ *
+ * @author IwbY
+ * @date 2025-08-14
+ */
+@RequiredArgsConstructor
+@Service
+public class ChickenTibiaServiceImpl implements IChickenTibiaService {
+
+    private final ChickenTibiaMapper baseMapper;
+
+    /**
+     * 查询胫骨长管理
+     */
+    @Override
+    public ChickenTibiaVo queryById(Long id) {
+        return baseMapper.selectVoById(id);
+    }
+
+    /**
+     * 查询胫骨长管理列表
+     */
+    @Override
+    public TableDataInfo<ChickenTibiaVo> queryPageList(ChickenTibiaBo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<ChickenTibia> lqw = buildQueryWrapper(bo);
+        Page<ChickenTibiaVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        return TableDataInfo.build(result);
+    }
+
+    /**
+     * 查询胫骨长管理列表
+     */
+    @Override
+    public List<ChickenTibiaVo> queryList(ChickenTibiaBo bo) {
+        LambdaQueryWrapper<ChickenTibia> lqw = buildQueryWrapper(bo);
+        return baseMapper.selectVoList(lqw);
+    }
+
+    private LambdaQueryWrapper<ChickenTibia> buildQueryWrapper(ChickenTibiaBo bo) {
+        Map<String, Object> params = bo.getParams();
+        LambdaQueryWrapper<ChickenTibia> lqw = Wrappers.lambdaQuery();
+        lqw.eq(bo.getChickenId() != null, ChickenTibia::getChickenId, bo.getChickenId());
+        lqw.between(StringUtils.isNotEmpty(params.get("beginRecordDate")) && StringUtils.isNotEmpty(params.get("endRecordDate")),
+                ChickenTibia::getRecordDate , params.get("beginRecordDate"), params.get("endRecordDate"));
+        return lqw;
+    }
+
+    /**
+     * 新增胫骨长管理
+     */
+    @Override
+    public Boolean insertByBo(ChickenTibiaBo bo) {
+        ChickenTibia add = MapstructUtils.convert(bo, ChickenTibia. class);
+        validEntityBeforeSave(add);
+        boolean flag = baseMapper.insert(add) > 0;
+        if (flag) {
+            bo.setId(add.getId());
+        }
+        return flag;
+    }
+
+    /**
+     * 修改胫骨长管理
+     */
+    @Override
+    public Boolean updateByBo(ChickenTibiaBo bo) {
+        ChickenTibia update = MapstructUtils.convert(bo, ChickenTibia. class);
+        validEntityBeforeSave(update);
+        return baseMapper.updateById(update) > 0;
+    }
+
+    /**
+     * 保存前的数据校验
+     */
+    private void validEntityBeforeSave(ChickenTibia entity) {
+        //TODO 做一些数据校验,如唯一约束
+    }
+
+    /**
+     * 批量删除胫骨长管理
+     */
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if (isValid) {
+            //TODO 做一些业务上的校验,判断是否需要校验
+        }
+        return baseMapper.deleteByIds(ids) > 0;
+    }
+}
+
+          
+        

+ 377 - 5
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/impl/CommonServiceImpl.java

@@ -1,18 +1,22 @@
 package cn.vber.breeding.service.impl;
 
 import cn.hutool.core.util.StrUtil;
+import cn.vber.base.enums.CageChangeStatusEnum;
 import cn.vber.base.enums.FamilyStatusEnum;
-import cn.vber.breeding.domain.Batch;
-import cn.vber.breeding.domain.Family;
+import cn.vber.base.enums.MeasureDetailStatusEnum;
+import cn.vber.base.enums.WingTagStatusEnum;
+import cn.vber.breeding.domain.*;
+import cn.vber.breeding.domain.bo.statistic.QueryStaBo;
+import cn.vber.breeding.domain.bo.statistic.QueryStaScopeParam;
 import cn.vber.breeding.domain.vo.BatchVo;
+import cn.vber.breeding.domain.vo.ChickenCageVo;
 import cn.vber.breeding.domain.vo.ChickenVo;
 import cn.vber.breeding.domain.vo.FamilyVo;
-import cn.vber.breeding.mapper.BatchMapper;
-import cn.vber.breeding.mapper.ChickenMapper;
-import cn.vber.breeding.mapper.FamilyMapper;
+import cn.vber.breeding.mapper.*;
 import cn.vber.breeding.service.ICommonService;
 import cn.vber.common.core.constant.CacheNames;
 import cn.vber.common.core.exception.ServiceException;
+import cn.vber.common.core.utils.DateUtils;
 import cn.vber.common.core.utils.MapstructUtils;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
@@ -23,13 +27,23 @@ import org.springframework.cache.CacheManager;
 import org.springframework.cache.annotation.Cacheable;
 import org.springframework.stereotype.Service;
 
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Objects;
+
 @RequiredArgsConstructor
 @Service
 @Slf4j
 public class CommonServiceImpl implements ICommonService {
     private final ChickenMapper chickenMapper;
+    private final MeasureDetailMapper measureDetailMapper;
     private final BatchMapper batchMapper;
     private final FamilyMapper familyMapper;
+    private final ChickenCageMapper chickenCageMapper;
+    private final CageChangeMapper cageChangeMapper;
+    private final WingTagMapper wingTagMapper;
+
     // 添加缓存管理器,用于手动清除缓存
     private final CacheManager cacheManager;
     @Override
@@ -64,6 +78,67 @@ public class CommonServiceImpl implements ICommonService {
         }
     }
 
+    @Override
+    public void cullMeasureDetail(Long chickenId) {
+        MeasureDetail measureDetail = measureDetailMapper.selectOne(new LambdaQueryWrapper<MeasureDetail>()
+                .eq(MeasureDetail::getChickenId, chickenId));
+        if (measureDetail != null) {
+            measureDetail.setStatus(MeasureDetailStatusEnum.CULLED.getCode());
+            measureDetailMapper.updateById(measureDetail);
+        }
+    }
+
+    @Override
+    public void addChickenCageChange(Long chickenId, Long sourceCageId, Long targetCageId,Integer status){
+        CageChange cageChange = new CageChange();
+        cageChange.setChickenId(chickenId);
+        cageChange.setSourceCageId(sourceCageId);
+        cageChange.setTargetCageId(targetCageId);
+        cageChange.setBindTime(DateUtils.getNowDate());
+        cageChange.setStatus(status);
+        cageChange.setCrossCoop(isCrossCoop(sourceCageId, targetCageId)?1:0);
+        cageChangeMapper.insert(cageChange);
+    }
+
+    /**
+     * 检查鸡翅号是否被绑定
+     * @param wingTagNum
+     * @return true:被绑定
+     */
+    @Override
+    public boolean checkWingTagNumIsBind(String wingTagNum) {
+        WingTag wingTag = wingTagMapper.selectOne(new LambdaQueryWrapper<WingTag>().eq(WingTag::getWingTagNum, wingTagNum));
+        if (wingTag != null) {
+            return Objects.equals(wingTag.getStatus(), WingTagStatusEnum.BOUND.getCode());
+        }
+        return false;
+    }
+
+    @Override
+    public Boolean isCrossCoop(Long sourceCageId, Long targetCageId) {
+        if((sourceCageId == null || sourceCageId == 0L )&& (targetCageId != null && targetCageId > 0L)){
+            return true;
+        }
+        ChickenCageVo sourceCage = chickenCageMapper.selectVoOne(new LambdaQueryWrapper<ChickenCage>()
+                .eq(ChickenCage::getId, sourceCageId));
+        ChickenCageVo targetCage = chickenCageMapper.selectVoOne(new LambdaQueryWrapper<ChickenCage>().eq(ChickenCage::getId, targetCageId));
+        if (sourceCage != null && targetCage != null) {
+            return sourceCage.getChickenCoopId().equals(targetCage.getChickenCoopId());
+        }
+        return false;
+    }
+
+    @Override
+    public void changeWingStatus(String wingTagNum, Integer Status){
+        try {
+            WingTag wingTag = wingTagMapper.selectOne(new LambdaQueryWrapper<WingTag>().eq(WingTag::getWingTagNum, wingTagNum));
+            wingTag.setStatus(Status);
+            wingTagMapper.updateById(wingTag);
+        } catch (Exception e) {
+            throw new ServiceException(StrUtil.format("修改鸡翅{}状态失败", wingTagNum));
+        }
+    }
+
     @Override
     public void clearCache(String cacheName) {
         // 删除前清除相关缓存
@@ -74,4 +149,301 @@ public class CommonServiceImpl implements ICommonService {
             }
         }
     }
+
+    @Override
+    public QueryStaScopeParam convertQueryStaToParam(QueryStaBo bo) {
+        if (bo == null) {
+            return null;
+        }
+        QueryStaScopeParam param = new QueryStaScopeParam();
+        // 复制非日期字段
+        param.setReportCycle(bo.getReportCycle());
+        //param.setFactory(bo.getFactory());
+
+        // 处理coopType转换
+        if (bo.getCoopType() != null) {
+            if ("coop".equals(bo.getCoopType())) {
+                param.setCoopType(1);
+            } else if ("egg".equals(bo.getCoopType())) {
+                param.setCoopType(2);
+            } else {
+                param.setCoopType(null);
+            }
+        }
+        // 处理日期转换 - 根据reportCycle和传入的参数计算startDate和endDate
+        Date startDate = null;
+        Date endDate = null;
+        Calendar cal = Calendar.getInstance();
+        // 根据reportCycle的值计算日期范围
+        switch (bo.getReportCycle()) {
+            case "Y": // 年
+                if (bo.getYear() == null) {
+                    throw new IllegalArgumentException("年份参数不能为空");
+                }
+                cal.set(bo.getYear(), Calendar.JANUARY, 1);
+                startDate = getStartOfDay(cal.getTime());
+
+                cal.set(bo.getYear(), Calendar.DECEMBER, 31);
+                endDate = getEndOfDay(cal.getTime());
+                break;
+
+            case "Q": // 季度
+                if (bo.getYear() == null || bo.getQuarter() == null) {
+                    throw new IllegalArgumentException("年份和季度参数不能为空");
+                }
+                int quarterStartMonth = (bo.getQuarter() - 1) * 3;
+                cal.set(bo.getYear(), quarterStartMonth, 1);
+                startDate = getStartOfDay(cal.getTime());
+
+                cal.set(bo.getYear(), quarterStartMonth + 2, 1);
+                cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
+                endDate = getEndOfDay(cal.getTime());
+                break;
+
+            case "M": // 月
+                if (bo.getYear() == null || bo.getMonth() == null) {
+                    throw new IllegalArgumentException("年份和月份参数不能为空");
+                }
+                cal.set(bo.getYear(), bo.getMonth() - 1, 1);
+                startDate = getStartOfDay(cal.getTime());
+
+                cal.set(bo.getYear(), bo.getMonth() - 1, 1);
+                cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
+                endDate = getEndOfDay(cal.getTime());
+                break;
+
+            case "D": // 日
+                if (bo.getYear() == null || bo.getMonth() == null || bo.getDay() == null) {
+                    throw new IllegalArgumentException("年份、月份和日期参数不能为空");
+                }
+                cal.set(bo.getYear(), bo.getMonth() - 1, bo.getDay());
+                startDate = getStartOfDay(cal.getTime());
+                endDate = getEndOfDay(cal.getTime());
+                break;
+
+            default:
+                break;
+        }
+
+        // 格式化日期为yyyy-MM-dd HH:mm:ss
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        param.setStartDate(sdf.format(startDate));
+        param.setEndDate(sdf.format(endDate));
+
+        return param;
+    }
+
+
+    /**
+     * 根据统计类型和当前时间生成QueryStaScopeParam对象
+     * @param reportCycle 统计类型(年:Y,月:M,日:D,季度:Q)
+     * @return QueryStaScopeParam对象
+     */
+    @Override
+    public QueryStaScopeParam convertQueryStaByCurrentTime(String reportCycle) {
+        QueryStaScopeParam param = new QueryStaScopeParam();
+        param.setReportCycle(reportCycle);
+
+        // 处理日期转换 - 根据reportCycle和当前时间计算startDate和endDate
+        Date startDate;
+        Date endDate;
+
+        Calendar cal = Calendar.getInstance();
+
+        // 根据reportCycle的值计算日期范围
+        switch (reportCycle) {
+            case "Y": // 年
+                cal.set(Calendar.MONTH, Calendar.JANUARY);
+                cal.set(Calendar.DAY_OF_MONTH, 1);
+                startDate = getStartOfDay(cal.getTime());
+
+                cal.set(Calendar.MONTH, Calendar.DECEMBER);
+                cal.set(Calendar.DAY_OF_MONTH, 31);
+                endDate = getEndOfDay(cal.getTime());
+                break;
+
+            case "Q": // 季度
+                int currentMonth = cal.get(Calendar.MONTH);
+                int quarterStartMonth = (currentMonth / 3) * 3;
+                cal.set(Calendar.MONTH, quarterStartMonth);
+                cal.set(Calendar.DAY_OF_MONTH, 1);
+                startDate = getStartOfDay(cal.getTime());
+
+                cal.set(Calendar.MONTH, quarterStartMonth + 2);
+                cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
+                endDate = getEndOfDay(cal.getTime());
+                break;
+
+            case "M": // 月
+                cal.set(Calendar.DAY_OF_MONTH, 1);
+                startDate = getStartOfDay(cal.getTime());
+
+                cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
+                endDate = getEndOfDay(cal.getTime());
+                break;
+
+            case "D": // 日
+            default:
+                startDate = getStartOfDay(cal.getTime());
+                endDate = getEndOfDay(cal.getTime());
+                break;
+        }
+
+        // 格式化日期为yyyy-MM-dd HH:mm:ss
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        param.setStartDate(sdf.format(startDate));
+        param.setEndDate(sdf.format(endDate));
+
+        return param;
+    }
+
+
+
+
+    /**
+     * 根据传入的周期类型,根据当前日期,转换成QueryStaBo对象
+     * @param reportCycle 周期类型(年:Y,月:M,日:D,季度:Q)
+     * @return QueryStaBo对象
+     */
+    @Override
+    public QueryStaBo convertQueryStaBoByCurrentTime(String reportCycle) {
+        QueryStaBo queryStaBo = new QueryStaBo();
+        queryStaBo.setReportCycle(reportCycle);
+
+        Calendar cal = Calendar.getInstance();
+
+        switch (reportCycle) {
+            case "Y": // 年
+                queryStaBo.setYear(cal.get(Calendar.YEAR));
+                break;
+
+            case "Q": // 季度
+                int month = cal.get(Calendar.MONTH);
+                int quarter = (month / 3) + 1;
+                queryStaBo.setYear(cal.get(Calendar.YEAR));
+                queryStaBo.setQuarter(quarter);
+                break;
+
+            case "M": // 月
+                queryStaBo.setYear(cal.get(Calendar.YEAR));
+                queryStaBo.setMonth(cal.get(Calendar.MONTH) + 1); // Calendar.MONTH是从0开始的
+                break;
+
+            case "D": // 日
+            default:
+                queryStaBo.setYear(cal.get(Calendar.YEAR));
+                queryStaBo.setMonth(cal.get(Calendar.MONTH) + 1); // Calendar.MONTH是从0开始的
+                queryStaBo.setDay(cal.get(Calendar.DAY_OF_MONTH));
+                break;
+        }
+
+        return queryStaBo;
+    }
+
+
+    /**
+     * 根据开始时间字符串和周期类型计算上一个周期的年、月、日或季度
+     * @param startDateStr 开始时间字符串
+     * @param cycleType 周期类型(年:Y,月:M,日:D,季度:Q)
+     * @return 包含上一个周期信息的QueryStaBo对象
+     */
+    @Override
+    public QueryStaBo getLastCycle(String startDateStr, String cycleType) {
+        QueryStaBo queryStaBo = new QueryStaBo();
+
+        try {
+            // 解析日期字符串
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+            Date startDate = sdf.parse(startDateStr);
+
+            Calendar cal = Calendar.getInstance();
+            cal.setTime(startDate);
+
+            // 根据周期类型计算上一个周期
+            switch (cycleType) {
+                case "Y": // 年
+                    int lastYear = cal.get(Calendar.YEAR) - 1;
+                    queryStaBo.setYear(lastYear);
+                    break;
+
+                case "Q": // 季度
+                    int year = cal.get(Calendar.YEAR);
+                    int month = cal.get(Calendar.MONTH);
+                    int quarter = (month / 3) + 1;
+                    int lastQuarter = quarter - 1;
+
+                    if (lastQuarter <= 0) {
+                        // 上一年的第4季度
+                        queryStaBo.setYear(year - 1);
+                        queryStaBo.setQuarter(4);
+                    } else {
+                        queryStaBo.setYear(year);
+                        queryStaBo.setQuarter(lastQuarter);
+                    }
+                    break;
+
+                case "M": // 月
+                    int monthOfYear = cal.get(Calendar.MONTH); // 0-11
+                    int yearForMonth = cal.get(Calendar.YEAR);
+
+                    if (monthOfYear == 0) {
+                        // 上一年的12月
+                        queryStaBo.setYear(yearForMonth - 1);
+                        queryStaBo.setMonth(12);
+                    } else {
+                        queryStaBo.setYear(yearForMonth);
+                        queryStaBo.setMonth(monthOfYear); // Calendar.MONTH是从0开始的,所以不需要减1
+                    }
+                    break;
+
+                case "D": // 日
+                default:
+                    cal.add(Calendar.DAY_OF_MONTH, -1);
+                    queryStaBo.setYear(cal.get(Calendar.YEAR));
+                    queryStaBo.setMonth(cal.get(Calendar.MONTH) + 1); // QueryStaBo中的month是1-12
+                    queryStaBo.setDay(cal.get(Calendar.DAY_OF_MONTH));
+                    break;
+            }
+
+            queryStaBo.setReportCycle(cycleType);
+        } catch (Exception e) {
+            throw new ServiceException("日期解析失败: " + e.getMessage());
+        }
+
+        return queryStaBo;
+    }
+
+
+
+
+
+    /**
+     * 将日期设置为当天的开始时间(0点0分0秒)
+     * @param date 原始日期
+     * @return 当天开始时间
+     */
+    private Date getStartOfDay(Date date) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        calendar.set(Calendar.HOUR_OF_DAY, 0);
+        calendar.set(Calendar.MINUTE, 0);
+        calendar.set(Calendar.SECOND, 0);
+        calendar.set(Calendar.MILLISECOND, 0);
+        return calendar.getTime();
+    }
+
+    /**
+     * 将日期设置为当天的结束时间(23点59分59秒)
+     * @param date 原始日期
+     * @return 当天结束时间
+     */
+    private Date getEndOfDay(Date date) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        calendar.set(Calendar.HOUR_OF_DAY, 23);
+        calendar.set(Calendar.MINUTE, 59);
+        calendar.set(Calendar.SECOND, 59);
+        calendar.set(Calendar.MILLISECOND, 999);
+        return calendar.getTime();
+    }
 }

+ 190 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/impl/CoopBatchReportDetailServiceImpl.java

@@ -0,0 +1,190 @@
+
+
+package cn.vber.breeding.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.vber.breeding.domain.bo.statistic.QueryStaBo;
+import cn.vber.breeding.domain.bo.statistic.QueryStaScopeParam;
+import cn.vber.breeding.domain.vo.report.CoopBatchReportDetailResult;
+import cn.vber.breeding.domain.vo.report.CoopBatchReportDetailView;
+import cn.vber.breeding.domain.vo.statistic.StatisticTmpResultDto;
+import cn.vber.breeding.service.IStatisticsHelperService;
+import cn.vber.common.core.utils.ChickenCalcUtils;
+import cn.vber.common.core.utils.DateUtils;
+import cn.vber.common.core.utils.MapstructUtils;
+import cn.vber.common.core.utils.StringUtils;
+import cn.vber.common.mybatis.core.page.TableDataInfo;
+import cn.vber.common.mybatis.core.page.PageQuery;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+import cn.vber.breeding.domain.bo.CoopBatchReportDetailBo;
+import cn.vber.breeding.domain.vo.CoopBatchReportDetailVo;
+import cn.vber.breeding.domain.CoopBatchReportDetail;
+import cn.vber.breeding.mapper.CoopBatchReportDetailMapper;
+import cn.vber.breeding.service.ICoopBatchReportDetailService;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 统计报表详情信息Service业务层处理
+ *
+ * @author IwbY
+ * @date 2025-08-18
+ */
+@RequiredArgsConstructor
+@Service
+public class CoopBatchReportDetailServiceImpl implements ICoopBatchReportDetailService {
+
+    private final CoopBatchReportDetailMapper baseMapper;
+    private final IStatisticsHelperService statisticsHelperService;
+
+    /**
+     * 查询统计报表详情信息
+     */
+    @Override
+    public CoopBatchReportDetailVo queryById(Long id) {
+        return baseMapper.selectVoById(id);
+    }
+
+    /**
+     * 查询统计报表详情信息列表
+     */
+    @Override
+    public TableDataInfo<CoopBatchReportDetailVo> queryPageList(CoopBatchReportDetailBo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<CoopBatchReportDetail> lqw = buildQueryWrapper(bo);
+        Page<CoopBatchReportDetailVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        return TableDataInfo.build(result);
+    }
+
+    /**
+     * 查询统计报表详情信息列表
+     */
+    @Override
+    public List<CoopBatchReportDetailVo> queryList(CoopBatchReportDetailBo bo) {
+        LambdaQueryWrapper<CoopBatchReportDetail> lqw = buildQueryWrapper(bo);
+        return baseMapper.selectVoList(lqw);
+    }
+
+    /**
+     * 查询统计报表详情信息列表
+     */
+    @Override
+    public List<CoopBatchReportDetailResult> queryListViewByReportId(String reportId, QueryStaScopeParam param) {
+        List<CoopBatchReportDetailView> coopBatchReportDetailViews =
+                baseMapper.selectCoopBatchReportDetail(reportId, param.getCoopType());
+        Date endDate = DateUtils.parseDate(param.getEndDate());
+        List<CoopBatchReportDetailView> listResult = coopBatchReportDetailViews.stream().peek(detailView ->
+                        detailView.setEndAge(ChickenCalcUtils.calcChickenAge(endDate, detailView.getHatchDate())))
+                .toList();
+        List<CoopBatchReportDetailResult> resultList =  new ArrayList<>();
+
+       // 根据coopId分组并统计各项数据总和
+        Map<Long, List<CoopBatchReportDetailView>> groupedByCoopId = listResult.stream()
+                .collect(Collectors.groupingBy(CoopBatchReportDetailView::getCoopId));
+        StatisticTmpResultDto totalResult = new StatisticTmpResultDto();
+        groupedByCoopId.forEach((coopId, view) -> {
+            CoopBatchReportDetailResult result = new CoopBatchReportDetailResult();
+            result.setCoopId(coopId);
+            result.setCoopName(view.get(0).getCoopName());
+            result.setData(view);
+            view.forEach((k)->{
+                totalResult.setLastSave0(totalResult.getLastSave0()+k.getLastSave0());
+                totalResult.setLastSave1(totalResult.getLastSave1()+k.getLastSave1());
+                totalResult.setSave0(totalResult.getSave0()+k.getSave0());
+                totalResult.setSave1(totalResult.getSave1()+k.getSave1());
+                totalResult.setCull0(totalResult.getCull0()+k.getCull0());
+                totalResult.setCull1(totalResult.getCull1()+k.getCull1());
+                totalResult.setIn0(totalResult.getIn0()+k.getIn0());
+                totalResult.setIn1(totalResult.getIn1()+k.getIn1());
+                totalResult.setOut0(totalResult.getOut0()+k.getOut0());
+                totalResult.setOut1(totalResult.getOut1()+k.getOut1());
+                totalResult.setChicken0(totalResult.getChicken0()+k.getChicken0());
+                totalResult.setChicken1(totalResult.getChicken1()+k.getChicken1());
+            });
+            statisticsHelperService.calcCommon(totalResult);
+            result.setTotal(totalResult.convertDetailView());
+            resultList.add(result);
+        });
+        return resultList;
+    }
+
+    private LambdaQueryWrapper<CoopBatchReportDetail> buildQueryWrapper(CoopBatchReportDetailBo bo) {
+        Map<String, Object> params = bo.getParams();
+        LambdaQueryWrapper<CoopBatchReportDetail> lqw = Wrappers.lambdaQuery();
+        lqw.eq(bo.getCoopId() != null, CoopBatchReportDetail::getCoopId, bo.getCoopId());
+        lqw.eq(StringUtils.isNotBlank(bo.getBatchNum()), CoopBatchReportDetail::getBatchNum, bo.getBatchNum());
+        lqw.eq(bo.getLastSave0() != null, CoopBatchReportDetail::getLastSave0, bo.getLastSave0());
+        lqw.eq(bo.getLastSave1() != null, CoopBatchReportDetail::getLastSave1, bo.getLastSave1());
+        lqw.eq(bo.getSave0() != null, CoopBatchReportDetail::getSave0, bo.getSave0());
+        lqw.eq(bo.getSave1() != null, CoopBatchReportDetail::getSave1, bo.getSave1());
+        lqw.eq(bo.getCull0() != null, CoopBatchReportDetail::getCull0, bo.getCull0());
+        lqw.eq(bo.getCull1() != null, CoopBatchReportDetail::getCull1, bo.getCull1());
+        lqw.eq(bo.getIn0() != null, CoopBatchReportDetail::getIn0, bo.getIn0());
+        lqw.eq(bo.getIn1() != null, CoopBatchReportDetail::getIn1, bo.getIn1());
+        lqw.eq(bo.getOut0() != null, CoopBatchReportDetail::getOut0, bo.getOut0());
+        lqw.eq(bo.getOut1() != null, CoopBatchReportDetail::getOut1, bo.getOut1());
+        lqw.eq(bo.getQualifiedEgg() != null, CoopBatchReportDetail::getQualifiedEgg, bo.getQualifiedEgg());
+        lqw.eq(bo.getDeformedEgg() != null, CoopBatchReportDetail::getDeformedEgg, bo.getDeformedEgg());
+        lqw.eq(bo.getBreakEgg() != null, CoopBatchReportDetail::getBreakEgg, bo.getBreakEgg());
+        lqw.eq(bo.getEggProductionRate() != null, CoopBatchReportDetail::getEggProductionRate, bo.getEggProductionRate());
+        lqw.eq(bo.getEggPassRate() != null, CoopBatchReportDetail::getEggPassRate, bo.getEggPassRate());
+        lqw.eq(bo.getChicken0() != null, CoopBatchReportDetail::getChicken0, bo.getChicken0());
+        lqw.eq(bo.getChicken1() != null, CoopBatchReportDetail::getChicken1, bo.getChicken1());
+        lqw.eq(bo.getCullRate() != null, CoopBatchReportDetail::getCullRate, bo.getCullRate());
+        lqw.eq(bo.getLifeRate() != null, CoopBatchReportDetail::getLifeRate, bo.getLifeRate());
+        lqw.between(StringUtils.isNotEmpty(params.get("beginReportDate")) && StringUtils.isNotEmpty(params.get("endReportDate")),
+                CoopBatchReportDetail::getReportDate , params.get("beginReportDate"), params.get("endReportDate"));
+        return lqw;
+    }
+
+    /**
+     * 新增统计报表详情信息
+     */
+    @Override
+    public Boolean insertByBo(CoopBatchReportDetailBo bo) {
+        CoopBatchReportDetail add = MapstructUtils.convert(bo, CoopBatchReportDetail. class);
+        validEntityBeforeSave(add);
+        boolean flag = baseMapper.insert(add) > 0;
+        if (flag) {
+            bo.setId(add.getId());
+        }
+        return flag;
+    }
+
+    /**
+     * 修改统计报表详情信息
+     */
+    @Override
+    public Boolean updateByBo(CoopBatchReportDetailBo bo) {
+        CoopBatchReportDetail update = MapstructUtils.convert(bo, CoopBatchReportDetail. class);
+        validEntityBeforeSave(update);
+        return baseMapper.updateById(update) > 0;
+    }
+
+    /**
+     * 保存前的数据校验
+     */
+    private void validEntityBeforeSave(CoopBatchReportDetail entity) {
+        //TODO 做一些数据校验,如唯一约束
+    }
+
+    /**
+     * 批量删除统计报表详情信息
+     */
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if (isValid) {
+            //TODO 做一些业务上的校验,判断是否需要校验
+        }
+        return baseMapper.deleteByIds(ids) > 0;
+    }
+}
+
+          
+        

+ 162 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/impl/CoopBatchReportServiceImpl.java

@@ -0,0 +1,162 @@
+
+
+package cn.vber.breeding.service.impl;
+
+import cn.vber.breeding.domain.bo.statistic.QueryStaBo;
+import cn.vber.common.core.utils.MapstructUtils;
+import cn.vber.common.core.utils.StringUtils;
+import cn.vber.common.mybatis.core.page.TableDataInfo;
+import cn.vber.common.mybatis.core.page.PageQuery;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import cn.vber.breeding.domain.bo.CoopBatchReportBo;
+import cn.vber.breeding.domain.vo.CoopBatchReportVo;
+import cn.vber.breeding.domain.CoopBatchReport;
+import cn.vber.breeding.mapper.CoopBatchReportMapper;
+import cn.vber.breeding.service.ICoopBatchReportService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 报表信息Service业务层处理
+ *
+ * @author IwbY
+ * @date 2025-08-18
+ */
+@RequiredArgsConstructor
+@Service
+public class CoopBatchReportServiceImpl implements ICoopBatchReportService {
+
+    private final CoopBatchReportMapper baseMapper;
+
+    /**
+     * 查询报表信息
+     */
+    @Override
+    public CoopBatchReportVo queryById(Long id) {
+        return baseMapper.selectVoById(id);
+    }
+
+    /**
+     * 查询报表信息列表
+     */
+    @Override
+    public TableDataInfo<CoopBatchReportVo> queryPageList(CoopBatchReportBo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<CoopBatchReport> lqw = buildQueryWrapper(bo);
+        Page<CoopBatchReportVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        return TableDataInfo.build(result);
+    }
+
+    /**
+     * 查询报表信息列表
+     */
+    @Override
+    public List<CoopBatchReportVo> queryList(CoopBatchReportBo bo) {
+        LambdaQueryWrapper<CoopBatchReport> lqw = buildQueryWrapper(bo);
+        return baseMapper.selectVoList(lqw);
+    }
+
+    @Override
+    public CoopBatchReportVo queryByStaParam(QueryStaBo bo) {
+        LambdaQueryWrapper<CoopBatchReport> lqw = Wrappers.lambdaQuery();
+        lqw.eq(CoopBatchReport::getReportCycle, bo.getReportCycle());
+        lqw.eq(bo.getYear() != null && bo.getYear() > 0,CoopBatchReport::getYear, bo.getYear());
+        switch (bo.getReportCycle()) {
+            case "Q" ->
+                    lqw.eq(bo.getQuarter() != null && bo.getQuarter() > 0, CoopBatchReport::getQuarter, bo.getQuarter());
+            case "M" -> lqw.eq(bo.getMonth() != null && bo.getMonth() > 0, CoopBatchReport::getMonth, bo.getMonth());
+            case "D" -> {
+                lqw.eq(bo.getMonth() != null && bo.getMonth() > 0, CoopBatchReport::getMonth, bo.getMonth());
+                lqw.eq(bo.getDay() != null && bo.getDay() > 0, CoopBatchReport::getDay, bo.getDay());
+            }
+        }
+
+        CoopBatchReport coopBatchReport = baseMapper.selectOne(lqw);
+        if(coopBatchReport == null){
+            return null;
+        }
+        return MapstructUtils.convert(coopBatchReport, CoopBatchReportVo.class);
+    }
+
+    private LambdaQueryWrapper<CoopBatchReport> buildQueryWrapper(CoopBatchReportBo bo) {
+        Map<String, Object> params = bo.getParams();
+        LambdaQueryWrapper<CoopBatchReport> lqw = Wrappers.lambdaQuery();
+        lqw.eq(StringUtils.isNotBlank(bo.getTitle()), CoopBatchReport::getTitle, bo.getTitle());
+        lqw.eq(StringUtils.isNotBlank(bo.getReportCycle()), CoopBatchReport::getReportCycle, bo.getReportCycle());
+        lqw.eq(StringUtils.isNotBlank(bo.getReportType()), CoopBatchReport::getReportType, bo.getReportType());
+        lqw.eq(bo.getYear() != null, CoopBatchReport::getYear, bo.getYear());
+        lqw.eq(bo.getMonth() != null, CoopBatchReport::getMonth, bo.getMonth());
+        lqw.eq(bo.getDay() != null, CoopBatchReport::getDay, bo.getDay());
+        lqw.eq(bo.getQuarter() != null, CoopBatchReport::getQuarter, bo.getQuarter());
+        lqw.eq(bo.getLastSave0() != null, CoopBatchReport::getLastSave0, bo.getLastSave0());
+        lqw.eq(bo.getLastSave1() != null, CoopBatchReport::getLastSave1, bo.getLastSave1());
+        lqw.eq(bo.getSave0() != null, CoopBatchReport::getSave0, bo.getSave0());
+        lqw.eq(bo.getSave1() != null, CoopBatchReport::getSave1, bo.getSave1());
+        lqw.eq(bo.getCull0() != null, CoopBatchReport::getCull0, bo.getCull0());
+        lqw.eq(bo.getCull1() != null, CoopBatchReport::getCull1, bo.getCull1());
+        lqw.eq(bo.getIn0() != null, CoopBatchReport::getIn0, bo.getIn0());
+        lqw.eq(bo.getIn1() != null, CoopBatchReport::getIn1, bo.getIn1());
+        lqw.eq(bo.getOut0() != null, CoopBatchReport::getOut0, bo.getOut0());
+        lqw.eq(bo.getOut1() != null, CoopBatchReport::getOut1, bo.getOut1());
+        lqw.eq(bo.getQualifiedEgg() != null, CoopBatchReport::getQualifiedEgg, bo.getQualifiedEgg());
+        lqw.eq(bo.getDeformedEgg() != null, CoopBatchReport::getDeformedEgg, bo.getDeformedEgg());
+        lqw.eq(bo.getBreakEgg() != null, CoopBatchReport::getBreakEgg, bo.getBreakEgg());
+        lqw.eq(bo.getEggProductionRate() != null, CoopBatchReport::getEggProductionRate, bo.getEggProductionRate());
+        lqw.eq(bo.getEggPassRate() != null, CoopBatchReport::getEggPassRate, bo.getEggPassRate());
+        lqw.eq(bo.getChicken0() != null, CoopBatchReport::getChicken0, bo.getChicken0());
+        lqw.eq(bo.getChicken1() != null, CoopBatchReport::getChicken1, bo.getChicken1());
+        lqw.eq(bo.getLifeRate() != null, CoopBatchReport::getLifeRate, bo.getLifeRate());
+        lqw.eq(bo.getCullRate() != null, CoopBatchReport::getCullRate, bo.getCullRate());
+        return lqw;
+    }
+
+    /**
+     * 新增报表信息
+     */
+    @Override
+    public Boolean insertByBo(CoopBatchReportBo bo) {
+        CoopBatchReport add = MapstructUtils.convert(bo, CoopBatchReport. class);
+        validEntityBeforeSave(add);
+        boolean flag = baseMapper.insert(add) > 0;
+        if (flag) {
+            bo.setId(add.getId());
+        }
+        return flag;
+    }
+
+    /**
+     * 修改报表信息
+     */
+    @Override
+    public Boolean updateByBo(CoopBatchReportBo bo) {
+        CoopBatchReport update = MapstructUtils.convert(bo, CoopBatchReport. class);
+        validEntityBeforeSave(update);
+        return baseMapper.updateById(update) > 0;
+    }
+
+    /**
+     * 保存前的数据校验
+     */
+    private void validEntityBeforeSave(CoopBatchReport entity) {
+        //TODO 做一些数据校验,如唯一约束
+    }
+
+    /**
+     * 批量删除报表信息
+     */
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if (isValid) {
+            //TODO 做一些业务上的校验,判断是否需要校验
+        }
+        return baseMapper.deleteByIds(ids) > 0;
+    }
+}
+
+          
+        

+ 0 - 118
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/impl/CoopEggDayServiceImpl.java

@@ -1,118 +0,0 @@
-
-
-package cn.vber.breeding.service.impl;
-
-import cn.vber.common.core.utils.MapstructUtils;
-import cn.vber.common.core.utils.StringUtils;
-import cn.vber.common.mybatis.core.page.TableDataInfo;
-import cn.vber.common.mybatis.core.page.PageQuery;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import lombok.RequiredArgsConstructor;
-import org.springframework.stereotype.Service;
-import cn.vber.breeding.domain.bo.CoopEggDayBo;
-import cn.vber.breeding.domain.vo.CoopEggDayVo;
-import cn.vber.breeding.domain.CoopEggDay;
-import cn.vber.breeding.mapper.CoopEggDayMapper;
-import cn.vber.breeding.service.ICoopEggDayService;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Collection;
-
-/**
- * 鸡舍日产蛋记录Service业务层处理
- *
- * @author IwbY
- * @date 2025-07-31
- */
-@RequiredArgsConstructor
-@Service
-public class CoopEggDayServiceImpl implements ICoopEggDayService {
-
-    private final CoopEggDayMapper baseMapper;
-
-    /**
-     * 查询鸡舍日产蛋记录
-     */
-    @Override
-    public CoopEggDayVo queryById(Long id) {
-        return baseMapper.selectVoById(id);
-    }
-
-    /**
-     * 查询鸡舍日产蛋记录列表
-     */
-    @Override
-    public TableDataInfo<CoopEggDayVo> queryPageList(CoopEggDayBo bo, PageQuery pageQuery) {
-        LambdaQueryWrapper<CoopEggDay> lqw = buildQueryWrapper(bo);
-        Page<CoopEggDayVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
-        return TableDataInfo.build(result);
-    }
-
-    /**
-     * 查询鸡舍日产蛋记录列表
-     */
-    @Override
-    public List<CoopEggDayVo> queryList(CoopEggDayBo bo) {
-        LambdaQueryWrapper<CoopEggDay> lqw = buildQueryWrapper(bo);
-        return baseMapper.selectVoList(lqw);
-    }
-
-    private LambdaQueryWrapper<CoopEggDay> buildQueryWrapper(CoopEggDayBo bo) {
-        Map<String, Object> params = bo.getParams();
-        LambdaQueryWrapper<CoopEggDay> lqw = Wrappers.lambdaQuery();
-        lqw.eq(bo.getCoopId() != null, CoopEggDay::getCoopId, bo.getCoopId());
-        lqw.eq(bo.getEggCount() != null, CoopEggDay::getEggCount, bo.getEggCount());
-        lqw.eq(bo.getEggType() != null, CoopEggDay::getEggType, bo.getEggType());
-        lqw.between(StringUtils.isNotEmpty(params.get("beginLayDate")) && StringUtils.isNotEmpty(params.get("endLayDate")),
-                CoopEggDay::getLayDate , params.get("beginLayDate"), params.get("endLayDate"));
-        return lqw;
-    }
-
-    /**
-     * 新增鸡舍日产蛋记录
-     */
-    @Override
-    public Boolean insertByBo(CoopEggDayBo bo) {
-        CoopEggDay add = MapstructUtils.convert(bo, CoopEggDay. class);
-        validEntityBeforeSave(add);
-        boolean flag = baseMapper.insert(add) > 0;
-        if (flag) {
-            bo.setId(add.getId());
-        }
-        return flag;
-    }
-
-    /**
-     * 修改鸡舍日产蛋记录
-     */
-    @Override
-    public Boolean updateByBo(CoopEggDayBo bo) {
-        CoopEggDay update = MapstructUtils.convert(bo, CoopEggDay. class);
-        validEntityBeforeSave(update);
-        return baseMapper.updateById(update) > 0;
-    }
-
-    /**
-     * 保存前的数据校验
-     */
-    private void validEntityBeforeSave(CoopEggDay entity) {
-        //TODO 做一些数据校验,如唯一约束
-    }
-
-    /**
-     * 批量删除鸡舍日产蛋记录
-     */
-    @Override
-    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
-        if (isValid) {
-            //TODO 做一些业务上的校验,判断是否需要校验
-        }
-        return baseMapper.deleteByIds(ids) > 0;
-    }
-}
-
-          
-        

+ 6 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/impl/MeasureServiceImpl.java

@@ -2,12 +2,14 @@
 
 package cn.vber.breeding.service.impl;
 
+import cn.vber.base.constant.CommonConstant;
 import cn.vber.base.enums.BatchStatusEnum;
 import cn.vber.breeding.domain.MeasureDetail;
 import cn.vber.breeding.domain.vo.BatchVo;
 import cn.vber.breeding.domain.vo.MeasureDetailVo;
 import cn.vber.breeding.mapper.MeasureDetailMapper;
 import cn.vber.breeding.service.ICommonService;
+import cn.vber.breeding.service.IStatisticsService;
 import cn.vber.common.core.exception.ServiceException;
 import cn.vber.common.core.utils.ChickenCalcUtils;
 import cn.vber.common.core.utils.MapstructUtils;
@@ -44,6 +46,7 @@ public class MeasureServiceImpl implements IMeasureService {
     private final ICommonService commonService;
     private final MeasureDetailMapper measureDetailMapper;
 
+
     /**
      * 查询测定管理
      */
@@ -152,6 +155,9 @@ public class MeasureServiceImpl implements IMeasureService {
         }
         return baseMapper.deleteByIds(ids) > 0;
     }
+
+
+
 }
 
           

+ 284 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/impl/SopServiceImpl.java

@@ -0,0 +1,284 @@
+package cn.vber.breeding.service.impl;
+
+import cn.vber.base.domain.vo.DrugSopVo;
+import cn.vber.base.domain.vo.FeedSopVo;
+import cn.vber.base.domain.vo.VaccineSopVo;
+import cn.vber.base.mapper.DrugSopMapper;
+import cn.vber.base.mapper.FeedSopMapper;
+import cn.vber.base.mapper.VaccineSopMapper;
+import cn.vber.breeding.domain.*;
+import cn.vber.breeding.domain.vo.sop.SopBindLogVo;
+import cn.vber.breeding.mapper.*;
+import cn.vber.breeding.service.ISopService;
+import cn.vber.common.core.utils.ChickenCalcUtils;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.BiFunction;
+
+@RequiredArgsConstructor
+@Service
+public class SopServiceImpl implements ISopService {
+    private final ChickenFeedMapper chickenFeedMapper;
+    private final ChickenDrugMapper chickenDrugMapper;
+    private final ChickenVaccineMapper chickenVaccineMapper;
+    private final BatchFeedMapper batchFeedMapper;
+    private final BatchDrugMapper batchDrugMapper;
+    private final BatchVaccineMapper batchVaccineMapper;
+    private final DrugSopMapper drugSopMapper;
+    private final VaccineSopMapper vaccineSopMapper;
+    private final FeedSopMapper feedSopMapper;
+    private final BatchMapper batchMapper;
+
+//    @Override
+//    public List<SopBindLogVo> queryChickenFeedRecord(Long chickenId, String batchNum) {
+//        Batch batch = batchMapper.selectOne(new LambdaQueryWrapper<Batch>().eq(Batch::getBatchNum, batchNum));
+//        List<BatchFeed> batchFeeds = batchFeedMapper.selectList(new LambdaQueryWrapper<BatchFeed>().eq(BatchFeed::getBatchNum, batchNum));
+//        List<ChickenFeed> chickenFeeds = chickenFeedMapper.selectList(new LambdaQueryWrapper<ChickenFeed>()
+//                .eq(ChickenFeed::getChickenId, chickenId));
+//        List<FeedSopVo> feedSopVos = feedSopMapper.selectVoList();
+//        List<SopBindLogVo> sopBindLogVos = new ArrayList<>();
+//        for (BatchFeed batchFeed : batchFeeds) {
+//            SopBindLogVo sopBindLogVo = new SopBindLogVo();
+//            sopBindLogVo.setBatchNum(batchFeed.getBatchNum());
+//            Optional<FeedSopVo> first = feedSopVos.stream().filter(feedSopVo -> feedSopVo.getId().equals(batchFeed.getFeedSopId()))
+//                    .findFirst();
+//            first.ifPresent(feedSopVo -> sopBindLogVo.setSopName(feedSopVo.getSopName()));
+//            sopBindLogVo.setSopId(batchFeed.getFeedSopId());
+//            sopBindLogVo.setBindTime(batchFeed.getCreateTime());
+//            sopBindLogVo.setBindAge(ChickenCalcUtils.calcChickenAge(batchFeed.getCreateTime(),batch.getHatchDate()));
+//            sopBindLogVo.setStatus(batchFeed.getStatus());
+//            sopBindLogVos.add(sopBindLogVo);
+//        }
+//        for (ChickenFeed chickenFeed : chickenFeeds) {
+//            SopBindLogVo sopBindLogVo = new SopBindLogVo();
+//            sopBindLogVo.setBatchNum(batchNum);
+//            Optional<FeedSopVo> first = feedSopVos.stream().filter(feedSopVo -> feedSopVo.getId().equals(chickenFeed.getFeedSopId()))
+//                    .findFirst();
+//            first.ifPresent(feedSopVo -> sopBindLogVo.setSopName(feedSopVo.getSopName()));
+//            sopBindLogVo.setSopId(chickenFeed.getFeedSopId());
+//            sopBindLogVo.setBindTime(chickenFeed.getCreateTime());
+//            sopBindLogVo.setBindAge(ChickenCalcUtils.calcChickenAge(chickenFeed.getCreateTime(),batch.getHatchDate()));
+//            sopBindLogVo.setStatus(chickenFeed.getStatus());
+//            sopBindLogVos.add(sopBindLogVo);
+//        }
+//        sopBindLogVos.sort((o1, o2) -> o2.getBindTime().compareTo(o1.getBindTime()));
+//        return sopBindLogVos;
+//    }
+//
+//    @Override
+//    public List<SopBindLogVo> queryChickenDrugRecord(Long chickenId,String batchNum) {
+//        Batch batch = batchMapper.selectOne(new LambdaQueryWrapper<Batch>().eq(Batch::getBatchNum, batchNum));
+//        List<BatchDrug> batchDrugs = batchDrugMapper.selectList(new LambdaQueryWrapper<BatchDrug>().eq(BatchDrug::getBatchNum, batchNum));
+//        List<ChickenDrug> chickenDrugs = chickenDrugMapper.selectList(new LambdaQueryWrapper<ChickenDrug>()
+//                .eq(ChickenDrug::getChickenId, chickenId));
+//        List<DrugSopVo> feedSopVos = drugSopMapper.selectVoList();
+//        List<SopBindLogVo> sopBindLogVos = new ArrayList<>();
+//        for (BatchDrug batchDrug : batchDrugs) {
+//            SopBindLogVo sopBindLogVo = new SopBindLogVo();
+//            sopBindLogVo.setBatchNum(batchDrug.getBatchNum());
+//            Optional<DrugSopVo> first = feedSopVos.stream().filter(drugSopVo -> drugSopVo.getId().equals(batchDrug.getDrugSopId()))
+//                    .findFirst();
+//            first.ifPresent(feedSopVo -> sopBindLogVo.setSopName(feedSopVo.getSopName()));
+//            sopBindLogVo.setSopId(batchDrug.getDrugSopId());
+//            sopBindLogVo.setBindTime(batchDrug.getCreateTime());
+//            sopBindLogVo.setBindAge(ChickenCalcUtils.calcChickenAge(batchDrug.getCreateTime(),batch.getHatchDate()));
+//            sopBindLogVo.setStatus(batchDrug.getStatus());
+//            sopBindLogVos.add(sopBindLogVo);
+//        }
+//        for (ChickenDrug chickenDrug : chickenDrugs) {
+//            SopBindLogVo sopBindLogVo = new SopBindLogVo();
+//            sopBindLogVo.setBatchNum(batchNum);
+//            Optional<DrugSopVo> first = feedSopVos.stream().filter(feedSopVo -> feedSopVo.getId().equals(chickenDrug.getDrugSopId()))
+//                    .findFirst();
+//            first.ifPresent(drugSopVo -> sopBindLogVo.setSopName(drugSopVo.getSopName()));
+//            sopBindLogVo.setSopId(chickenDrug.getDrugSopId());
+//            sopBindLogVo.setBindTime(chickenDrug.getCreateTime());
+//            sopBindLogVo.setBindAge(ChickenCalcUtils.calcChickenAge(chickenDrug.getCreateTime(),batch.getHatchDate()));
+//            sopBindLogVo.setStatus(chickenDrug.getStatus());
+//            sopBindLogVos.add(sopBindLogVo);
+//        }
+//        sopBindLogVos.sort((o1, o2) -> o2.getBindTime().compareTo(o1.getBindTime()));
+//        return sopBindLogVos;
+//    }
+
+//    @Override
+//    public List<SopBindLogVo> queryChickenVaccineRecord(Long chickenId,String batchNum) {
+//        Batch batch = batchMapper.selectOne(new LambdaQueryWrapper<Batch>().eq(Batch::getBatchNum, batchNum));
+//        List<BatchVaccine> batchVaccines = batchVaccineMapper.selectList(new LambdaQueryWrapper<BatchVaccine>().eq(BatchVaccine::getBatchNum, batchNum));
+//        List<ChickenVaccine> chickenVaccines = chickenVaccineMapper.selectList(new LambdaQueryWrapper<ChickenVaccine>()
+//                .eq(ChickenVaccine::getChickenId, chickenId));
+//        List<VaccineSopVo> vaccineSopVos = vaccineSopMapper.selectVoList();
+//        List<SopBindLogVo> sopBindLogVos = new ArrayList<>();
+//        for (BatchVaccine batchVaccine : batchVaccines) {
+//            SopBindLogVo sopBindLogVo = new SopBindLogVo();
+//            sopBindLogVo.setBatchNum(batchVaccine.getBatchNum());
+//            Optional<VaccineSopVo> first = vaccineSopVos.stream().filter(vaccineSopVo -> vaccineSopVo.getId().equals(batchVaccine.getVaccineSopId()))
+//                    .findFirst();
+//            first.ifPresent(vaccineSopVo -> sopBindLogVo.setSopName(vaccineSopVo.getSopName()));
+//            sopBindLogVo.setSopId(batchVaccine.getVaccineSopId());
+//            sopBindLogVo.setBindTime(batchVaccine.getCreateTime());
+//            sopBindLogVo.setBindAge(ChickenCalcUtils.calcChickenAge(batchVaccine.getCreateTime(),batch.getHatchDate()));
+//            sopBindLogVo.setStatus(batchVaccine.getStatus());
+//            sopBindLogVos.add(sopBindLogVo);
+//        }
+//        for (ChickenVaccine chickenVaccine : chickenVaccines) {
+//            SopBindLogVo sopBindLogVo = new SopBindLogVo();
+//            sopBindLogVo.setBatchNum(batchNum);
+//            Optional<VaccineSopVo> first = vaccineSopVos.stream().filter(vaccineSopVo -> vaccineSopVo.getId().equals(chickenVaccine.getVaccineSopId()))
+//                    .findFirst();
+//            first.ifPresent(vaccineSopVo -> sopBindLogVo.setSopName(vaccineSopVo.getSopName()));
+//            sopBindLogVo.setSopId(chickenVaccine.getVaccineSopId());
+//            sopBindLogVo.setBindTime(chickenVaccine.getCreateTime());
+//            sopBindLogVo.setBindAge(ChickenCalcUtils.calcChickenAge(chickenVaccine.getCreateTime(),batch.getHatchDate()));
+//            sopBindLogVo.setStatus(chickenVaccine.getStatus());
+//            sopBindLogVos.add(sopBindLogVo);
+//        }
+//        sopBindLogVos.sort((o1, o2) -> o2.getBindTime().compareTo(o1.getBindTime()));
+//        return sopBindLogVos;
+//    }
+
+    @Override
+    public List<SopBindLogVo> queryChickenFeedRecord(Long chickenId, String batchNum) {
+        Batch batch = batchMapper.selectOne(new LambdaQueryWrapper<Batch>().eq(Batch::getBatchNum, batchNum));
+        List<BatchFeed> batchFeeds = batchFeedMapper.selectList(new LambdaQueryWrapper<BatchFeed>().eq(BatchFeed::getBatchNum, batchNum));
+        List<ChickenFeed> chickenFeeds = chickenFeedMapper.selectList(new LambdaQueryWrapper<ChickenFeed>()
+                .eq(ChickenFeed::getChickenId, chickenId).orderByAsc(ChickenFeed::getCreateTime));
+        var first = chickenFeeds.isEmpty() ? null : chickenFeeds.get(0);
+        List<FeedSopVo> feedSopVos = feedSopMapper.selectVoList();
+        List<SopBindLogVo> sopBindLogVos = new ArrayList<>();
+
+        // 处理个体饲料记录
+        for (ChickenFeed chickenFeed : chickenFeeds) {
+            SopBindLogVo sopBindLogVo = createSopBindLogVo(batchNum, chickenFeed.getFeedSopId(),
+                    chickenFeed.getCreateTime(), chickenFeed.getStatus(), feedSopVos, batch,"个体");
+
+            sopBindLogVos.add(sopBindLogVo);
+        }
+
+        // 处理批次饲料记录
+        for (BatchFeed batchFeed : batchFeeds) {
+            if(first != null && first.getCreateTime().before(batchFeed.getCreateTime())){
+                continue;
+            }
+            SopBindLogVo sopBindLogVo = createSopBindLogVo(batchFeed.getBatchNum(), batchFeed.getFeedSopId(),
+                    batchFeed.getCreateTime(), batchFeed.getStatus(), feedSopVos, batch,"批次");
+            sopBindLogVos.add(sopBindLogVo);
+        }
+
+        sopBindLogVos.sort((o1, o2) -> o2.getBindTime().compareTo(o1.getBindTime()));
+        return sopBindLogVos;
+    }
+
+    @Override
+    public List<SopBindLogVo> queryChickenDrugRecord(Long chickenId, String batchNum) {
+        Batch batch = batchMapper.selectOne(new LambdaQueryWrapper<Batch>().eq(Batch::getBatchNum, batchNum));
+        List<BatchDrug> batchDrugs = batchDrugMapper.selectList(new LambdaQueryWrapper<BatchDrug>().eq(BatchDrug::getBatchNum, batchNum));
+        List<ChickenDrug> chickenDrugs = chickenDrugMapper.selectList(new LambdaQueryWrapper<ChickenDrug>()
+                .eq(ChickenDrug::getChickenId, chickenId).orderByAsc(ChickenDrug::getCreateTime));
+        var first = chickenDrugs.isEmpty() ? null : chickenDrugs.get(0);
+        List<DrugSopVo> drugSopVos = drugSopMapper.selectVoList();
+        List<SopBindLogVo> sopBindLogVos = new ArrayList<>();
+
+
+
+        // 处理个体用药记录
+        for (ChickenDrug chickenDrug : chickenDrugs) {
+            SopBindLogVo sopBindLogVo = createSopBindLogVo(batchNum, chickenDrug.getDrugSopId(),
+                    chickenDrug.getCreateTime(), chickenDrug.getStatus(), drugSopVos, batch,"个体");
+            sopBindLogVos.add(sopBindLogVo);
+        }
+        // 处理批次用药记录
+        for (BatchDrug batchDrug : batchDrugs) {
+            if(first != null && first.getCreateTime().before(batchDrug.getCreateTime())){
+                continue;
+            }
+            SopBindLogVo sopBindLogVo = createSopBindLogVo(batchDrug.getBatchNum(), batchDrug.getDrugSopId(),
+                    batchDrug.getCreateTime(), batchDrug.getStatus(), drugSopVos, batch,"批次");
+            sopBindLogVos.add(sopBindLogVo);
+        }
+        sopBindLogVos.sort((o1, o2) -> o2.getBindTime().compareTo(o1.getBindTime()));
+        return sopBindLogVos;
+    }
+
+    @Override
+    public List<SopBindLogVo> queryChickenVaccineRecord(Long chickenId, String batchNum) {
+        Batch batch = batchMapper.selectOne(new LambdaQueryWrapper<Batch>().eq(Batch::getBatchNum, batchNum));
+        List<BatchVaccine> batchVaccines = batchVaccineMapper.selectList(new LambdaQueryWrapper<BatchVaccine>().eq(BatchVaccine::getBatchNum, batchNum));
+        List<ChickenVaccine> chickenVaccines = chickenVaccineMapper.selectList(new LambdaQueryWrapper<ChickenVaccine>()
+                .eq(ChickenVaccine::getChickenId, chickenId));
+        var first = chickenVaccines.isEmpty() ? null : chickenVaccines.get(0);
+        List<VaccineSopVo> vaccineSopVos = vaccineSopMapper.selectVoList();
+        List<SopBindLogVo> sopBindLogVos = new ArrayList<>();
+
+
+
+        // 处理个体疫苗记录
+        for (ChickenVaccine chickenVaccine : chickenVaccines) {
+            SopBindLogVo sopBindLogVo = createSopBindLogVo(batchNum, chickenVaccine.getVaccineSopId(),
+                    chickenVaccine.getCreateTime(), chickenVaccine.getStatus(), vaccineSopVos, batch,"个体");
+            sopBindLogVos.add(sopBindLogVo);
+        }
+       // 处理批次疫苗记录
+        for (BatchVaccine batchVaccine : batchVaccines) {
+            if(first != null && first.getCreateTime().before(batchVaccine.getCreateTime())){
+                continue;
+            }
+            SopBindLogVo sopBindLogVo = createSopBindLogVo(batchVaccine.getBatchNum(), batchVaccine.getVaccineSopId(),
+                    batchVaccine.getCreateTime(), batchVaccine.getStatus(), vaccineSopVos, batch,"批次");
+            sopBindLogVos.add(sopBindLogVo);
+        }
+        sopBindLogVos.sort((o1, o2) -> o2.getBindTime().compareTo(o1.getBindTime()));
+        return sopBindLogVos;
+    }
+    /**
+     * 创建SopBindLogVo对象的通用方法
+     */
+    private <T> SopBindLogVo createSopBindLogVo(String batchNum, Long sopId,
+                                                java.util.Date bindTime, Integer status,
+                                                List<T> sopVos, Batch batch,String typeName) {
+        SopBindLogVo sopBindLogVo = new SopBindLogVo();
+        sopBindLogVo.setBatchNum(batchNum);
+        sopBindLogVo.setSopId(sopId);
+        sopBindLogVo.setBindTime(bindTime);
+        sopBindLogVo.setStatus(status);
+
+        // 设置SOP名称
+        if (sopVos != null && !sopVos.isEmpty()) {
+            Optional<T> first = sopVos.stream()
+                    .filter(sop -> {
+                        if (sop instanceof FeedSopVo) {
+                            return ((FeedSopVo) sop).getId().equals(sopId);
+                        } else if (sop instanceof DrugSopVo) {
+                            return ((DrugSopVo) sop).getId().equals(sopId);
+                        } else if (sop instanceof VaccineSopVo) {
+                            return ((VaccineSopVo) sop).getId().equals(sopId);
+                        }
+                        return false;
+                    })
+                    .findFirst();
+            first.ifPresent(sop -> {
+                if (sop instanceof FeedSopVo) {
+                    sopBindLogVo.setSopName(((FeedSopVo) sop).getSopName());
+                } else if (sop instanceof DrugSopVo) {
+                    sopBindLogVo.setSopName(((DrugSopVo) sop).getSopName());
+                } else if (sop instanceof VaccineSopVo) {
+                    sopBindLogVo.setSopName(((VaccineSopVo) sop).getSopName());
+                }
+            });
+        }
+
+        // 计算鸡龄
+        if (batch != null &&  bindTime != null) {
+            sopBindLogVo.setBindAge(ChickenCalcUtils.calcChickenAge(bindTime, batch.getHatchDate()));
+        }
+        sopBindLogVo.setTypeName(typeName);
+        return sopBindLogVo;
+    }
+   
+
+}

+ 402 - 0
SERVER/ChickenFarmV3/vb-modules/vb-breeding/src/main/java/cn/vber/breeding/service/impl/StatisticsHelperServiceImpl.java

@@ -0,0 +1,402 @@
+package cn.vber.breeding.service.impl;
+
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.IdUtil;
+import cn.vber.base.enums.EggTypeEnum;
+import cn.vber.breeding.domain.CoopBatchReport;
+import cn.vber.breeding.domain.CoopBatchReportDetail;
+import cn.vber.breeding.domain.bo.statistic.QueryStaBo;
+import cn.vber.breeding.domain.bo.statistic.QueryStaScopeParam;
+import cn.vber.breeding.domain.bo.statistic.QueryStaScopeParamBo;
+import cn.vber.breeding.domain.vo.CoopBatchReportVo;
+import cn.vber.breeding.domain.vo.statistic.*;
+import cn.vber.breeding.mapper.CoopBatchReportDetailMapper;
+import cn.vber.breeding.mapper.CoopBatchReportMapper;
+import cn.vber.breeding.service.ICommonService;
+import cn.vber.breeding.service.IStatisticsHelperService;
+import cn.vber.common.core.exception.ServiceException;
+import cn.vber.common.core.utils.DateUtils;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+@RequiredArgsConstructor
+@Service
+@Slf4j
+public class StatisticsHelperServiceImpl implements IStatisticsHelperService {
+
+    private final CoopBatchReportMapper reportMapper;
+    private final CoopBatchReportDetailMapper reportDetailMapper;
+    private final CoopBatchReportDetailMapper coopBatchReportDetailMapper;
+    private final ICommonService commonService;
+
+    @Transactional
+    @Override
+    public void statisticDay(QueryStaBo input){
+        log.info("--------------开始日统计--------------");
+        QueryStaScopeParam param = commonService.convertQueryStaToParam(input);
+        Map<String, StatisticTmpResultDto> tmpResultMap = new HashMap<>();
+        //统计出当日个体个数
+        List<CoopBatchChickenStatisticResultVo> chickenStatistics = reportDetailMapper.selectChickenCount(param);
+        for (CoopBatchChickenStatisticResultVo resultVo : chickenStatistics) {
+            String key = resultVo.getCoopId() + "_" + resultVo.getBatchNum();
+            StatisticTmpResultDto tmpResult = tmpResultMap.computeIfAbsent(key,k->new StatisticTmpResultDto());
+            tmpResult.setCoopId(resultVo.getCoopId());
+            tmpResult.setBatchNum(resultVo.getBatchNum());
+            if(resultVo.getGender() == 0){
+                tmpResult.setChicken0(resultVo.getChickenCount());
+            }else if(resultVo.getGender() == 1){
+                tmpResult.setChicken1(resultVo.getChickenCount());
+            }
+        }
+        //统计出淘汰数,转入,转出,蛋的统计
+        statisticCommon(tmpResultMap,param);
+        //fillFemaleCountAll(tmpResultMap,param);
+        fillLastCycle(tmpResultMap,param);
+
+        tmpResultMap.forEach((k,v)->{
+            calcCommon(v);
+        });
+        insertReport(input,tmpResultMap);
+    }
+    @Transactional
+    @Override
+    public void statisticMonthOrYearOrQuarter(QueryStaBo input){
+        log.info("--------------开始月/年/季度统计--------------");
+        QueryStaScopeParam param = commonService.convertQueryStaToParam(input);
+        Map<String, StatisticTmpResultDto> tmpResultMap = new HashMap<>();
+        //统计出淘汰数,转入,转出,蛋的统计
+        statisticCommon(tmpResultMap,param);
+        //填充母鸡数量的每日总和
+        fillFemaleCountAll(tmpResultMap,param);
+        //填充上一次周期的统计
+        fillLastCycle(tmpResultMap,param);
+
+        tmpResultMap.forEach((k,v)->{
+            calcCommon(v);
+        });
+        insertReport(input,tmpResultMap);
+
+    }
+
+   //插入统计表中
+
+    private void insertReport(QueryStaBo input, Map<String, StatisticTmpResultDto> tmpResultMap){
+        deleteHistory(input);
+        CoopBatchReport report = new CoopBatchReport();
+        String title = Objects.equals(input.getReportCycle(), "Y") ? "年" : Objects.equals(input.getReportCycle(), "Q")
+                ? "季度" : Objects.equals(input.getReportCycle(), "M") ? "月" : "日" + "统计";
+        String reportId = IdUtil.simpleUUID();
+        report.setId(reportId);
+        report.setTitle(title);
+        report.setYear(input.getYear());
+        report.setReportCycle(input.getReportCycle());
+        report.setMonth(input.getMonth());
+        report.setDay(input.getDay());
+        report.setQuarter(input.getQuarter());
+        report.setReportType(input.getCoopType());
+        //临时头报表统计数据
+        StatisticTmpResultDto tmpAll = new StatisticTmpResultDto();
+        // 1. 使用entrySet()遍历键值对
+        for (Map.Entry<String, StatisticTmpResultDto> entry : tmpResultMap.entrySet()) {
+            String key = entry.getKey();
+            StatisticTmpResultDto value = entry.getValue();
+            // 处理key和value
+            //System.out.println("Key: " + key + ", Value: " + value);
+            CoopBatchReportDetail detail = new CoopBatchReportDetail();
+            detail.setReportId(reportId);
+            detail.setCoopId(value.getCoopId());
+            detail.setBatchNum(value.getBatchNum());
+            detail.setReportDate(getReportDate(input));
+            detail.setReportCycle(input.getReportCycle());
+            detail.setLastSave0(value.getLastSave0());
+            tmpAll.setLastSave0(tmpAll.getLastSave0() + value.getLastSave0());
+            detail.setLastSave1(value.getLastSave1());
+            tmpAll.setLastSave1(tmpAll.getLastSave1() + value.getLastSave1());
+            detail.setSave0(value.getSave0());
+            detail.setSave1(value.getSave1());
+            detail.setCull0(value.getCull0());
+            tmpAll.setCull0(tmpAll.getCull0() + value.getCull0());
+            detail.setCull1(value.getCull1());
+            tmpAll.setCull1(tmpAll.getCull1() + value.getCull1());
+            detail.setIn0(value.getIn0());
+            tmpAll.setIn0(tmpAll.getIn0() + value.getIn0());
+            detail.setIn1(value.getIn1());
+            tmpAll.setIn1(tmpAll.getIn1() + value.getIn1());
+            detail.setOut0(value.getOut0());
+            tmpAll.setOut0(tmpAll.getOut0() + value.getOut0());
+            detail.setOut1(value.getOut1());
+            tmpAll.setOut1(tmpAll.getOut1() + value.getOut1());
+            detail.setChicken0(value.getChicken0());
+            tmpAll.setChicken0(tmpAll.getChicken0() + value.getChicken0());
+            detail.setChicken1(value.getChicken1());
+            tmpAll.setChicken1(tmpAll.getChicken1() + value.getChicken1());
+            detail.setQualifiedEgg(value.getQualifiedEgg());
+            tmpAll.setQualifiedEgg(tmpAll.getQualifiedEgg() + value.getQualifiedEgg());
+            detail.setDeformedEgg(value.getDeformedEgg());
+            tmpAll.setDeformedEgg(tmpAll.getDeformedEgg() + value.getDeformedEgg());
+            detail.setBreakEgg(value.getBreakEgg());
+            tmpAll.setBreakEgg(tmpAll.getBreakEgg() + value.getBreakEgg());
+            detail.setEggPassRate(value.getEggPassRate());
+            detail.setEggProductionRate(value.getEggProductionRate());
+            detail.setLifeRate(value.getLifeRate());
+            detail.setCullRate(value.getCullRate());
+            detail.setCreateOrg(201L);
+            reportDetailMapper.insert(detail);
+        }
+        calcCommon(tmpAll);
+        report.setLastSave0(tmpAll.getLastSave0());
+        report.setLastSave1(tmpAll.getLastSave1());
+        report.setSave0(tmpAll.getSave0());
+        report.setSave1(tmpAll.getSave1());
+        report.setCull0(tmpAll.getCull0());
+        report.setCull1(tmpAll.getCull1());
+        report.setIn0(tmpAll.getIn0());
+        report.setIn1(tmpAll.getIn1());
+        report.setOut0(tmpAll.getOut0());
+        report.setOut1(tmpAll.getOut1());
+        report.setChicken0(tmpAll.getChicken0());
+        report.setChicken1(tmpAll.getChicken1());
+        report.setQualifiedEgg(tmpAll.getQualifiedEgg());
+        report.setDeformedEgg(tmpAll.getDeformedEgg());
+        report.setBreakEgg(tmpAll.getBreakEgg());
+        report.setEggPassRate(tmpAll.getEggPassRate());
+        report.setEggProductionRate(tmpAll.getEggProductionRate());
+        report.setLifeRate(tmpAll.getLifeRate());
+        report.setCullRate(tmpAll.getCullRate());
+        reportMapper.insert(report);
+    }
+    //删除之前统计数据
+    private void deleteHistory(QueryStaBo input){
+        LambdaQueryWrapper<CoopBatchReport> law = new LambdaQueryWrapper<>(CoopBatchReport.class)
+                .eq(CoopBatchReport::getReportCycle, input.getReportCycle())
+                .eq(CoopBatchReport::getYear, input.getYear())
+                .eq(input.getMonth()!=null &&input.getMonth() > 0,CoopBatchReport::getMonth, input.getMonth())
+                .eq(input.getDay()!=null &&input.getDay() > 0,CoopBatchReport::getDay, input.getDay())
+                .eq(input.getQuarter()!=null &&input.getQuarter() > 0,CoopBatchReport::getQuarter, input.getQuarter());
+        List<CoopBatchReport> coopBatchReports = reportMapper.selectList(law);
+        if(!coopBatchReports.isEmpty()){
+            //reportMapper.deleteBatchIds(coopBatchReports);
+            coopBatchReports.forEach(report -> {
+                reportDetailMapper.delete(new LambdaQueryWrapper<>(CoopBatchReportDetail.class)
+                        .eq(CoopBatchReportDetail::getReportId, report.getId()));
+            });
+        }
+        reportMapper.delete(law);
+    }
+    //统计月/季度/年 中所有天数中母鸡的总数 chicken1 ,日的不统计
+    private void fillFemaleCountAll(Map<String, StatisticTmpResultDto> map,QueryStaScopeParam queryScopeParam) {
+        Map<String, SumFemaleCountTmpDto> sumFemaleCountTmpDtoMap = queryFemaleCountAll(queryScopeParam);
+        map.forEach((k,v)->{
+            SumFemaleCountTmpDto sumFemaleDto = sumFemaleCountTmpDtoMap.get(k);
+            if(sumFemaleDto != null){
+                v.setChicken1(sumFemaleDto.getChickenAll1());
+            }
+        });
+    }
+    private void fillLastCycle(Map<String, StatisticTmpResultDto> map,QueryStaScopeParam queryScopeParam) {
+        Map<String, CoopBatchReportDetail> coopBatchReportDetailMap = queryLastCycleReportDetail(queryScopeParam);
+        if(coopBatchReportDetailMap==null || coopBatchReportDetailMap.isEmpty()){
+            log.info("--------------没有上一周期数据--------------");
+            return;
+        }
+        map.forEach((k,v)->{
+            CoopBatchReportDetail detail = coopBatchReportDetailMap.get(k);
+            if(detail != null){
+                v.setLastSave0(detail.getSave0());
+                v.setLastSave1(detail.getSave1());
+            }
+
+        });
+    }
+
+    private Map<String, SumFemaleCountTmpDto> queryFemaleCountAll(QueryStaScopeParam queryScopeParam){
+        List<ChickenStatisticDayResultVo> chickenStatisticDayResultVos =
+                coopBatchReportDetailMapper.selectChickenCountDay(queryScopeParam);
+        Map<String, SumFemaleCountTmpDto> map = new HashMap<>();
+        for (ChickenStatisticDayResultVo chickenStatisticDayResultVo : chickenStatisticDayResultVos) {
+            String key = chickenStatisticDayResultVo.getCoopId() + "_" + chickenStatisticDayResultVo.getBatchNum();
+            SumFemaleCountTmpDto sumFemaleDto = map.computeIfAbsent(key, k -> new SumFemaleCountTmpDto());
+            sumFemaleDto.setBatchNum(chickenStatisticDayResultVo.getBatchNum());
+            sumFemaleDto.setCoopId(chickenStatisticDayResultVo.getCoopId());
+            Integer chickenAll1 = sumFemaleDto.getChickenAll1();
+            sumFemaleDto.setChickenAll1(chickenAll1 + chickenStatisticDayResultVo.getChicken1());
+        }
+        return map;
+    }
+
+    /**
+     * 获取上一周期数据
+     * @param queryScopeParam
+     * @return  Map<String,CoopBatchReportDetail>
+     */
+    private Map<String,CoopBatchReportDetail> queryLastCycleReportDetail(QueryStaScopeParam queryScopeParam){
+        QueryStaBo queryLastStaBo = commonService.getLastCycle(queryScopeParam.getStartDate(), queryScopeParam.getReportCycle());
+        LambdaQueryWrapper<CoopBatchReport> law = new LambdaQueryWrapper<>(CoopBatchReport.class)
+                .eq(CoopBatchReport::getReportCycle, queryLastStaBo.getReportCycle())
+                .eq(CoopBatchReport::getYear, queryLastStaBo.getYear())
+                .eq((queryLastStaBo.getMonth()!=null && queryLastStaBo.getMonth() > 0),CoopBatchReport::getMonth, queryLastStaBo.getMonth())
+                .eq(queryLastStaBo.getDay()!=null && queryLastStaBo.getDay() > 0,CoopBatchReport::getDay, queryLastStaBo.getDay())
+                .eq(queryLastStaBo.getQuarter()!=null && queryLastStaBo.getQuarter() > 0,CoopBatchReport::getQuarter, queryLastStaBo.getQuarter());
+        try {
+            CoopBatchReport coopBatchReport = reportMapper.selectOne(law);
+            if(coopBatchReport == null){
+                log.error("没有查询到上一周期数据-{}-{}-{}-{}-{}"
+                        ,queryLastStaBo.getReportCycle(),queryLastStaBo.getYear()
+                        ,queryLastStaBo.getMonth(),queryLastStaBo.getDay()
+                        ,queryLastStaBo.getQuarter());
+                return null;
+            }
+            LambdaQueryWrapper<CoopBatchReportDetail> law1 = new LambdaQueryWrapper<>(CoopBatchReportDetail.class)
+                    .eq(CoopBatchReportDetail::getReportId, coopBatchReport.getId());
+
+            List<CoopBatchReportDetail> coopBatchReportDetails = reportDetailMapper.selectList(law1);
+            Map<String, CoopBatchReportDetail> map = new HashMap<>();
+            for (CoopBatchReportDetail coopBatchReportDetail : coopBatchReportDetails) {
+                String key = coopBatchReportDetail.getCoopId() + "_" + coopBatchReportDetail.getBatchNum();
+                map.computeIfAbsent(key, k->coopBatchReportDetail);
+            }
+            return map;
+        }catch (Exception e){
+            log.error("查询上一周期数据失败",e);
+            return null;
+        }
+    }
+
+
+
+    /**
+     * 计算通用数据
+     * @param tmpResult
+     */
+    @Override
+    public void calcCommon(StatisticTmpResultDto tmpResult){
+        tmpResult.setSave0(tmpResult.getIn0() - tmpResult.getOut0() - tmpResult.getCull0());
+        tmpResult.setSave1(tmpResult.getIn1() - tmpResult.getOut1() - tmpResult.getCull1());
+        int cultCount = tmpResult.getCull0() + tmpResult.getCull1();
+        int lastSave = tmpResult.getLastSave0() + tmpResult.getLastSave1();
+        int inCount = tmpResult.getIn0() + tmpResult.getIn1();
+        int outCount = tmpResult.getOut0() + tmpResult.getOut1();
+        int d2 = lastSave + inCount - outCount;
+        if(cultCount == 0 || d2 == 0){
+            tmpResult.setCullRate(0f);
+        }
+        if(d2==0 || cultCount==0){
+            tmpResult.setCullRate(0f);
+            tmpResult.setLifeRate(0f);
+        }else{
+            float  cultRate = (float) cultCount / d2;
+            float lifeRate = 1 - cultRate;
+            tmpResult.setCullRate(cultRate);
+            tmpResult.setLifeRate(lifeRate);
+        }
+        int qualifiedEgg = tmpResult.getQualifiedEgg();
+        int allEgg = tmpResult.getQualifiedEgg() + tmpResult.getDeformedEgg() + tmpResult.getBreakEgg();
+        //每日母鸡总数之和
+        Integer chickenAll1 = tmpResult.getChicken1();
+        if(qualifiedEgg == 0){
+            tmpResult.setEggPassRate(0f);
+        }else{
+            //种蛋合格率
+            tmpResult.setEggPassRate((float) (qualifiedEgg / allEgg));
+        }
+
+        if(allEgg <= 0 || chickenAll1 <= 0){
+            tmpResult.setEggProductionRate(0f);
+        }else{
+            //产蛋率
+            tmpResult.setEggProductionRate((float) (allEgg / chickenAll1));
+        }
+//        tmpResult.setLifeRateStr(convertFloatToStr(tmpResult.getLifeRate()));
+//        tmpResult.setCullRateStr(convertFloatToStr(tmpResult.getCullRate()));
+//        tmpResult.setEggProductionRate-Str(convertFloatToStr(tmpResult.getEggProductionRate()));
+//        tmpResult.setEggPassRateStr(convertFloatToStr(tmpResult.getEggPassRate()));
+    }
+//    private String convertFloatToStr(Float f){
+//        if(f == null){
+//            return "-";
+//        }
+//        return String.format("%.4f", f * 100) + "%";
+//    }
+
+
+    /**
+     * 通用统计
+     * @param tmpResultMap
+     * @param param
+     */
+    public void statisticCommon(Map<String, StatisticTmpResultDto> tmpResultMap,QueryStaScopeParam param){
+
+        List<CoopBatchChickenStatisticResultVo> cullStatistics = reportDetailMapper.selectCullCount(param);
+        for (CoopBatchChickenStatisticResultVo resultVo : cullStatistics) {
+            String key = resultVo.getCoopId() + "_" + resultVo.getBatchNum();
+            StatisticTmpResultDto tmpResult = tmpResultMap.computeIfAbsent(key,k->new StatisticTmpResultDto());
+            tmpResult.setCoopId(resultVo.getCoopId());
+            tmpResult.setBatchNum(resultVo.getBatchNum());
+            if(resultVo.getGender() == 0){
+                tmpResult.setCull0(resultVo.getChickenCount());
+            }else if(resultVo.getGender() == 1){
+                tmpResult.setCull1(resultVo.getChickenCount());
+            }
+        }
+        List<CoopBatchChickenStatisticResultVo> statisticsIn = reportDetailMapper.selectChickenIn(param);
+        for (CoopBatchChickenStatisticResultVo resultVo : statisticsIn) {
+            String key = resultVo.getCoopId() + "_" + resultVo.getBatchNum();
+            StatisticTmpResultDto tmpResult = tmpResultMap.computeIfAbsent(key,k->new StatisticTmpResultDto());
+            tmpResult.setCoopId(resultVo.getCoopId());
+            tmpResult.setBatchNum(resultVo.getBatchNum());
+            if(resultVo.getGender() == 0){
+                tmpResult.setIn0(resultVo.getChickenCount());
+            }else if(resultVo.getGender() == 1){
+                tmpResult.setIn1(resultVo.getChickenCount());
+            }
+        }
+        List<CoopBatchChickenStatisticResultVo> statisticsOut = reportDetailMapper.selectChickenOut(param);
+        for (CoopBatchChickenStatisticResultVo resultVo : statisticsOut) {
+            String key = resultVo.getCoopId() + "_" + resultVo.getBatchNum();
+            StatisticTmpResultDto tmpResult = tmpResultMap.computeIfAbsent(key,k->new StatisticTmpResultDto());
+            tmpResult.setCoopId(resultVo.getCoopId());
+            tmpResult.setBatchNum(resultVo.getBatchNum());
+            if(resultVo.getGender() == 0){
+                tmpResult.setOut0(resultVo.getChickenCount());
+            }else if(resultVo.getGender() == 1){
+                tmpResult.setOut1(resultVo.getChickenCount());
+            }
+        }
+        List<CoopBatchEggStatisticResultVo> eggStatistics = reportDetailMapper.selectStatisticEgg(param);
+        for (CoopBatchEggStatisticResultVo resultVo : eggStatistics) {
+            String key = resultVo.getCoopId() + "_" + resultVo.getBatchNum();
+            StatisticTmpResultDto tmpResult = tmpResultMap.computeIfAbsent(key,k->new StatisticTmpResultDto());
+            tmpResult.setCoopId(resultVo.getCoopId());
+            tmpResult.setBatchNum(resultVo.getBatchNum());
+            if(Objects.equals(resultVo.getEggType(), EggTypeEnum.INCUBATION_EGG.getCode())){
+                tmpResult.setEggCount0(resultVo.getEggCount());
+            }else if(Objects.equals(resultVo.getEggType(), EggTypeEnum.VEGETABLE_EGG.getCode())){
+                tmpResult.setEggCount1(resultVo.getEggCount());
+            }else if (Objects.equals(resultVo.getEggType(), EggTypeEnum.DEFORMED_EGG.getCode())){
+                tmpResult.setDeformedEgg(resultVo.getEggCount());
+            }else if (Objects.equals(resultVo.getEggType(), EggTypeEnum.BREAK_EGG.getCode())){
+                tmpResult.setBreakEgg(resultVo.getEggCount());
+            }
+            tmpResult.setQualifiedEgg((tmpResult.getEggCount0()>0 ? tmpResult.getEggCount0() : 0) +
+                    (tmpResult.getEggCount1()>0? tmpResult.getEggCount1() : 0));
+        }
+    }
+
+    private Date getReportDate(QueryStaBo input) {
+        String reportCycle = input.getReportCycle();
+       return switch (reportCycle) {
+           case "Y", "Q", "M" -> DateUtils.getNowDate();
+           case "D" -> DateUtils.createDate(input.getYear(), input.getMonth(), input.getDay());
+           default -> throw new ServiceException("不支持的报表周期: " + reportCycle);
+       };
+    }
+
+
+}

部分文件因为文件数量过多而无法显示