Quellcode durchsuchen

三资具体问题上报

wwh vor 1 Woche
Ursprung
Commit
cdc80b5d60
13 geänderte Dateien mit 910 neuen und 0 gelöschten Zeilen
  1. 89 0
      baqing-admin/src/main/java/com/ruoyi/web/modules/industryservice/controller/BizThreeAssetsProblemReportController.java
  2. 166 0
      baqing-admin/src/main/java/com/ruoyi/web/modules/industryservice/domain/BizThreeAssetsProblemReport.java
  3. 21 0
      baqing-admin/src/main/java/com/ruoyi/web/modules/industryservice/mapper/BizThreeAssetsProblemReportMapper.java
  4. 26 0
      baqing-admin/src/main/java/com/ruoyi/web/modules/industryservice/service/IBizThreeAssetsProblemReportService.java
  5. 108 0
      baqing-admin/src/main/java/com/ruoyi/web/modules/industryservice/service/impl/BizThreeAssetsProblemReportServiceImpl.java
  6. 42 0
      baqing-admin/src/main/java/com/ruoyi/web/modules/industryservice/support/ThreeAssetsProblemReportRules.java
  7. 93 0
      baqing-admin/src/main/java/com/ruoyi/web/modules/industryservice/support/ThreeAssetsProblemReportValidation.java
  8. 103 0
      baqing-admin/src/main/resources/mapper/industryservice/BizThreeAssetsProblemReportMapper.xml
  9. 86 0
      baqing-admin/src/test/java/com/ruoyi/web/modules/industryservice/support/ThreeAssetsProblemReportValidationTest.java
  10. 57 0
      doc/产业数据模型及服务/三资具体问题上报/三资具体问题上报功能需求.md
  11. 60 0
      doc/产业数据模型及服务/三资具体问题上报/三资具体问题上报技术方案.md
  12. 35 0
      doc/产业数据模型及服务/三资具体问题上报/三资具体问题上报测试用例.md
  13. 24 0
      sql/biz_three_assets_problem_report.sql

+ 89 - 0
baqing-admin/src/main/java/com/ruoyi/web/modules/industryservice/controller/BizThreeAssetsProblemReportController.java

@@ -0,0 +1,89 @@
1
+package com.ruoyi.web.modules.industryservice.controller;
2
+
3
+import java.util.List;
4
+import org.springframework.beans.factory.annotation.Autowired;
5
+import org.springframework.security.access.prepost.PreAuthorize;
6
+import org.springframework.validation.annotation.Validated;
7
+import org.springframework.web.bind.annotation.DeleteMapping;
8
+import org.springframework.web.bind.annotation.GetMapping;
9
+import org.springframework.web.bind.annotation.PathVariable;
10
+import org.springframework.web.bind.annotation.PostMapping;
11
+import org.springframework.web.bind.annotation.PutMapping;
12
+import org.springframework.web.bind.annotation.RequestBody;
13
+import org.springframework.web.bind.annotation.RequestMapping;
14
+import org.springframework.web.bind.annotation.RestController;
15
+import com.ruoyi.common.annotation.Log;
16
+import com.ruoyi.common.core.controller.BaseController;
17
+import com.ruoyi.common.core.domain.AjaxResult;
18
+import com.ruoyi.common.core.page.TableDataInfo;
19
+import com.ruoyi.common.enums.BusinessType;
20
+import com.ruoyi.web.modules.industryservice.domain.BizThreeAssetsProblemReport;
21
+import com.ruoyi.web.modules.industryservice.service.IBizThreeAssetsProblemReportService;
22
+
23
+/**
24
+ * 三资具体问题上报 REST。
25
+ * <p>Base:{@code /dataModel/threeAssetsProblemReport};权限 {@code dataModel:threeAssetsProblemReport:*};无导入导出。</p>
26
+ */
27
+@RestController
28
+@RequestMapping("/dataModel/threeAssetsProblemReport")
29
+public class BizThreeAssetsProblemReportController extends BaseController
30
+{
31
+    @Autowired
32
+    private IBizThreeAssetsProblemReportService service;
33
+
34
+    @PreAuthorize("@ss.hasPermi('dataModel:threeAssetsProblemReport:list')")
35
+    @GetMapping("/list")
36
+    public TableDataInfo list(BizThreeAssetsProblemReport query)
37
+    {
38
+        startPage();
39
+        List<BizThreeAssetsProblemReport> list = service.selectBizThreeAssetsProblemReportList(query);
40
+        return getDataTable(list);
41
+    }
42
+
43
+    @PreAuthorize("@ss.hasPermi('dataModel:threeAssetsProblemReport:query')")
44
+    @GetMapping("/{id}")
45
+    public AjaxResult getInfo(@PathVariable("id") Long id)
46
+    {
47
+        return success(service.selectBizThreeAssetsProblemReportById(id));
48
+    }
49
+
50
+    @PreAuthorize("@ss.hasPermi('dataModel:threeAssetsProblemReport:add')")
51
+    @Log(title = "三资具体问题上报", businessType = BusinessType.INSERT)
52
+    @PostMapping
53
+    public AjaxResult add(@Validated @RequestBody BizThreeAssetsProblemReport row)
54
+    {
55
+        row.setCreateBy(getUsername());
56
+        return toAjax(service.insertBizThreeAssetsProblemReport(row));
57
+    }
58
+
59
+    @PreAuthorize("@ss.hasPermi('dataModel:threeAssetsProblemReport:edit')")
60
+    @Log(title = "三资具体问题上报", businessType = BusinessType.UPDATE)
61
+    @PutMapping
62
+    public AjaxResult edit(@Validated @RequestBody BizThreeAssetsProblemReport row)
63
+    {
64
+        row.setUpdateBy(getUsername());
65
+        return toAjax(service.updateBizThreeAssetsProblemReport(row));
66
+    }
67
+
68
+    @PreAuthorize("@ss.hasPermi('dataModel:threeAssetsProblemReport:remove')")
69
+    @Log(title = "三资具体问题上报", businessType = BusinessType.DELETE)
70
+    @DeleteMapping("/{ids}")
71
+    public AjaxResult remove(@PathVariable Long[] ids)
72
+    {
73
+        return toAjax(service.deleteBizThreeAssetsProblemReportByIds(ids, getUsername()));
74
+    }
75
+
76
+    @PreAuthorize("@ss.hasPermi('dataModel:threeAssetsProblemReport:list')")
77
+    @GetMapping("/townOptions")
78
+    public AjaxResult townOptions()
79
+    {
80
+        return success(service.listTownOptions());
81
+    }
82
+
83
+    @PreAuthorize("@ss.hasPermi('dataModel:threeAssetsProblemReport:list')")
84
+    @GetMapping("/villageTree")
85
+    public AjaxResult villageTree()
86
+    {
87
+        return success(service.listVillageTree());
88
+    }
89
+}

+ 166 - 0
baqing-admin/src/main/java/com/ruoyi/web/modules/industryservice/domain/BizThreeAssetsProblemReport.java

@@ -0,0 +1,166 @@
1
+package com.ruoyi.web.modules.industryservice.domain;
2
+
3
+import java.util.Date;
4
+import javax.validation.constraints.NotNull;
5
+import com.fasterxml.jackson.annotation.JsonFormat;
6
+import com.ruoyi.common.core.domain.BaseEntity;
7
+
8
+/**
9
+ * 三资具体问题上报,对应表 {@code biz_three_assets_problem_report}。
10
+ */
11
+public class BizThreeAssetsProblemReport extends BaseEntity
12
+{
13
+    private static final long serialVersionUID = 1L;
14
+
15
+    private Long id;
16
+
17
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
18
+    private Date reportTime;
19
+
20
+    private Long townDeptId;
21
+
22
+    private String townName;
23
+
24
+    @NotNull(message = "所属村不能为空")
25
+    private Long villageDeptId;
26
+
27
+    private String villageName;
28
+
29
+    /** 问题类型:fund/asset/resource/other */
30
+    private String problemType;
31
+
32
+    /** 问题等级:general/key/major */
33
+    private String problemLevel;
34
+
35
+    private String problemDetail;
36
+
37
+    private String handleResult;
38
+
39
+    /** 查询:上报时间起 */
40
+    @JsonFormat(pattern = "yyyy-MM-dd")
41
+    private Date beginReportTime;
42
+
43
+    /** 查询:上报时间止 */
44
+    @JsonFormat(pattern = "yyyy-MM-dd")
45
+    private Date endReportTime;
46
+
47
+    public Long getId()
48
+    {
49
+        return id;
50
+    }
51
+
52
+    public void setId(Long id)
53
+    {
54
+        this.id = id;
55
+    }
56
+
57
+    public Date getReportTime()
58
+    {
59
+        return reportTime;
60
+    }
61
+
62
+    public void setReportTime(Date reportTime)
63
+    {
64
+        this.reportTime = reportTime;
65
+    }
66
+
67
+    public Long getTownDeptId()
68
+    {
69
+        return townDeptId;
70
+    }
71
+
72
+    public void setTownDeptId(Long townDeptId)
73
+    {
74
+        this.townDeptId = townDeptId;
75
+    }
76
+
77
+    public String getTownName()
78
+    {
79
+        return townName;
80
+    }
81
+
82
+    public void setTownName(String townName)
83
+    {
84
+        this.townName = townName;
85
+    }
86
+
87
+    public Long getVillageDeptId()
88
+    {
89
+        return villageDeptId;
90
+    }
91
+
92
+    public void setVillageDeptId(Long villageDeptId)
93
+    {
94
+        this.villageDeptId = villageDeptId;
95
+    }
96
+
97
+    public String getVillageName()
98
+    {
99
+        return villageName;
100
+    }
101
+
102
+    public void setVillageName(String villageName)
103
+    {
104
+        this.villageName = villageName;
105
+    }
106
+
107
+    public String getProblemType()
108
+    {
109
+        return problemType;
110
+    }
111
+
112
+    public void setProblemType(String problemType)
113
+    {
114
+        this.problemType = problemType;
115
+    }
116
+
117
+    public String getProblemLevel()
118
+    {
119
+        return problemLevel;
120
+    }
121
+
122
+    public void setProblemLevel(String problemLevel)
123
+    {
124
+        this.problemLevel = problemLevel;
125
+    }
126
+
127
+    public String getProblemDetail()
128
+    {
129
+        return problemDetail;
130
+    }
131
+
132
+    public void setProblemDetail(String problemDetail)
133
+    {
134
+        this.problemDetail = problemDetail;
135
+    }
136
+
137
+    public String getHandleResult()
138
+    {
139
+        return handleResult;
140
+    }
141
+
142
+    public void setHandleResult(String handleResult)
143
+    {
144
+        this.handleResult = handleResult;
145
+    }
146
+
147
+    public Date getBeginReportTime()
148
+    {
149
+        return beginReportTime;
150
+    }
151
+
152
+    public void setBeginReportTime(Date beginReportTime)
153
+    {
154
+        this.beginReportTime = beginReportTime;
155
+    }
156
+
157
+    public Date getEndReportTime()
158
+    {
159
+        return endReportTime;
160
+    }
161
+
162
+    public void setEndReportTime(Date endReportTime)
163
+    {
164
+        this.endReportTime = endReportTime;
165
+    }
166
+}

+ 21 - 0
baqing-admin/src/main/java/com/ruoyi/web/modules/industryservice/mapper/BizThreeAssetsProblemReportMapper.java

@@ -0,0 +1,21 @@
1
+package com.ruoyi.web.modules.industryservice.mapper;
2
+
3
+import java.util.List;
4
+import org.apache.ibatis.annotations.Param;
5
+import com.ruoyi.web.modules.industryservice.domain.BizThreeAssetsProblemReport;
6
+
7
+/**
8
+ * 三资具体问题上报 Mapper。
9
+ */
10
+public interface BizThreeAssetsProblemReportMapper
11
+{
12
+    BizThreeAssetsProblemReport selectBizThreeAssetsProblemReportById(Long id);
13
+
14
+    List<BizThreeAssetsProblemReport> selectBizThreeAssetsProblemReportList(BizThreeAssetsProblemReport query);
15
+
16
+    int insertBizThreeAssetsProblemReport(BizThreeAssetsProblemReport row);
17
+
18
+    int updateBizThreeAssetsProblemReport(BizThreeAssetsProblemReport row);
19
+
20
+    int deleteBizThreeAssetsProblemReportByIds(@Param("ids") Long[] ids);
21
+}

+ 26 - 0
baqing-admin/src/main/java/com/ruoyi/web/modules/industryservice/service/IBizThreeAssetsProblemReportService.java

@@ -0,0 +1,26 @@
1
+package com.ruoyi.web.modules.industryservice.service;
2
+
3
+import java.util.List;
4
+import java.util.Map;
5
+import com.ruoyi.common.core.domain.TreeSelect;
6
+import com.ruoyi.web.modules.industryservice.domain.BizThreeAssetsProblemReport;
7
+
8
+/**
9
+ * 三资具体问题上报服务(仅 CRUD,无导入导出)。
10
+ */
11
+public interface IBizThreeAssetsProblemReportService
12
+{
13
+    BizThreeAssetsProblemReport selectBizThreeAssetsProblemReportById(Long id);
14
+
15
+    List<BizThreeAssetsProblemReport> selectBizThreeAssetsProblemReportList(BizThreeAssetsProblemReport query);
16
+
17
+    int insertBizThreeAssetsProblemReport(BizThreeAssetsProblemReport row);
18
+
19
+    int updateBizThreeAssetsProblemReport(BizThreeAssetsProblemReport row);
20
+
21
+    int deleteBizThreeAssetsProblemReportByIds(Long[] ids, String updateBy);
22
+
23
+    List<Map<String, Object>> listTownOptions();
24
+
25
+    List<TreeSelect> listVillageTree();
26
+}

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

@@ -0,0 +1,108 @@
1
+package com.ruoyi.web.modules.industryservice.service.impl;
2
+
3
+import java.util.ArrayList;
4
+import java.util.List;
5
+import java.util.Map;
6
+import org.springframework.beans.factory.annotation.Autowired;
7
+import org.springframework.stereotype.Service;
8
+import org.springframework.transaction.annotation.Transactional;
9
+import com.ruoyi.common.core.domain.TreeSelect;
10
+import com.ruoyi.common.exception.ServiceException;
11
+import com.ruoyi.web.modules.industryservice.domain.BizThreeAssetsProblemReport;
12
+import com.ruoyi.web.modules.industryservice.mapper.BizThreeAssetsProblemReportMapper;
13
+import com.ruoyi.web.modules.industryservice.service.IBizThreeAssetsProblemReportService;
14
+import com.ruoyi.web.modules.industryservice.support.ReportDeptDataScopeSupport;
15
+import com.ruoyi.web.modules.industryservice.support.ThreeAssetsProblemReportValidation;
16
+import com.ruoyi.web.modules.industryservice.support.TownDeptSupport;
17
+
18
+/**
19
+ * 三资具体问题上报服务实现。
20
+ */
21
+@Service
22
+public class BizThreeAssetsProblemReportServiceImpl implements IBizThreeAssetsProblemReportService
23
+{
24
+    @Autowired
25
+    private BizThreeAssetsProblemReportMapper mapper;
26
+
27
+    @Autowired
28
+    private TownDeptSupport townDeptSupport;
29
+
30
+    @Override
31
+    public BizThreeAssetsProblemReport selectBizThreeAssetsProblemReportById(Long id)
32
+    {
33
+        return mapper.selectBizThreeAssetsProblemReportById(id);
34
+    }
35
+
36
+    @Override
37
+    public List<BizThreeAssetsProblemReport> selectBizThreeAssetsProblemReportList(BizThreeAssetsProblemReport query)
38
+    {
39
+        ReportDeptDataScopeSupport.apply(query, "r");
40
+        return mapper.selectBizThreeAssetsProblemReportList(query);
41
+    }
42
+
43
+    @Override
44
+    @Transactional(rollbackFor = Exception.class)
45
+    public int insertBizThreeAssetsProblemReport(BizThreeAssetsProblemReport row)
46
+    {
47
+        ThreeAssetsProblemReportValidation.validateRowForSave(row, townDeptSupport);
48
+        return mapper.insertBizThreeAssetsProblemReport(row);
49
+    }
50
+
51
+    @Override
52
+    @Transactional(rollbackFor = Exception.class)
53
+    public int updateBizThreeAssetsProblemReport(BizThreeAssetsProblemReport row)
54
+    {
55
+        if (row.getId() == null)
56
+        {
57
+            throw new ServiceException("主键不能为空");
58
+        }
59
+        requireExistingRow(row.getId());
60
+        ThreeAssetsProblemReportValidation.validateRowForSave(row, townDeptSupport);
61
+        return mapper.updateBizThreeAssetsProblemReport(row);
62
+    }
63
+
64
+    @Override
65
+    @Transactional(rollbackFor = Exception.class)
66
+    public int deleteBizThreeAssetsProblemReportByIds(Long[] ids, String updateBy)
67
+    {
68
+        if (ids == null || ids.length == 0)
69
+        {
70
+            return 0;
71
+        }
72
+        List<Long> cleaned = new ArrayList<>();
73
+        for (Long id : ids)
74
+        {
75
+            if (id != null)
76
+            {
77
+                cleaned.add(id);
78
+            }
79
+        }
80
+        if (cleaned.isEmpty())
81
+        {
82
+            return 0;
83
+        }
84
+        return mapper.deleteBizThreeAssetsProblemReportByIds(cleaned.toArray(new Long[0]));
85
+    }
86
+
87
+    @Override
88
+    public List<Map<String, Object>> listTownOptions()
89
+    {
90
+        return townDeptSupport.toOptionList();
91
+    }
92
+
93
+    @Override
94
+    public List<TreeSelect> listVillageTree()
95
+    {
96
+        return townDeptSupport.buildVillageTree();
97
+    }
98
+
99
+    private BizThreeAssetsProblemReport requireExistingRow(Long id)
100
+    {
101
+        BizThreeAssetsProblemReport row = mapper.selectBizThreeAssetsProblemReportById(id);
102
+        if (row == null)
103
+        {
104
+            throw new ServiceException("记录不存在");
105
+        }
106
+        return row;
107
+    }
108
+}

+ 42 - 0
baqing-admin/src/main/java/com/ruoyi/web/modules/industryservice/support/ThreeAssetsProblemReportRules.java

@@ -0,0 +1,42 @@
1
+package com.ruoyi.web.modules.industryservice.support;
2
+
3
+/**
4
+ * 三资具体问题上报常量。
5
+ * <p>问题类型 Excel 未列选项,按「三资」暂定资金/资产/资源/其他;问题等级:一般/重点/重大。</p>
6
+ */
7
+public final class ThreeAssetsProblemReportRules
8
+{
9
+    /** 资金问题 */
10
+    public static final String TYPE_FUND = "fund";
11
+    /** 资产问题 */
12
+    public static final String TYPE_ASSET = "asset";
13
+    /** 资源问题 */
14
+    public static final String TYPE_RESOURCE = "resource";
15
+    /** 其他 */
16
+    public static final String TYPE_OTHER = "other";
17
+
18
+    /** 一般 */
19
+    public static final String LEVEL_GENERAL = "general";
20
+    /** 重点 */
21
+    public static final String LEVEL_KEY = "key";
22
+    /** 重大 */
23
+    public static final String LEVEL_MAJOR = "major";
24
+
25
+    public static final int MAX_DETAIL_LEN = 2000;
26
+    public static final int MAX_HANDLE_RESULT_LEN = 2000;
27
+
28
+    private ThreeAssetsProblemReportRules()
29
+    {
30
+    }
31
+
32
+    public static boolean isValidType(String type)
33
+    {
34
+        return TYPE_FUND.equals(type) || TYPE_ASSET.equals(type)
35
+                || TYPE_RESOURCE.equals(type) || TYPE_OTHER.equals(type);
36
+    }
37
+
38
+    public static boolean isValidLevel(String level)
39
+    {
40
+        return LEVEL_GENERAL.equals(level) || LEVEL_KEY.equals(level) || LEVEL_MAJOR.equals(level);
41
+    }
42
+}

+ 93 - 0
baqing-admin/src/main/java/com/ruoyi/web/modules/industryservice/support/ThreeAssetsProblemReportValidation.java

@@ -0,0 +1,93 @@
1
+package com.ruoyi.web.modules.industryservice.support;
2
+
3
+import java.util.Date;
4
+import com.ruoyi.common.core.domain.entity.SysDept;
5
+import com.ruoyi.common.exception.ServiceException;
6
+import com.ruoyi.common.utils.StringUtils;
7
+import com.ruoyi.web.modules.industryservice.domain.BizThreeAssetsProblemReport;
8
+
9
+/**
10
+ * 三资具体问题上报校验:村反推乡镇、类型/等级枚举、描述长度。
11
+ */
12
+public final class ThreeAssetsProblemReportValidation
13
+{
14
+    private ThreeAssetsProblemReportValidation()
15
+    {
16
+    }
17
+
18
+    public static void validateRowForSave(BizThreeAssetsProblemReport row, TownDeptSupport townDeptSupport)
19
+    {
20
+        if (row == null)
21
+        {
22
+            throw new ServiceException("参数不能为空");
23
+        }
24
+        if (row.getVillageDeptId() == null)
25
+        {
26
+            throw new ServiceException("所属村不能为空");
27
+        }
28
+        SysDept village = townDeptSupport.requireReportVillage(row.getVillageDeptId());
29
+        if (village == null)
30
+        {
31
+            throw new ServiceException("所属村不合法");
32
+        }
33
+        SysDept town = townDeptSupport.requireReportTown(village.getParentId());
34
+        if (town == null)
35
+        {
36
+            throw new ServiceException("所属村的上级乡镇不合法");
37
+        }
38
+        row.setVillageName(village.getDeptName());
39
+        row.setTownDeptId(town.getDeptId());
40
+        row.setTownName(town.getDeptName());
41
+
42
+        if (row.getReportTime() == null)
43
+        {
44
+            row.setReportTime(new Date());
45
+        }
46
+        if (StringUtils.isEmpty(row.getProblemType()))
47
+        {
48
+            throw new ServiceException("问题类型不能为空");
49
+        }
50
+        if (!ThreeAssetsProblemReportRules.isValidType(row.getProblemType()))
51
+        {
52
+            throw new ServiceException("问题类型不合法");
53
+        }
54
+        if (StringUtils.isEmpty(row.getProblemLevel()))
55
+        {
56
+            throw new ServiceException("问题等级不能为空");
57
+        }
58
+        if (!ThreeAssetsProblemReportRules.isValidLevel(row.getProblemLevel()))
59
+        {
60
+            throw new ServiceException("问题等级不合法");
61
+        }
62
+        String detail = StringUtils.trim(row.getProblemDetail());
63
+        if (StringUtils.isEmpty(detail))
64
+        {
65
+            throw new ServiceException("问题详细描述不能为空");
66
+        }
67
+        if (detail.length() > ThreeAssetsProblemReportRules.MAX_DETAIL_LEN)
68
+        {
69
+            throw new ServiceException("问题详细描述不能超过"
70
+                    + ThreeAssetsProblemReportRules.MAX_DETAIL_LEN + "字");
71
+        }
72
+        row.setProblemDetail(detail);
73
+
74
+        String handle = StringUtils.trim(row.getHandleResult());
75
+        if (StringUtils.isEmpty(handle))
76
+        {
77
+            row.setHandleResult(null);
78
+        }
79
+        else
80
+        {
81
+            if (handle.length() > ThreeAssetsProblemReportRules.MAX_HANDLE_RESULT_LEN)
82
+            {
83
+                throw new ServiceException("处理结果不能超过"
84
+                        + ThreeAssetsProblemReportRules.MAX_HANDLE_RESULT_LEN + "字");
85
+            }
86
+            row.setHandleResult(handle);
87
+        }
88
+        if (StringUtils.isNotEmpty(row.getRemark()) && row.getRemark().length() > 500)
89
+        {
90
+            throw new ServiceException("备注不能超过500字");
91
+        }
92
+    }
93
+}

+ 103 - 0
baqing-admin/src/main/resources/mapper/industryservice/BizThreeAssetsProblemReportMapper.xml

@@ -0,0 +1,103 @@
1
+<?xml version="1.0" encoding="UTF-8" ?>
2
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
3
+<!-- 三资具体问题上报 biz_three_assets_problem_report -->
4
+<mapper namespace="com.ruoyi.web.modules.industryservice.mapper.BizThreeAssetsProblemReportMapper">
5
+
6
+    <resultMap type="com.ruoyi.web.modules.industryservice.domain.BizThreeAssetsProblemReport"
7
+               id="BizThreeAssetsProblemReportResult">
8
+        <id     property="id"              column="id"/>
9
+        <result property="reportTime"      column="report_time"/>
10
+        <result property="townDeptId"      column="town_dept_id"/>
11
+        <result property="townName"        column="town_name"/>
12
+        <result property="villageDeptId"   column="village_dept_id"/>
13
+        <result property="villageName"     column="village_name"/>
14
+        <result property="problemType"     column="problem_type"/>
15
+        <result property="problemLevel"    column="problem_level"/>
16
+        <result property="problemDetail"   column="problem_detail"/>
17
+        <result property="handleResult"    column="handle_result"/>
18
+        <result property="createBy"        column="create_by"/>
19
+        <result property="createTime"      column="create_time"/>
20
+        <result property="updateBy"        column="update_by"/>
21
+        <result property="updateTime"      column="update_time"/>
22
+        <result property="remark"          column="remark"/>
23
+    </resultMap>
24
+
25
+    <sql id="selectVo">
26
+        select r.id, r.report_time, r.town_dept_id, r.town_name, r.village_dept_id, r.village_name,
27
+               r.problem_type, r.problem_level, r.problem_detail, r.handle_result,
28
+               r.create_by, r.create_time, r.update_by, r.update_time, r.remark
29
+        from biz_three_assets_problem_report r
30
+    </sql>
31
+
32
+    <select id="selectBizThreeAssetsProblemReportById" parameterType="long"
33
+            resultMap="BizThreeAssetsProblemReportResult">
34
+        <include refid="selectVo"/>
35
+        where r.id = #{id}
36
+    </select>
37
+
38
+    <select id="selectBizThreeAssetsProblemReportList"
39
+            parameterType="com.ruoyi.web.modules.industryservice.domain.BizThreeAssetsProblemReport"
40
+            resultMap="BizThreeAssetsProblemReportResult">
41
+        <include refid="selectVo"/>
42
+        left join sys_dept d on r.town_dept_id = d.dept_id
43
+        left join sys_dept v on r.village_dept_id = v.dept_id
44
+        <where>
45
+            <if test="townDeptId != null">
46
+                and r.town_dept_id = #{townDeptId}
47
+            </if>
48
+            <if test="villageDeptId != null">
49
+                and r.village_dept_id = #{villageDeptId}
50
+            </if>
51
+            <if test="problemType != null and problemType != ''">
52
+                and r.problem_type = #{problemType}
53
+            </if>
54
+            <if test="beginReportTime != null">
55
+                and date_format(r.report_time,'%y%m%d') &gt;= date_format(#{beginReportTime},'%y%m%d')
56
+            </if>
57
+            <if test="endReportTime != null">
58
+                and date_format(r.report_time,'%y%m%d') &lt;= date_format(#{endReportTime},'%y%m%d')
59
+            </if>
60
+            ${params.dataScope}
61
+        </where>
62
+        order by r.report_time desc, d.order_num asc, v.order_num asc, r.id desc
63
+    </select>
64
+
65
+    <insert id="insertBizThreeAssetsProblemReport"
66
+            parameterType="com.ruoyi.web.modules.industryservice.domain.BizThreeAssetsProblemReport"
67
+            useGeneratedKeys="true" keyProperty="id">
68
+        insert into biz_three_assets_problem_report (
69
+            report_time, town_dept_id, town_name, village_dept_id, village_name,
70
+            problem_type, problem_level, problem_detail, handle_result,
71
+            create_by, create_time, remark
72
+        ) values (
73
+            #{reportTime}, #{townDeptId}, #{townName}, #{villageDeptId}, #{villageName},
74
+            #{problemType}, #{problemLevel}, #{problemDetail}, #{handleResult},
75
+            #{createBy}, sysdate(), #{remark}
76
+        )
77
+    </insert>
78
+
79
+    <update id="updateBizThreeAssetsProblemReport"
80
+            parameterType="com.ruoyi.web.modules.industryservice.domain.BizThreeAssetsProblemReport">
81
+        update biz_three_assets_problem_report set
82
+            report_time = #{reportTime},
83
+            town_dept_id = #{townDeptId},
84
+            town_name = #{townName},
85
+            village_dept_id = #{villageDeptId},
86
+            village_name = #{villageName},
87
+            problem_type = #{problemType},
88
+            problem_level = #{problemLevel},
89
+            problem_detail = #{problemDetail},
90
+            handle_result = #{handleResult},
91
+            update_by = #{updateBy},
92
+            update_time = sysdate(),
93
+            remark = #{remark}
94
+        where id = #{id}
95
+    </update>
96
+
97
+    <delete id="deleteBizThreeAssetsProblemReportByIds">
98
+        delete from biz_three_assets_problem_report where id in
99
+        <foreach collection="ids" item="id" open="(" separator="," close=")">
100
+            #{id}
101
+        </foreach>
102
+    </delete>
103
+</mapper>

+ 86 - 0
baqing-admin/src/test/java/com/ruoyi/web/modules/industryservice/support/ThreeAssetsProblemReportValidationTest.java

@@ -0,0 +1,86 @@
1
+package com.ruoyi.web.modules.industryservice.support;
2
+
3
+import static org.junit.jupiter.api.Assertions.assertEquals;
4
+import static org.junit.jupiter.api.Assertions.assertNotNull;
5
+import static org.junit.jupiter.api.Assertions.assertThrows;
6
+import static org.mockito.Mockito.when;
7
+
8
+import org.junit.jupiter.api.DisplayName;
9
+import org.junit.jupiter.api.Test;
10
+import org.junit.jupiter.api.extension.ExtendWith;
11
+import org.mockito.Mock;
12
+import org.mockito.junit.jupiter.MockitoExtension;
13
+import com.ruoyi.common.core.domain.entity.SysDept;
14
+import com.ruoyi.common.exception.ServiceException;
15
+import com.ruoyi.web.modules.industryservice.domain.BizThreeAssetsProblemReport;
16
+
17
+@ExtendWith(MockitoExtension.class)
18
+@DisplayName("ThreeAssetsProblemReportValidation")
19
+class ThreeAssetsProblemReportValidationTest
20
+{
21
+    @Mock
22
+    private TownDeptSupport townDeptSupport;
23
+
24
+    @Test
25
+    @DisplayName("保存时反填乡镇并默认上报时间")
26
+    void fillTownAndDefaultReportTime()
27
+    {
28
+        SysDept town = town(101L, "雅安镇");
29
+        SysDept village = village(201L, "荣嘎村", 101L);
30
+        when(townDeptSupport.requireReportVillage(201L)).thenReturn(village);
31
+        when(townDeptSupport.requireReportTown(101L)).thenReturn(town);
32
+
33
+        BizThreeAssetsProblemReport row = new BizThreeAssetsProblemReport();
34
+        row.setVillageDeptId(201L);
35
+        row.setProblemType(ThreeAssetsProblemReportRules.TYPE_FUND);
36
+        row.setProblemLevel(ThreeAssetsProblemReportRules.LEVEL_GENERAL);
37
+        row.setProblemDetail("资金账目不清");
38
+        ThreeAssetsProblemReportValidation.validateRowForSave(row, townDeptSupport);
39
+
40
+        assertEquals(101L, row.getTownDeptId());
41
+        assertEquals("雅安镇", row.getTownName());
42
+        assertEquals("荣嘎村", row.getVillageName());
43
+        assertNotNull(row.getReportTime());
44
+    }
45
+
46
+    @Test
47
+    @DisplayName("问题类型不合法时拒绝")
48
+    void invalidTypeRejected()
49
+    {
50
+        SysDept town = town(101L, "雅安镇");
51
+        SysDept village = village(201L, "荣嘎村", 101L);
52
+        when(townDeptSupport.requireReportVillage(201L)).thenReturn(village);
53
+        when(townDeptSupport.requireReportTown(101L)).thenReturn(town);
54
+
55
+        BizThreeAssetsProblemReport row = new BizThreeAssetsProblemReport();
56
+        row.setVillageDeptId(201L);
57
+        row.setProblemType("unknown");
58
+        row.setProblemLevel(ThreeAssetsProblemReportRules.LEVEL_KEY);
59
+        row.setProblemDetail("描述");
60
+        assertThrows(ServiceException.class,
61
+                () -> ThreeAssetsProblemReportValidation.validateRowForSave(row, townDeptSupport));
62
+    }
63
+
64
+    private static SysDept town(Long id, String name)
65
+    {
66
+        SysDept d = new SysDept();
67
+        d.setDeptId(id);
68
+        d.setDeptName(name);
69
+        d.setParentId(YakHerdInventoryRules.TOWN_PARENT_ID);
70
+        d.setOrderNum(20);
71
+        d.setStatus("0");
72
+        d.setDelFlag("0");
73
+        return d;
74
+    }
75
+
76
+    private static SysDept village(Long id, String name, Long townId)
77
+    {
78
+        SysDept d = new SysDept();
79
+        d.setDeptId(id);
80
+        d.setDeptName(name);
81
+        d.setParentId(townId);
82
+        d.setStatus("0");
83
+        d.setDelFlag("0");
84
+        return d;
85
+    }
86
+}

+ 57 - 0
doc/产业数据模型及服务/三资具体问题上报/三资具体问题上报功能需求.md

@@ -0,0 +1,57 @@
1
+# 三资具体问题上报 — 功能需求
2
+
3
+## 1. 文档说明
4
+
5
+| 项 | 说明 |
6
+| --- | --- |
7
+| 模块名称 | 三资具体问题上报 |
8
+| 来源 | `三资具体问题上报.xlsx` |
9
+| 范围 | 普通增删改查;**无需**导入/导出 |
10
+
11
+---
12
+
13
+## 2. 字段
14
+
15
+| 字段 | 逻辑 | 搜索 | 列表 | 表单 |
16
+| --- | --- | --- | --- | --- |
17
+| 上报时间 | 新增默认当前时间 | √(日期区间) | √ | √ |
18
+| 所属村 | 必填;反推乡镇 | √ | √ | √ |
19
+| 所属乡镇 | 由村反推 | √ | √ | 查看展示 |
20
+| 问题类型 | 单选 | √ | √ | √ |
21
+| 问题等级 | 单选:一般/重点/重大 | — | √ | √ |
22
+| 问题详细描述 | 必填,≤2000 字 | — | √ | √ |
23
+| 处理结果 | 选填,≤2000 字 | — | — | √ |
24
+
25
+**问题类型说明**:Excel 仅写「单选,」未列选项;实现暂按三资类别:资金问题 / 资产问题 / 资源问题 / 其他(码值 `fund`/`asset`/`resource`/`other`)。若业务另有口径可再改。
26
+
27
+**问题等级码值**:`general`(一般)/ `key`(重点)/ `major`(重大)。
28
+
29
+---
30
+
31
+## 3. 业务规则
32
+
33
+1. 普通 CRUD,无导入导出。
34
+2. 新增时上报时间默认当前时间(前后端均可带默认值;后端空则补 `now`)。
35
+3. 保存时按所属村反推并落库乡镇。
36
+4. 列表/乡镇村下拉沿用填报部门数据权限(乡镇看本镇及村,村看本村)。
37
+
38
+---
39
+
40
+## 4. 权限与菜单
41
+
42
+- 权限:`dataModel:threeAssetsProblemReport:list|query|add|edit|remove`
43
+- 组件:`dataModel/threeAssetsProblemReport/index`
44
+
45
+---
46
+
47
+## 5. 相关文档
48
+
49
+- [三资具体问题上报技术方案.md](./三资具体问题上报技术方案.md)
50
+- [三资具体问题上报前端技术方案.md](./三资具体问题上报前端技术方案.md)
51
+- [三资具体问题上报测试用例.md](./三资具体问题上报测试用例.md)
52
+
53
+## 6. 修订记录
54
+
55
+| 版本 | 说明 |
56
+| --- | --- |
57
+| 1.0 | 初版:按 Excel 实现 CRUD |

+ 60 - 0
doc/产业数据模型及服务/三资具体问题上报/三资具体问题上报技术方案.md

@@ -0,0 +1,60 @@
1
+# 三资具体问题上报 — 技术方案
2
+
3
+## 1. 架构
4
+
5
+Controller `/dataModel/threeAssetsProblemReport` → Service → Mapper;校验 `ThreeAssetsProblemReportValidation`;列表数据范围 `ReportDeptDataScopeSupport`;乡镇/村 `TownDeptSupport`。
6
+
7
+## 2. 表结构
8
+
9
+见 `sql/biz_three_assets_problem_report.sql`。
10
+
11
+| 列 | 说明 |
12
+| --- | --- |
13
+| `report_time` | 上报时间 |
14
+| `town_dept_id` / `town_name` | 乡镇 |
15
+| `village_dept_id` / `village_name` | 村 |
16
+| `problem_type` | fund/asset/resource/other |
17
+| `problem_level` | general/key/major |
18
+| `problem_detail` | 详细描述 |
19
+| `handle_result` | 处理结果(可空) |
20
+
21
+物理删除;无村级唯一约束(同一村可多次上报)。
22
+
23
+## 3. 接口
24
+
25
+| 方法 | 路径 | 权限 |
26
+| --- | --- | --- |
27
+| GET | `/list` | list |
28
+| GET | `/{id}` | query |
29
+| POST | `/` | add |
30
+| PUT | `/` | edit |
31
+| DELETE | `/{ids}` | remove |
32
+| GET | `/townOptions` | list |
33
+| GET | `/villageTree` | list |
34
+
35
+列表筛选:`beginReportTime`/`endReportTime`、`townDeptId`、`villageDeptId`、`problemType`。
36
+
37
+## 4. 前端
38
+
39
+详见 [三资具体问题上报前端技术方案.md](./三资具体问题上报前端技术方案.md)。
40
+
41
+## 5. 菜单示例
42
+
43
+```sql
44
+-- parent_id 替换为「产业数据模型」实际 ID;menu_id 按环境递增
45
+INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
46
+VALUES ('三资具体问题上报', {parentId}, 20, 'threeAssetsProblemReport', 'dataModel/threeAssetsProblemReport/index', 1, 0, 'C', '0', '0', 'dataModel:threeAssetsProblemReport:list', 'form', 'admin', sysdate(), '三资具体问题上报');
47
+
48
+-- 按钮权限(parent_id = 上菜单 id)
49
+INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) VALUES
50
+('三资问题上报查询', {menuId}, 1, '#', '', 1, 0, 'F', '0', '0', 'dataModel:threeAssetsProblemReport:query', '#', 'admin', sysdate(), ''),
51
+('三资问题上报新增', {menuId}, 2, '#', '', 1, 0, 'F', '0', '0', 'dataModel:threeAssetsProblemReport:add', '#', 'admin', sysdate(), ''),
52
+('三资问题上报修改', {menuId}, 3, '#', '', 1, 0, 'F', '0', '0', 'dataModel:threeAssetsProblemReport:edit', '#', 'admin', sysdate(), ''),
53
+('三资问题上报删除', {menuId}, 4, '#', '', 1, 0, 'F', '0', '0', 'dataModel:threeAssetsProblemReport:remove', '#', 'admin', sysdate(), '');
54
+```
55
+
56
+## 6. 修订记录
57
+
58
+| 版本 | 说明 |
59
+| --- | --- |
60
+| 1.0 | 初版 |

+ 35 - 0
doc/产业数据模型及服务/三资具体问题上报/三资具体问题上报测试用例.md

@@ -0,0 +1,35 @@
1
+# 三资具体问题上报 — 测试用例
2
+
3
+> **接口 Base Path**:`/dataModel/threeAssetsProblemReport`
4
+
5
+## 1. 列表与筛选
6
+
7
+| 编号 | 步骤 | 期望 |
8
+| --- | --- | --- |
9
+| L1 | 超管打开列表 | 返回分页数据 |
10
+| L2 | 按上报时间区间筛选 | 仅区间内记录 |
11
+| L3 | 按乡镇/村/问题类型筛选 | 条件生效 |
12
+| L4 | 乡镇账号登录 | 仅本镇数据;乡镇下拉仅本镇 |
13
+
14
+## 2. 新增
15
+
16
+| 编号 | 步骤 | 期望 |
17
+| --- | --- | --- |
18
+| A1 | 打开新增 | 上报时间默认当前 |
19
+| A2 | 不选村提交 | 校验失败 |
20
+| A3 | 必填齐全提交 | 成功;乡镇由村反推落库 |
21
+| A4 | 问题类型非法码 | 后端拒绝 |
22
+
23
+## 3. 修改 / 查看 / 删除
24
+
25
+| 编号 | 步骤 | 期望 |
26
+| --- | --- | --- |
27
+| U1 | 修改描述与处理结果 | 保存成功 |
28
+| V1 | 查看详情 | 展示全部字段含处理结果 |
29
+| D1 | 删除一条 | 物理删除,列表不再出现 |
30
+
31
+## 4. 修订记录
32
+
33
+| 版本 | 说明 |
34
+| --- | --- |
35
+| 1.0 | 初版 |

+ 24 - 0
sql/biz_three_assets_problem_report.sql

@@ -0,0 +1,24 @@
1
+-- 三资具体问题上报(物理删除;普通 CRUD,无导入导出)
2
+DROP TABLE IF EXISTS `biz_three_assets_problem_report`;
3
+CREATE TABLE `biz_three_assets_problem_report` (
4
+  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
5
+  `report_time` datetime NOT NULL COMMENT '上报时间',
6
+  `town_dept_id` bigint(20) NOT NULL COMMENT '所属乡镇dept_id',
7
+  `town_name` varchar(64) NOT NULL COMMENT '乡镇名称',
8
+  `village_dept_id` bigint(20) NOT NULL COMMENT '所属村dept_id',
9
+  `village_name` varchar(128) NOT NULL COMMENT '所属村名称',
10
+  `problem_type` varchar(32) NOT NULL COMMENT '问题类型:fund/asset/resource/other',
11
+  `problem_level` varchar(16) NOT NULL COMMENT '问题等级:general/key/major',
12
+  `problem_detail` varchar(2000) NOT NULL COMMENT '问题详细描述',
13
+  `handle_result` varchar(2000) DEFAULT NULL COMMENT '处理结果',
14
+  `create_by` varchar(64) DEFAULT '' COMMENT '创建者',
15
+  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
16
+  `update_by` varchar(64) DEFAULT '' COMMENT '更新者',
17
+  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
18
+  `remark` varchar(500) DEFAULT NULL COMMENT '备注',
19
+  PRIMARY KEY (`id`),
20
+  KEY `idx_town_dept_id` (`town_dept_id`),
21
+  KEY `idx_village_dept_id` (`village_dept_id`),
22
+  KEY `idx_report_time` (`report_time`),
23
+  KEY `idx_problem_type` (`problem_type`)
24
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='三资具体问题上报';