Bladeren bron

土地供应统计计算(年度分析逻辑)

chenendian 1 maand geleden
bovenliggende
commit
522befbfcf

+ 45 - 1
siwei-modules/siwei-apply/src/main/java/com/siwei/apply/common/Constant.java

@@ -1,6 +1,7 @@
 package com.siwei.apply.common;
 
 import java.util.List;
+import java.util.Map;
 
 public class Constant {
     public static String UserId = "123456789"; // 用户ID
@@ -21,4 +22,47 @@ public class Constant {
     );
 
 
-}
+
+    public static final Map<String,List<String>> TDYG_TDYT_MAP = Map.ofEntries(
+
+
+            Map.entry("城镇住宅用地", List.of(
+                    "居住用地"
+            )),
+            Map.entry("教育用地", List.of(
+                    "公共管理与公共服务用地(教育用地)"
+            )),
+            Map.entry("商业用地", List.of(
+                    "商住用地",
+                    "商业服务业用地(加油站)",
+                    "公共管理与公共服务用地(科研用地)",
+                    "公共管理与公共服务用地(文化设施用地)",
+                    "特殊用地",
+                    "特殊用地(宗教用地)",
+                    "公共管理与公共服务用地(机关团体用地)",
+                    "公用设施用地(供电用地)",
+                    "公共管理与公共服务用地",
+                    "公用设施用地(供热用地)",
+                    "商业服务业用地",
+                    "公用设施用地"
+            )),
+            Map.entry("工业用地", List.of(
+                    "工业用地"
+            )),
+            Map.entry("物流仓储用地", List.of(
+                    "物流仓储用地"
+            )),
+            Map.entry("公路用地", List.of(
+                    "交通运输用地",
+                    "交通运输用地(其他交通设施用地)"
+            )),
+            Map.entry("工业绿地", List.of(
+                    "公园与绿地",
+                    "绿地与开敞空间用地"
+            ))
+    );
+
+
+
+
+    }

+ 28 - 3
siwei-modules/siwei-apply/src/main/java/com/siwei/apply/controller/cadastre/SupplyController.java

@@ -38,9 +38,6 @@ public class SupplyController extends BaseController {
 
 
 
-
-
-
     /**
      *
      * 年度统计
@@ -48,6 +45,24 @@ public class SupplyController extends BaseController {
      */
     @GetMapping("/yearStatistics/{year}")
     public R<SupplyYearStatisticsRes> getYearStatistics(@PathVariable String year) {
+        try {
+            SupplyYearStatisticsRes res =  supplyService.yearStatistics(year);
+            return R.ok(res);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return R.fail(e.getMessage());
+        }
+    }
+
+
+
+    /**
+     *
+     * 年度统计2
+     *
+     */
+    @GetMapping("/yearStatistics2/{year}")
+    public R<SupplyYearStatisticsRes> getYearStatistics2(@PathVariable String year) {
         try {
             SupplyYearStatisticsRes res = new SupplyYearStatisticsRes();
             if (year.equalsIgnoreCase("2024")) {
@@ -152,6 +167,16 @@ public class SupplyController extends BaseController {
         }
     }
 
+
+
+
+
+
+
+
+
+
+
     /**
      *
      * 趋势统计

+ 2 - 0
siwei-modules/siwei-apply/src/main/java/com/siwei/apply/domain/res/ProjectSupplyRes.java

@@ -11,4 +11,6 @@ public class ProjectSupplyRes {
     private String gdUnit;// 供地单位
     private Float gdArea; // 供地面积
     private Integer count; // 供地数量
+    private Float planArea; // 计划面积
+    private Float completeArea; // 完成面积
 }

+ 34 - 0
siwei-modules/siwei-apply/src/main/java/com/siwei/apply/domain/res/TdgyStatisticsRes.java

@@ -0,0 +1,34 @@
+package com.siwei.apply.domain.res;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ *
+ */
+@Data
+public class TdgyStatisticsRes {
+
+
+    private BigDecimal mjPfm;
+
+    private BigDecimal mjMu;
+
+    private String xmmc;
+
+    private String tdyt;
+
+    private String gyfs;
+
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date gysj;
+
+    private String bz;
+
+    private String geom;
+
+
+}

+ 2 - 0
siwei-modules/siwei-apply/src/main/java/com/siwei/apply/domain/vo/GongdiJihuaFilterVo.java

@@ -15,6 +15,8 @@ public class GongdiJihuaFilterVo {
 
     private String endDate;
 
+    private String year;
+
     private Integer pageNum = 1;
 
     private Integer pageSize = 10;

+ 63 - 0
siwei-modules/siwei-apply/src/main/java/com/siwei/apply/enums/LandUseTypeEnum.java

@@ -0,0 +1,63 @@
+package com.siwei.apply.enums;
+
+/**
+ *  土地用途映射表
+ */
+public enum LandUseTypeEnum {
+
+    USE_TYPE_1("09", "商业服务业用地(加油站)", "商业服务业用地"),
+    USE_TYPE_2("08", "公共管理与公共服务用地(科研用地)", "公共管理与公共服务用地"),
+    USE_TYPE_3("07", "居住用地", "居住用地"),
+    USE_TYPE_4("08", "公共管理与公共服务用地(文化设施用地)", "公共管理与公共服务用地"),
+    USE_TYPE_5("14", "公园与绿地", "绿地与开敞空间用地"),
+    USE_TYPE_6("10", "工业用地", "工矿用地"),
+    USE_TYPE_7("15", "特殊用地", "特殊用地"),
+    USE_TYPE_8("15", "特殊用地(宗教用地)", "特殊用地"),
+    USE_TYPE_9("12", "交通运输用地", "交通运输用地"),
+    USE_TYPE_10("08", "公共管理与公共服务用地(机关团体用地)", "公共管理与公共服务用地"),
+    USE_TYPE_11("12", "交通运输用地(其他交通设施用地)", "交通运输用地"),
+    USE_TYPE_12("14", "绿地与开敞空间用地", "绿地与开敞空间用地"),
+    USE_TYPE_13("13", "公用设施用地(供电用地)", "公用设施用地"),
+    USE_TYPE_14("08", "公共管理与公共服务用地", "公共管理与公共服务用地"),
+    USE_TYPE_15("13", "公用设施用地(供热用地)", "公用设施用地"),
+    USE_TYPE_16("08", "公共管理与公共服务用地(教育用地)", "公共管理与公共服务用地"),
+    USE_TYPE_17("13", "公用设施用地", "公用设施用地"),
+    USE_TYPE_18("09", "商业服务业用地", "商业服务业用地"),
+    USE_TYPE_19("00", "商住用地", "其它");
+
+    private final String code;
+    private final String name;
+    private final String parentName;
+
+    LandUseTypeEnum(String code, String name, String parentName) {
+        this.code = code;
+        this.name = name;
+        this.parentName = parentName;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getParentName() {
+        return parentName;
+    }
+
+    /**
+     * 根据名称获取对应的代码
+     * @param name 用途名称
+     * @return 对应代码,未找到返回 null
+     */
+    public static String getCodeByName(String name) {
+        for (LandUseTypeEnum type : LandUseTypeEnum.values()) {
+            if (type.getName().equals(name)) {
+                return type.getCode();
+            }
+        }
+        return null;
+    }
+}

+ 2 - 0
siwei-modules/siwei-apply/src/main/java/com/siwei/apply/mapper/LandTypeMapper.java

@@ -9,5 +9,7 @@ import java.util.List;
 public interface LandTypeMapper {
     /** 查询所有地块类型 */
     List<LandType> selectAll();
+
+    LandType  selectByCode(String code);
 }
 

+ 12 - 0
siwei-modules/siwei-apply/src/main/java/com/siwei/apply/mapper/TdgyMapper.java

@@ -2,11 +2,13 @@ package com.siwei.apply.mapper;
 
 import com.siwei.apply.domain.Tdgy;
 import com.siwei.apply.domain.res.ProjectSupplyRes;
+import com.siwei.apply.domain.res.TdgyStatisticsRes;
 import com.siwei.apply.domain.vo.TdgyUpdateVo;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
+import java.util.Map;
 
 // 土地供应 Mapper 接口
 @Mapper
@@ -55,4 +57,14 @@ public interface TdgyMapper {
      * 返回字段:gdType, count, gdArea, gdUnit,可选传入 projectType 过滤 t_project.project_type
      */
     List<ProjectSupplyRes> countAndSumByGdType(@Param("projectType") Integer projectType);
+
+
+
+    List<TdgyStatisticsRes> getListByYear(@Param("year") String year);
+
+
+
+
+
+
 }

+ 2 - 0
siwei-modules/siwei-apply/src/main/java/com/siwei/apply/service/cadastre/ISupplyService.java

@@ -2,6 +2,7 @@ package com.siwei.apply.service.cadastre;
 
 
 import com.siwei.apply.domain.cadastre.LandSupplyReportDTO;
+import com.siwei.apply.domain.res.SupplyYearStatisticsRes;
 import com.siwei.common.core.domain.R;
 
 
@@ -11,5 +12,6 @@ public interface ISupplyService {
     LandSupplyReportDTO getTdgyReport(String startTime,String endTime); //  supplyService.getTdgyReport(startTime,endTime);
 
 
+    SupplyYearStatisticsRes yearStatistics(String year);
 
 }

+ 193 - 3
siwei-modules/siwei-apply/src/main/java/com/siwei/apply/service/cadastre/impl/SupplyServiceImpl.java

@@ -1,16 +1,24 @@
 package com.siwei.apply.service.cadastre.impl;
 
+import com.siwei.apply.common.Constant;
+import com.siwei.apply.domain.GongdiJihua;
+import com.siwei.apply.domain.LandType;
 import com.siwei.apply.domain.cadastre.*;
+import com.siwei.apply.domain.res.*;
+import com.siwei.apply.domain.vo.GongdiJihuaFilterVo;
+import com.siwei.apply.enums.LandUseTypeEnum;
 import com.siwei.apply.mapper.GongdiJihuaMapper;
+import com.siwei.apply.mapper.LandTypeMapper;
+import com.siwei.apply.mapper.TdgyMapper;
 import com.siwei.apply.service.cadastre.ISupplyService;
+import org.apache.commons.collections4.CollectionUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.math.BigDecimal;
 import java.math.RoundingMode;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
+import java.util.stream.Collectors;
 
 
 @Service
@@ -19,11 +27,193 @@ public class SupplyServiceImpl implements ISupplyService {
     @Autowired
     private GongdiJihuaMapper gongdiJihuaMapper;
 
+    @Autowired
+    private TdgyMapper dgyMapper;
+
+    @Autowired
+    private LandTypeMapper landTypeMapper;
+
+
+
     @Override
     public Object GetList(String param) {
+
+        ///Map<String, Object> planSummary = gongdiJihuaMapper.getList(startTime, endTime);
+
         return null;
     }
 
+
+    /**
+     * 年度统计
+     * @param year
+     * @return
+     */
+    @Override
+    public SupplyYearStatisticsRes yearStatistics(String year) {
+        SupplyYearStatisticsRes res = new SupplyYearStatisticsRes();
+        GongdiJihuaFilterVo filterVo = new GongdiJihuaFilterVo();
+        filterVo.setYear(year);
+        filterVo.setPageSize(100000);
+        List<GongdiJihua> list = gongdiJihuaMapper.getList(filterVo);
+
+        List<TdgyStatisticsRes> completeList = dgyMapper.getListByYear(year);
+
+        if(CollectionUtils.isNotEmpty(list)) {
+            double completeRate =0;
+            if(CollectionUtils.isNotEmpty(completeList)) {
+                completeRate = (double) completeList.size() / list.size() * 100;
+            }
+            SupplyRateRes supplyRate = new SupplyRateRes();
+            //这里先计算一个供应率,后续可以根据实际需求计算其他数据
+            supplyRate.setCompleteRate((int) completeRate);
+            supplyRate.setPlanProjectCount(list.size());
+            supplyRate.setCompleteProjectCount(completeList.size()); 
+
+            //根据GongdiJihua 对象的MjMu 计算加总值
+            double planArea = list.stream()
+                .filter(g -> g.getMjMu() != null)
+                .mapToDouble(g -> g.getMjMu().doubleValue())
+                .sum();
+            supplyRate.setPlanArea((float) planArea);
+
+            //完成的计算加总值
+            double completeArea = completeList.stream()
+                    .filter(g -> g.getMjMu() != null)
+                    .mapToDouble(g -> g.getMjMu().doubleValue())
+                    .sum();
+            supplyRate.setCompleteArea((float)completeArea);
+            supplyRate.setGdUnit("亩");
+            res.setSupplyRate(supplyRate);
+
+            //这里计算用途分析和供应方式分析的list,后续可以根据实际需求计算其他数据
+            List<LandUseRes> landUseStatisticsList = new ArrayList<>(); // 用途分析
+
+            Map<String, Double> planAreaMap = list.stream()
+                    .filter(g -> g.getTdyt() != null)
+                    .map(g -> {
+                        for (LandUseTypeEnum type : LandUseTypeEnum.values()) {
+                            if (type.getName().equals(g.getTdyt())) {
+                                return Map.entry(type.getParentName(), g.getMjMu() != null ? g.getMjMu().doubleValue() : 0.0);
+                            }
+                        }
+                        return null;
+                    })
+                    .filter(Objects::nonNull)
+                    .collect(Collectors.groupingBy(Map.Entry::getKey, Collectors.summingDouble(Map.Entry::getValue)));
+
+            Map<String, Double> completeAreaMap = new HashMap<>();
+            if (CollectionUtils.isNotEmpty(completeList)) {
+                Map<String, String> codeToNameCache = new HashMap<>();
+                for (TdgyStatisticsRes g : completeList) {
+                    if (g.getTdyt() != null && g.getTdyt().length() >= 2) {
+                        String code = g.getTdyt().substring(0, 2);
+                        String categoryName = codeToNameCache.computeIfAbsent(code, k -> {
+                            LandType landType = landTypeMapper.selectByCode(k);
+                            return landType != null ? landType.getName() : null;
+                        });
+
+                        if (categoryName != null) {
+                            double area = g.getMjMu() != null ? g.getMjMu().doubleValue() : 0.0;
+                            completeAreaMap.put(categoryName, completeAreaMap.getOrDefault(categoryName, 0.0) + area);
+                        }
+                    }
+                }
+            }
+
+            Set<String> allCategories = new HashSet<>(planAreaMap.keySet());
+            allCategories.addAll(completeAreaMap.keySet());
+
+            for (String category : allCategories) {
+                LandUseRes landUseRes = new LandUseRes();
+                landUseRes.setLandUseTypeName(category);
+                landUseRes.setPlanLandUseArea(planAreaMap.getOrDefault(category, 0.0).intValue());
+                landUseRes.setCompleteLandUseArea(completeAreaMap.getOrDefault(category, 0.0).intValue());
+                landUseStatisticsList.add(landUseRes);
+            }
+            res.setLandUseStatisticsList(landUseStatisticsList);
+
+
+
+
+
+            // 根据当前list中的字段,统计不同供应方式(gyfs)进行分组,如果是 gyfs=划拨或出让分别分组,其它为一组,然后分别计算每个供应方式的计划供应面积(mjMu)和完成供应面积(0填充),最后封装成 ProjectSupplyRes 对象添加到 projectSupplyList 中
+            List<ProjectSupplyRes> projectSupplyList = new ArrayList<>(); // 供应方式
+
+            // 预先按供应方式对已完成列表进行分组求和
+            Map<String, Double> completeModeAreaMap = new HashMap<>();
+            if (CollectionUtils.isNotEmpty(completeList)) {
+                for (TdgyStatisticsRes g : completeList) {
+                    String mode = g.getGyfs();
+                    String category = ("划拨".equals(mode) || "出让".equals(mode)) ? mode : "其它";
+                    double area = g.getMjMu() != null ? g.getMjMu().doubleValue() : 0.0;
+                    completeModeAreaMap.put(category, completeModeAreaMap.getOrDefault(category, 0.0) + area);
+                }
+            }
+
+            // 1. 划拨
+            List<GongdiJihua> hbList = list.stream()
+                    .filter(g -> "划拨".equals(g.getGyfs()))
+                    .collect(Collectors.toList());
+            if (CollectionUtils.isNotEmpty(hbList)) {
+                ProjectSupplyRes resHb = new ProjectSupplyRes();
+                resHb.setGdType("划拨");
+                resHb.setGdUnit("亩");
+                resHb.setCount(hbList.size());
+                float hbPlanArea = (float) hbList.stream()
+                        .filter(g -> g.getMjMu() != null)
+                        .mapToDouble(g -> g.getMjMu().doubleValue())
+                        .sum();
+                resHb.setPlanArea(hbPlanArea);
+                resHb.setGdArea(hbPlanArea);
+                resHb.setCompleteArea(completeModeAreaMap.getOrDefault("划拨", 0.0).floatValue());
+                projectSupplyList.add(resHb);
+            }
+
+            // 2. 出让
+            List<GongdiJihua> crList = list.stream()
+                    .filter(g -> "出让".equals(g.getGyfs()))
+                    .collect(Collectors.toList());
+            if (CollectionUtils.isNotEmpty(crList)) {
+                ProjectSupplyRes resCr = new ProjectSupplyRes();
+                resCr.setGdType("出让");
+                resCr.setGdUnit("亩");
+                resCr.setCount(crList.size());
+                float crPlanArea = (float) crList.stream()
+                        .filter(g -> g.getMjMu() != null)
+                        .mapToDouble(g -> g.getMjMu().doubleValue())
+                        .sum();
+                resCr.setPlanArea(crPlanArea);
+                resCr.setGdArea(crPlanArea);
+                resCr.setCompleteArea(completeModeAreaMap.getOrDefault("出让", 0.0).floatValue());
+                projectSupplyList.add(resCr);
+            }
+
+            // 3. 其它
+            List<GongdiJihua> qtList = list.stream()
+                    .filter(g -> !"划拨".equals(g.getGyfs()) && !"出让".equals(g.getGyfs()))
+                    .collect(Collectors.toList());
+            if (CollectionUtils.isNotEmpty(qtList)) {
+                ProjectSupplyRes resQt = new ProjectSupplyRes();
+                resQt.setGdType("其它");
+                resQt.setGdUnit("亩");
+                resQt.setCount(qtList.size());
+                float qtPlanArea = (float) qtList.stream()
+                        .filter(g -> g.getMjMu() != null)
+                        .mapToDouble(g -> g.getMjMu().doubleValue())
+                        .sum();
+                resQt.setPlanArea(qtPlanArea);
+                resQt.setGdArea(qtPlanArea);
+                resQt.setCompleteArea(completeModeAreaMap.getOrDefault("其它", 0.0).floatValue());
+                projectSupplyList.add(resQt);
+            }
+            res.setProjectSupplyList(projectSupplyList);
+        }
+        return res;
+    }
+
+
+
     @Override
     public LandSupplyReportDTO getTdgyReport(String startTime, String endTime) {
         LandSupplyReportDTO report = new LandSupplyReportDTO();

+ 11 - 0
siwei-modules/siwei-apply/src/main/resources/mapper/GongdiJihuaMapper.xml

@@ -47,11 +47,22 @@
             <if test="endDate != null and endDate != ''">
                 AND gysj &lt;= #{endDate}
             </if>
+            <if test="year != null and year != ''">
+                AND  TO_CHAR(gysj, 'YYYY') = #{year}
+            </if>
         </where>
         ORDER BY gid DESC
         LIMIT #{pageSize} OFFSET #{offset}
     </select>
 
+
+
+
+
+
+
+
+
     <select id="getCount" parameterType="com.siwei.apply.domain.vo.GongdiJihuaFilterVo" resultType="int">
         SELECT COUNT(*)
         FROM vector.gj_gongdi_jihua

+ 8 - 0
siwei-modules/siwei-apply/src/main/resources/mapper/LandTypeMapper.xml

@@ -12,4 +12,12 @@
     <select id="selectAll" resultMap="LandTypeResultMap">
         SELECT code, name, parent_code, index, source FROM land_type ORDER BY index
     </select>
+
+
+    <select id="selectByCode" resultMap="LandTypeResultMap">
+        SELECT code, name, parent_code, index, source FROM land_type
+        where code = #{code}
+    </select>
+
+
 </mapper>

+ 42 - 0
siwei-modules/siwei-apply/src/main/resources/mapper/TdgyMapper.xml

@@ -119,4 +119,46 @@
         </where>
         GROUP BY COALESCE(NULLIF(TRIM(td.gd_type), ''), '其他')
     </select>
+
+
+    <!-- 跟年份查询当前土地实际供应情况! -->
+    <select id="getListByYear" resultType="com.siwei.apply.domain.res.TdgyStatisticsRes" parameterType="String">
+        SELECT
+            project.ID AS projectId,
+            project.NAME AS xmmc,
+            t_node.ID AS nodeId,
+            t_node.tdyt,
+            t_node.gd_type AS gyfs,
+            t_node.hbcrht_date AS gysj,
+            COALESCE (
+                    CASE
+                        WHEN t_node.gd_unit = '平方米' THEN
+                            COALESCE ( t_node.gd_area, 0 ) / 666.6666667-- 平方米 -> 亩
+                        WHEN t_node.gd_unit = '公顷' THEN
+                            COALESCE ( t_node.gd_area, 0 ) * 15-- 公顷 -> 亩 ELSE COALESCE ( t_node.gd_area, 0 ) -- 默认当作亩(含 '2')
+                        END,
+                    0
+            ) AS mjMu,
+            land.geom_db_id as geomDbId,
+            details.upload_id as uploadId,
+            details.geom_json as geomJson,
+            details.sort,
+            details.geom_area as geomArea,
+            details.geom
+        FROM
+            t_geom_db_details details
+            LEFT JOIN t_node_land land ON details.upload_id :: TEXT = land.geom_db_id ::TEXT
+            LEFT JOIN t_tdgy t_node ON land.node_id :: TEXT = t_node.ID ::TEXT
+            LEFT JOIN t_project project ON project.ID :: TEXT = t_node.project_id :: TEXT
+        WHERE
+            t_node.has_onchain = TRUE
+          AND project.ID IS NOT NULL
+        <if test="year != null">
+            AND  LEFT(t_node.hbcrht_date, 4) = #{year}
+        </if>
+    </select>
+
+
+
+
 </mapper>