xsh_1997 недель назад: 2
Родитель
Сommit
f26dd7b185
16 измененных файлов с 43 добавлено и 37 удалено
  1. 1 1
      baqing-admin/src/main/java/com/ruoyi/web/modules/industryservice/domain/BizDisposableIncome.java
  2. 0 6
      baqing-admin/src/main/java/com/ruoyi/web/modules/industryservice/service/impl/BizVaccinationDataServiceImpl.java
  3. 4 3
      baqing-admin/src/main/java/com/ruoyi/web/modules/industryservice/support/DisposableIncomeGrowthSupport.java
  4. 5 5
      baqing-admin/src/main/java/com/ruoyi/web/modules/industryservice/support/VaccinationDataValidation.java
  5. 6 6
      baqing-admin/src/test/java/com/ruoyi/web/modules/industryservice/support/DisposableIncomeGrowthSupportTest.java
  6. 9 5
      baqing-admin/src/test/java/com/ruoyi/web/modules/industryservice/support/VaccinationDataExcelParserTest.java
  7. 1 1
      doc/产业数据模型及服务/可支配收入数据填报/可支配收入数据填报前端技术方案.md
  8. 3 2
      doc/产业数据模型及服务/可支配收入数据填报/可支配收入数据填报功能需求.md
  9. 2 2
      doc/产业数据模型及服务/可支配收入数据填报/可支配收入数据填报技术方案.md
  10. 1 1
      doc/产业数据模型及服务/可支配收入数据填报/可支配收入数据填报测试用例.md
  11. 6 1
      doc/产业数据模型及服务/疫苗接种数据填报/疫苗接种数据填报功能需求.md
  12. 1 1
      doc/产业数据模型及服务/疫苗接种数据填报/疫苗接种数据填报技术方案.md
  13. 3 2
      doc/产业数据模型及服务/疫苗接种数据填报/疫苗接种数据填报测试用例.md
  14. 1 1
      sql/biz_disposable_income.sql
  15. 0 0
      sql/biz_large_livestock_farmer.sql
  16. 0 0
      sql/biz_vaccination_data.sql

+ 1 - 1
baqing-admin/src/main/java/com/ruoyi/web/modules/industryservice/domain/BizDisposableIncome.java

@@ -25,7 +25,7 @@ public class BizDisposableIncome extends BaseEntity
25 25
     /** 增幅(元),可选;公式=本年可支配收入-上年可支配收入 */
26 26
     private BigDecimal incomeIncrease;
27 27
 
28
-    /** 增速,可选;公式=增幅/上年可支配收入 */
28
+    /** 增速,可选;公式=(增幅/上年可支配收入)×100,保留2位小数 */
29 29
     private BigDecimal incomeGrowthRate;
30 30
 
31 31
     public Long getId()

+ 0 - 6
baqing-admin/src/main/java/com/ruoyi/web/modules/industryservice/service/impl/BizVaccinationDataServiceImpl.java

@@ -157,12 +157,6 @@ public class BizVaccinationDataServiceImpl implements IBizVaccinationDataService
157 157
                 BizVaccinationData row = VaccinationDataExcelParser.toEntity(parsed, statYear, statMonth,
158 158
                         town.getDeptId(), town.getDeptName(), village.getDeptId(), village.getDeptName());
159 159
                 VaccinationDataValidation.validateRowForSave(row, townDeptSupport);
160
-                String warn = VaccinationDataValidation.buildActualExceedShouldWarn(row);
161
-                if (StringUtils.isNotEmpty(warn))
162
-                {
163
-                    result.addWarn("第" + parsed.getExcelRowNum() + "行[" + parsed.getTownName() + "/"
164
-                            + parsed.getVillageName() + "]: " + warn);
165
-                }
166 160
                 String batchKey = row.getStatYear() + "|" + row.getStatMonth() + "|" + row.getVillageDeptId();
167 161
                 if (!batchKeys.add(batchKey))
168 162
                 {

+ 4 - 3
baqing-admin/src/main/java/com/ruoyi/web/modules/industryservice/support/DisposableIncomeGrowthSupport.java

@@ -7,11 +7,11 @@ import com.ruoyi.web.modules.industryservice.domain.BizDisposableIncome;
7 7
 /**
8 8
  * 可支配收入增幅、增速:可选填;未填或口径变更时按公式计算。
9 9
  * 增幅 = 本年人均可支配收入 - 上年人均可支配收入;
10
- * 增速 = 增幅 / 上年人均可支配收入。
10
+ * 增速 = (增幅 / 上年人均可支配收入) × 100,保留 2 位小数
11 11
  */
12 12
 public final class DisposableIncomeGrowthSupport
13 13
 {
14
-    private static final int RATE_SCALE = 6;
14
+    private static final int RATE_SCALE = 2;
15 15
 
16 16
     private DisposableIncomeGrowthSupport()
17 17
     {
@@ -56,7 +56,8 @@ public final class DisposableIncomeGrowthSupport
56 56
             BigDecimal usedIncrease = current.getIncomeIncrease() != null ? current.getIncomeIncrease() : increase;
57 57
             if (prev.compareTo(BigDecimal.ZERO) != 0)
58 58
             {
59
-                current.setIncomeGrowthRate(usedIncrease.divide(prev, RATE_SCALE, RoundingMode.HALF_UP));
59
+                current.setIncomeGrowthRate(usedIncrease.multiply(BigDecimal.valueOf(100))
60
+                        .divide(prev, RATE_SCALE, RoundingMode.HALF_UP));
60 61
             }
61 62
         }
62 63
     }

+ 5 - 5
baqing-admin/src/main/java/com/ruoyi/web/modules/industryservice/support/VaccinationDataValidation.java

@@ -41,6 +41,7 @@ public final class VaccinationDataValidation
41 41
 
42 42
         validateNonNegative(row.getShouldVaccinateCount(), "应免数");
43 43
         validateNonNegative(row.getActualVaccinateCount(), "实免数");
44
+        validateActualNotExceedShould(row);
44 45
         if (StringUtils.isNotEmpty(row.getRemark()) && row.getRemark().length() > 500)
45 46
         {
46 47
             throw new ServiceException("备注不能超过500字");
@@ -56,17 +57,16 @@ public final class VaccinationDataValidation
56 57
         }
57 58
     }
58 59
 
59
-    /** 实免数大于应免数时给出软警告(不阻断保存) */
60
-    public static String buildActualExceedShouldWarn(BizVaccinationData row)
60
+    /** 实免数须小于等于应免数(两者均非空时) */
61
+    public static void validateActualNotExceedShould(BizVaccinationData row)
61 62
     {
62 63
         if (row == null || row.getShouldVaccinateCount() == null || row.getActualVaccinateCount() == null)
63 64
         {
64
-            return null;
65
+            return;
65 66
         }
66 67
         if (row.getActualVaccinateCount() > row.getShouldVaccinateCount())
67 68
         {
68
-            return "实免数大于应免数";
69
+            throw new ServiceException("实免数不能大于应免数");
69 70
         }
70
-        return null;
71 71
     }
72 72
 }

+ 6 - 6
baqing-admin/src/test/java/com/ruoyi/web/modules/industryservice/support/DisposableIncomeGrowthSupportTest.java

@@ -19,7 +19,7 @@ class DisposableIncomeGrowthSupportTest
19 19
         BizDisposableIncome previous = row(2019, "11886");
20 20
         DisposableIncomeGrowthSupport.fillMissingGrowth(current, previous);
21 21
         assertEquals(0, new BigDecimal("1460").compareTo(current.getIncomeIncrease()));
22
-        assertEquals(0, new BigDecimal("0.122834").compareTo(current.getIncomeGrowthRate()));
22
+        assertEquals(0, new BigDecimal("12.28").compareTo(current.getIncomeGrowthRate()));
23 23
     }
24 24
 
25 25
     @Test
@@ -28,11 +28,11 @@ class DisposableIncomeGrowthSupportTest
28 28
     {
29 29
         BizDisposableIncome current = row(2020, "13346");
30 30
         current.setIncomeIncrease(new BigDecimal("1000"));
31
-        current.setIncomeGrowthRate(new BigDecimal("0.0800"));
31
+        current.setIncomeGrowthRate(new BigDecimal("8.00"));
32 32
         BizDisposableIncome previous = row(2019, "11886");
33 33
         DisposableIncomeGrowthSupport.fillMissingGrowth(current, previous);
34 34
         assertEquals(new BigDecimal("1000"), current.getIncomeIncrease());
35
-        assertEquals(new BigDecimal("0.0800"), current.getIncomeGrowthRate());
35
+        assertEquals(new BigDecimal("8.00"), current.getIncomeGrowthRate());
36 36
     }
37 37
 
38 38
     @Test
@@ -44,7 +44,7 @@ class DisposableIncomeGrowthSupportTest
44 44
         BizDisposableIncome previous = row(2019, "11886");
45 45
         DisposableIncomeGrowthSupport.fillMissingGrowth(current, previous);
46 46
         assertEquals(new BigDecimal("1460"), current.getIncomeIncrease());
47
-        assertEquals(0, new BigDecimal("0.122834").compareTo(current.getIncomeGrowthRate()));
47
+        assertEquals(0, new BigDecimal("12.28").compareTo(current.getIncomeGrowthRate()));
48 48
     }
49 49
 
50 50
     @Test
@@ -74,11 +74,11 @@ class DisposableIncomeGrowthSupportTest
74 74
     {
75 75
         BizDisposableIncome current = row(2022, "13346");
76 76
         current.setIncomeIncrease(new BigDecimal("1"));
77
-        current.setIncomeGrowthRate(new BigDecimal("0.01"));
77
+        current.setIncomeGrowthRate(new BigDecimal("1.00"));
78 78
         BizDisposableIncome previous = row(2021, "11886");
79 79
         DisposableIncomeGrowthSupport.recalculateGrowth(current, previous);
80 80
         assertEquals(0, new BigDecimal("1460").compareTo(current.getIncomeIncrease()));
81
-        assertEquals(0, new BigDecimal("0.122834").compareTo(current.getIncomeGrowthRate()));
81
+        assertEquals(0, new BigDecimal("12.28").compareTo(current.getIncomeGrowthRate()));
82 82
     }
83 83
 
84 84
     private static BizDisposableIncome row(int year, String income)

+ 9 - 5
baqing-admin/src/test/java/com/ruoyi/web/modules/industryservice/support/VaccinationDataExcelParserTest.java

@@ -1,13 +1,14 @@
1 1
 package com.ruoyi.web.modules.industryservice.support;
2 2
 
3 3
 import static org.junit.jupiter.api.Assertions.assertEquals;
4
-import static org.junit.jupiter.api.Assertions.assertTrue;
4
+import static org.junit.jupiter.api.Assertions.assertThrows;
5 5
 
6 6
 import java.io.InputStream;
7 7
 import java.util.List;
8 8
 import org.junit.jupiter.api.DisplayName;
9 9
 import org.junit.jupiter.api.Test;
10 10
 import org.springframework.core.io.ClassPathResource;
11
+import com.ruoyi.common.exception.ServiceException;
11 12
 import com.ruoyi.web.modules.industryservice.support.VaccinationDataExcelParser.ParsedRow;
12 13
 
13 14
 @DisplayName("VaccinationDataExcelParser")
@@ -46,8 +47,8 @@ class VaccinationDataExcelParserTest
46 47
     }
47 48
 
48 49
     @Test
49
-    @DisplayName("免疫率派生与百分比格式化")
50
-    void derivedImmunityRate()
50
+    @DisplayName("免疫率派生与实免不超过应免硬校验")
51
+    void derivedImmunityRateAndActualConstraint()
51 52
     {
52 53
         com.ruoyi.web.modules.industryservice.domain.BizVaccinationData row =
53 54
                 new com.ruoyi.web.modules.industryservice.domain.BizVaccinationData();
@@ -56,8 +57,11 @@ class VaccinationDataExcelParserTest
56 57
         VaccinationDataDerivedSupport.applyDerived(row);
57 58
         assertEquals("98.33", row.getImmunityRate().toPlainString());
58 59
         assertEquals("98.33%", VaccinationDataDerivedSupport.formatImmunityRatePercent(row.getImmunityRate()));
59
-        assertTrue(VaccinationDataValidation.buildActualExceedShouldWarn(row) == null);
60
+        VaccinationDataValidation.validateActualNotExceedShould(row);
61
+
60 62
         row.setActualVaccinateCount(13000);
61
-        assertEquals("实免数大于应免数", VaccinationDataValidation.buildActualExceedShouldWarn(row));
63
+        ServiceException ex = assertThrows(ServiceException.class,
64
+                () -> VaccinationDataValidation.validateActualNotExceedShould(row));
65
+        assertEquals("实免数不能大于应免数", ex.getMessage());
62 66
     }
63 67
 }

+ 1 - 1
doc/产业数据模型及服务/可支配收入数据填报/可支配收入数据填报前端技术方案.md

@@ -65,7 +65,7 @@
65 65
 | 所属年份 | `statYear` |
66 66
 | 农村居民人均可支配收入(元) | `ruralDisposableIncome` |
67 67
 | 增幅(元) | `incomeIncrease` |
68
-| 增速(小数,如 0.1228) | `incomeGrowthRate` |
68
+| 增速(百分数,如 12.28) | `incomeGrowthRate` |
69 69
 | 脱贫人口人均纯收入(元) | `povertyNetIncome` |
70 70
 | 备注 | `remark` |
71 71
 

+ 3 - 2
doc/产业数据模型及服务/可支配收入数据填报/可支配收入数据填报功能需求.md

@@ -17,7 +17,7 @@
17 17
 - 唯一键:所属年份。
18 18
 - **增幅、增速可选填并落库**:
19 19
   - 增幅 = 人均可支配收入 − 去年人均可支配收入
20
-  - 增速 = 增幅 / 去年人均可支配收入
20
+  - 增速 = (增幅 / 去年人均可支配收入) × 100,保留 2 位小数(如 12.28)
21 21
   - **新增**或仅改其他字段且未填增幅/增速时:存在上年数据则按公式补齐;已手工填写则保留。
22 22
   - **修改年份或人均可支配收入时**:按新口径**强制重算**增幅、增速(与前端清空后提交一致)。
23 23
   - 无上年数据或无法计算增速(如上年可支配收入为 0)时,对应字段可为 `null`。
@@ -31,7 +31,7 @@
31 31
 | 能力 | 说明 |
32 32
 | --- | --- |
33 33
 | 分页列表 | 筛选:所属年份;列:年份、农村居民人均可支配收入、增幅、增速、脱贫人口人均纯收入;增幅/增速 null 显示为 0 |
34
-| 新增 / 修改 | 年份、人均可支配收入、增幅(选填)、增速(选填,小数如 0.1228)、人均纯收入、备注;新增默认本年;改年份/可支配收入时清空并重算增幅增速 |
34
+| 新增 / 修改 | 年份、人均可支配收入、增幅(选填)、增速(选填,百分数如 12.28)、人均纯收入、备注;新增默认本年;改年份/可支配收入时清空并重算增幅增速 |
35 35
 | 详情 | 全部字段;增幅/增速 null 显示为 0 |
36 36
 | 删除 | 物理删除 |
37 37
 
@@ -50,3 +50,4 @@
50 50
 | 1.0 | 首版:县级年度 CRUD |
51 51
 | 1.1 | 增幅、增速改为可选填落库;未填按公式补齐 |
52 52
 | 1.2 | 修改年份/可支配收入强制重算;列表详情 null 显示为 0 |
53
+| 1.3 | 增速改为 (增幅/去年人均可支配收入)×100,保留 2 位小数落库 |

+ 2 - 2
doc/产业数据模型及服务/可支配收入数据填报/可支配收入数据填报技术方案.md

@@ -24,7 +24,7 @@
24 24
 | stat_year | 所属年份,唯一 |
25 25
 | rural_disposable_income | 农村居民人均可支配收入(元) |
26 26
 | income_increase | 增幅(元),可选可空 |
27
-| income_growth_rate | 增速(小数),可选可空 |
27
+| income_growth_rate | 增速(百分数值,如 12.28),可选可空 |
28 28
 | poverty_net_income | 脱贫人口人均纯收入(元) |
29 29
 | remark | 备注 |
30 30
 
@@ -44,7 +44,7 @@
44 44
 公式:
45 45
 
46 46
 - 增幅 = 本年 `rural_disposable_income` − 上年同字段
47
-- 增速 = 增幅 ÷ 上年 `rural_disposable_income`(保留 6 位小数)
47
+- 增速 = (增幅 ÷ 上年 `rural_disposable_income`) × 100,保留 2 位小数
48 48
 
49 49
 ---
50 50
 

+ 1 - 1
doc/产业数据模型及服务/可支配收入数据填报/可支配收入数据填报测试用例.md

@@ -12,7 +12,7 @@
12 12
 
13 13
 | 用例编号 | 测试模块 | 测试项 | 测试类型 | 测试工具 | 测试目的 | 前置条件 | 测试步骤 | 预期结果 |
14 14
 | --- | --- | --- | --- | --- | --- | --- | --- | --- |
15
-| ZCZX-KZPMSR-UT-001 | 增幅增速 | 未填时按公式补齐 | 单元测试 | JUnit5 | 可选填+公式 | 本年 13346、上年 11886 | `fillMissingGrowth` | 增幅=1460;增速≈0.1228 |
15
+| ZCZX-KZPMSR-UT-001 | 增幅增速 | 未填时按公式补齐 | 单元测试 | JUnit5 | 可选填+公式 | 本年 13346、上年 11886 | `fillMissingGrowth` | 增幅=1460;增速=12.28 |
16 16
 | ZCZX-KZPMSR-UT-002 | 增幅增速 | 已填保留手工值 | 单元测试 | JUnit5 | 不覆盖 | 已填增幅/增速 | `fillMissingGrowth` | 仍为手工值 |
17 17
 | ZCZX-KZPMSR-UT-003 | 增幅增速 | 无上年数据 | 单元测试 | JUnit5 | 首年 | previous=null | `fillMissingGrowth` | 增幅、增速仍为 null |
18 18
 | ZCZX-KZPMSR-UT-004 | 增幅增速 | 上年为 0 | 单元测试 | JUnit5 | 除零保护 | 上年可支配收入=0 | `fillMissingGrowth` | 仅补齐增幅;增速仍 null |

+ 6 - 1
doc/产业数据模型及服务/疫苗接种数据填报/疫苗接种数据填报功能需求.md

@@ -18,7 +18,8 @@
18 18
 - 唯一键:所属年份 + 所属月份 + 所属村。
19 19
 - 导入:存在则更新、不存在则插入(不按年月先删后插)。
20 20
 - 派生(保存时计算并落库):**免疫率 = (实免数 / 应免数) × 100**,保留 2 位小数(应免数 > 0 且实免数非空;如 98.33;界面/导出展示为 `98.33%`)。
21
-- 页面填报:实免数须小于等于应免数;导入:实免大于应免时后端可软警告(不阻断)。
21
+
22
+- **约束:实免数 ≤ 应免数**(两者均填写时;保存与导入均硬拦截,不允许超过)。
22 23
 
23 24
 ---
24 25
 
@@ -49,4 +50,8 @@
49 50
 | --- | --- |
50 51
 | 1.0 | 首版:CRUD + upsert 导入 + 导出 |
51 52
 | 1.1 | 免疫率改为 (实免数/应免数)×100,保留 2 位小数落库 |
53
+<<<<<<< HEAD
52 54
 | 1.2 | 页面填报约束实免数 ≤ 应免数(前端校验) |
55
+=======
56
+| 1.2 | 约束:实免数 ≤ 应免数(硬校验) |
57
+>>>>>>> ef65fad8763e393adf8cf1e918e4eec407e1b967

+ 1 - 1
doc/产业数据模型及服务/疫苗接种数据填报/疫苗接种数据填报技术方案.md

@@ -34,7 +34,7 @@ Excel 列:0 序号、1 乡镇、2 村、3 应免数、4 实免数、5 免疫
34 34
 | `VaccinationDataExcelParser` | 识别主表头,跳过子表头/空白/合计 |
35 35
 | `VaccinationDataExcelExporter` | 基于模板写数据 |
36 36
 | `VaccinationDataDerivedSupport` | 免疫率计算与百分比格式化 |
37
-| `VaccinationDataValidation` | 年月/村校验、非负整数、软警告 |
37
+| `VaccinationDataValidation` | 年月/村校验、非负整数、实免≤应免硬校验 |
38 38
 
39 39
 ---
40 40
 

+ 3 - 2
doc/产业数据模型及服务/疫苗接种数据填报/疫苗接种数据填报测试用例.md

@@ -10,7 +10,8 @@
10 10
 | VD-04 | 修改 | 改应免/实免 | 免疫率重算 |
11 11
 | VD-05 | 删除 | 删除一条 | 物理删除成功 |
12 12
 | VD-06 | 未来月 | 选未来年月保存 | 拒绝 |
13
-| VD-07 | 实免&gt;应免 | 页面保存 | 前端拦截;导入可有软警告 |
13
+
14
+| VD-07 | 实免&gt;应免 | 保存/导入 | 拒绝(硬校验) |
14 15
 | VD-08 | 下载模板 | 点下载模板 | 得到官方 xlsx |
15 16
 | VD-09 | 导入 upsert | 上传模板示例行,再导入同村改数 | 首次新增、再次更新 |
16 17
 | VD-10 | 导出 | 选年月,可选乡镇 | 按模板填充;免疫率为百分比;无合计行 |
@@ -21,4 +22,4 @@
21 22
 | --- | --- | --- |
22 23
 | VD-UT-01 | `VaccinationDataExcelParserTest` | 官方模板解析出 2 条示例行 |
23 24
 | VD-UT-02 | 同上 | 主表头行索引=2,子表头跳过 |
24
-| VD-UT-03 | 同上 | 免疫率派生与软警告 |
25
+| VD-UT-03 | 同上 | 免疫率派生与实免≤应免硬校验 |

+ 1 - 1
sql/biz_disposable_income.sql

@@ -5,7 +5,7 @@ CREATE TABLE `biz_disposable_income` (
5 5
   `stat_year` int(11) NOT NULL COMMENT '所属年份',
6 6
   `rural_disposable_income` decimal(18,2) DEFAULT NULL COMMENT '农村居民人均可支配收入(元)',
7 7
   `income_increase` decimal(18,2) DEFAULT NULL COMMENT '增幅(元),可选;公式=本年可支配收入-上年',
8
-  `income_growth_rate` decimal(18,6) DEFAULT NULL COMMENT '增速,可选;公式=增幅/上年可支配收入',
8
+  `income_growth_rate` decimal(8,2) DEFAULT NULL COMMENT '增速,可选;公式=(增幅/上年可支配收入)*100,保留2位小数',
9 9
   `poverty_net_income` decimal(18,2) DEFAULT NULL COMMENT '脱贫人口人均纯收入(元)',
10 10
   `create_by` varchar(64) DEFAULT '' COMMENT '创建者',
11 11
   `create_time` datetime DEFAULT NULL COMMENT '创建时间',

+ 0 - 0
sql/biz_large_livestock_farmer.sql

@@ -1,5 +1,4 @@
1 1
 -- 养殖大户数据填报(物理删除;全量覆盖建表)
2 2
 -- 唯一键:uk_year_month_village_enterprise (stat_year, stat_month, village_dept_id, enterprise_name)
3 3
 -- 派生落库:stock_subtotal / grassland_area_subtotal / profit / is_grass_balanced
4 4
 -- 草畜失衡预警写入 biz_yak_disease_warning(data_source=large_livestock_farmer, device_no=LLF-{id}),不另建表

+ 0 - 0
sql/biz_vaccination_data.sql

@@ -1,5 +1,4 @@
1 1
 -- 疫苗接种数据填报(物理删除;全量覆盖建表)
2 2
 -- 唯一键:uk_year_month_village (stat_year, stat_month, village_dept_id)
3 3
 -- 派生落库:immunity_rate = (实免数/应免数)*100,保留2位小数(如 98.33)
4 4
 DROP TABLE IF EXISTS `biz_vaccination_data`;