Forráskód Böngészése

Merge branch 'master' of http://47.108.172.52:3000/dayou/item-management-1phase

GouGengquan 1 hete
szülő
commit
8d740aee08
34 módosított fájl, 721 hozzáadás és 48 törlés
  1. 23 0
      biz-base/src/main/java/com/dayou/controller/MajorProductionController.java
  2. 37 0
      biz-base/src/main/java/com/dayou/controller/PersonalFacePriceController.java
  3. BIN
      biz-base/src/main/resources/xlsx/personal/personal_face_price_batch_temp.xlsx
  4. 2 0
      common/src/main/java/com/dayou/exception/ErrorCode.java
  5. 3 3
      common/src/main/java/com/dayou/utils/AddressUtil.java
  6. 3 2
      common/src/main/java/com/dayou/utils/ExcelPlusUtil.java
  7. 21 0
      dao/src/main/java/com/dayou/mapper/BusinessNumberRecycleMapper.java
  8. 2 1
      dao/src/main/java/com/dayou/mapper/ExternalDyDataBaseMapper.java
  9. 3 2
      dao/src/main/java/com/dayou/mapper/PersonalFacePriceMapper.java
  10. 3 0
      dao/src/main/java/com/dayou/mapper/WorkFlowLogMapper.java
  11. 2 0
      dao/src/main/java/com/dayou/mapper/WorkFlowNodeInstanceMapper.java
  12. 17 0
      dao/src/main/resources/mapper/BusinessNumberRecycleMapper.xml
  13. 3 0
      dao/src/main/resources/mapper/ExternalDyDataBaseMapper.xml
  14. 1 1
      dao/src/main/resources/mapper/MajorTargetMapper.xml
  15. 8 1
      dao/src/main/resources/mapper/PersonalFacePriceMapper.xml
  16. 9 0
      dao/src/main/resources/mapper/WorkFlowLogMapper.xml
  17. 9 0
      dao/src/main/resources/mapper/WorkFlowNodeInstanceMapper.xml
  18. 45 0
      domain/src/main/java/com/dayou/dto/PersonalFacePriceBatchDTO.java
  19. 17 0
      domain/src/main/java/com/dayou/dto/PersonalFacePriceQueryDTO.java
  20. 5 0
      domain/src/main/java/com/dayou/dto/TakeNumberDTO.java
  21. 56 0
      domain/src/main/java/com/dayou/entity/BusinessNumberRecycle.java
  22. 12 1
      domain/src/main/java/com/dayou/enums/TakeNumberEnum.java
  23. 15 0
      service/src/main/java/com/dayou/service/IBusinessNumberRecycleService.java
  24. 8 0
      service/src/main/java/com/dayou/service/IBusinessNumberService.java
  25. 2 1
      service/src/main/java/com/dayou/service/IExternalDyDataBaseService.java
  26. 4 0
      service/src/main/java/com/dayou/service/IMajorProductionService.java
  27. 12 0
      service/src/main/java/com/dayou/service/IPersonalFacePriceService.java
  28. 119 0
      service/src/main/java/com/dayou/service/impl/BusinessNumberRecycleServiceImpl.java
  29. 44 18
      service/src/main/java/com/dayou/service/impl/BusinessNumberServiceImpl.java
  30. 3 2
      service/src/main/java/com/dayou/service/impl/ExternalDyDataBaseServiceImpl.java
  31. 118 0
      service/src/main/java/com/dayou/service/impl/MajorProductionServiceImpl.java
  32. 73 14
      service/src/main/java/com/dayou/service/impl/PersonalFacePriceServiceImpl.java
  33. 23 2
      service/src/main/java/com/dayou/workflow/handler/MajorNodeHandler.java
  34. 19 0
      sql/update_sql.sql

+ 23 - 0
biz-base/src/main/java/com/dayou/controller/MajorProductionController.java

@@ -348,5 +348,28 @@ public class MajorProductionController extends BaseController {
         Page<MajorProductionPerformanceVO> ret = majorProductionService.performanceAllotPage(page,productionPerformance,keyword);
         return RestResponse.data(ret);
     }
+
+
+    /**
+     * 修改产品备案状态至不备案
+     * @param id
+     * @return
+     */
+    @PutMapping("/notRecord/{id}")
+    public RestResponse<Boolean> updateNotRecord(@PathVariable("id") Long id){
+        Boolean ret = majorProductionService.updateNotRecord(id);
+        return RestResponse.data(ret);
+    }
+
+    /**
+     * 修改产品不备案状态至备案
+     * @param id
+     * @return
+     */
+    @PutMapping("/record/{id}")
+    public RestResponse<Boolean> updateRecord(@PathVariable("id") Long id){
+        Boolean ret = majorProductionService.updateRecord(id);
+        return RestResponse.data(ret);
+    }
 }
 

+ 37 - 0
biz-base/src/main/java/com/dayou/controller/PersonalFacePriceController.java

@@ -2,6 +2,7 @@ package com.dayou.controller;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.dayou.annotation.IgnoreAuth;
 import com.dayou.common.RestResponse;
 import com.dayou.dto.PersonalFacePriceQueryDTO;
 import com.dayou.entity.PersonalFacePrice;
@@ -9,9 +10,15 @@ import com.dayou.service.IPersonalFacePriceService;
 import com.dayou.vo.DayouPersonalPriceVO;
 import com.dayou.vo.ExternalFacePriceVO;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.ClassPathResource;
 import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
 
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
 import java.util.List;
 
 /**
@@ -91,4 +98,34 @@ public class PersonalFacePriceController extends BaseController {
         IPage<PersonalFacePrice> ret = personalFacePriceService.getPage(page,facePrice);
         return RestResponse.success(ret);
     }
+
+    /**
+     * 个贷批量口估模版下载
+     * @param request
+     * @param response
+     */
+    @IgnoreAuth
+    @GetMapping("/download/temp")
+    public void downloadPersonalFacePriceTemp(HttpServletRequest request, HttpServletResponse response){
+        try {
+            XSSFWorkbook workbook = new XSSFWorkbook(new ClassPathResource("xlsx/personal/personal_face_price_batch_temp.xlsx").getInputStream());
+            writeXss2Response(request,response,workbook,"批量询价模版.xlsx");
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * 个贷批量口估上传
+     * @param file
+     * @return
+     */
+    @IgnoreAuth
+    @PostMapping("/upload/temp")
+    public RestResponse<String> uploadPersonalFacePriceTemp(@RequestPart("file") MultipartFile file,HttpServletResponse response) throws IOException {
+        String url = personalFacePriceService.uploadPersonalFacePriceTemp(file);
+        return RestResponse.data(url);
+    }
+
+
 }

BIN
biz-base/src/main/resources/xlsx/personal/personal_face_price_batch_temp.xlsx


+ 2 - 0
common/src/main/java/com/dayou/exception/ErrorCode.java

@@ -91,6 +91,8 @@ public class ErrorCode {
 
     public static final ErrorCode BATCH_COMMIT_ERROR = ErrorCode("10043", "订单号:{0}、产品号:{1}的流程批量提交失败,请检查后重试。");
 
+    public static final ErrorCode IS_RECORD_ERROR = ErrorCode("10044", "已取报告号子号,无法改为不备案。");
+
     private String code;
     private String errorMsg;
 

+ 3 - 3
common/src/main/java/com/dayou/utils/AddressUtil.java

@@ -103,7 +103,7 @@ public class AddressUtil {
                     .append(addressDTO.getRoad()!=null?addressDTO.getRoad():"")
                     .append(addressDTO.getRoadNumber()!=null?addressDTO.getRoadNumber():"").toString();
         }else {
-            ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR,"地址为空");
+//            ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR,"地址为空");
             return null;
         }
 
@@ -127,7 +127,7 @@ public class AddressUtil {
                 return "";
             }
         }else {
-            ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR,"地址为空");
+//            ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR,"地址为空");
             return null;
         }
     }
@@ -151,7 +151,7 @@ public class AddressUtil {
                 }
             }
         } catch (Exception e) {
-            ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR,"口估地址不规范");
+//            ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR,"口估地址不规范");
         }
         return null;
     }

+ 3 - 2
common/src/main/java/com/dayou/utils/ExcelPlusUtil.java

@@ -367,9 +367,10 @@ public class ExcelPlusUtil<T> {
             double sheetNo = Math.ceil(list.size() / sheetSize);
             beforeExport(sheetNo);
             String filename = encodingFilename(sheetName);
-            out = new FileOutputStream(getAbsoluteFile(filename));
+            String absoluteFile = getAbsoluteFile(filename);
+            out = new FileOutputStream(absoluteFile);
             wb.write(out);
-            return filename;
+            return absoluteFile;
         } catch (Exception e) {
             log.error("导出Excel异常{}", e.getMessage());
             throw new RuntimeException("导出Excel失败,请联系网站管理员!");

+ 21 - 0
dao/src/main/java/com/dayou/mapper/BusinessNumberRecycleMapper.java

@@ -0,0 +1,21 @@
+package com.dayou.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.dayou.entity.BusinessNumber;
+import com.dayou.entity.BusinessNumberRecycle;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * <p>
+ * 业务号回收 Mapper 接口
+ * </p>
+ *
+ * @author wucl
+ * @since 2025-07-09
+ */
+public interface BusinessNumberRecycleMapper extends BaseMapper<BusinessNumberRecycle> {
+
+    BusinessNumber takeRecycleNo(@Param("businessType") String businessType, @Param("takeType")String takeType ,@Param("year") Integer year);
+
+    void updateState(@Param("id") Long id);
+}

+ 2 - 1
dao/src/main/java/com/dayou/mapper/ExternalDyDataBaseMapper.java

@@ -3,6 +3,7 @@ package com.dayou.mapper;
 import com.dayou.vo.ExternalPersonalVO;
 import org.apache.ibatis.annotations.Param;
 
+import java.math.BigDecimal;
 import java.util.Date;
 import java.util.List;
 
@@ -12,7 +13,7 @@ public interface ExternalDyDataBaseMapper {
 
     List<ExternalPersonalVO> queryQiYuUpPrice(@Param("communityNames") List<String> communityNames,@Param("startDate")Date startDate);
 
-    List<ExternalPersonalVO> queryLianJiaDealPrice(@Param("communityNames") List<String> communityNames,@Param("startDate")Date startDate);
+    List<ExternalPersonalVO> queryLianJiaDealPrice(@Param("communityNames") List<String> communityNames, @Param("startDate")Date startDate, @Param("acreageMin") BigDecimal acreageMin, @Param("acreageMax")BigDecimal acreageMax);
 
     List<ExternalPersonalVO> queryLianJiaUpPrice(@Param("communityNames") List<String> communityNames,@Param("startDate")Date startDate);
 }

+ 3 - 2
dao/src/main/java/com/dayou/mapper/PersonalFacePriceMapper.java

@@ -7,12 +7,13 @@ import com.dayou.entity.PersonalFacePrice;
 import com.dayou.vo.DayouPersonalPriceVO;
 import org.apache.ibatis.annotations.Param;
 
+import java.math.BigDecimal;
 import java.util.Date;
 import java.util.List;
 
 public interface PersonalFacePriceMapper extends BaseMapper<PersonalFacePrice> {
 
-    List<DayouPersonalPriceVO> queryByFuzzyAddress(@Param("address") String roadNumberAddress, @Param("valueTiming") Date startDate);
+    List<DayouPersonalPriceVO> queryByFuzzyAddress(@Param("address") String roadNumberAddress, @Param("valueTiming") Date startDate, @Param("acreageMin")BigDecimal acreageMin, @Param("acreageMax")BigDecimal acreageMax);
 
     List<String> queryCommunityNameByFuzzyAddress(@Param("address") String address);
 
@@ -20,5 +21,5 @@ public interface PersonalFacePriceMapper extends BaseMapper<PersonalFacePrice> {
 
     IPage<PersonalFacePrice> getPage(Page page, @Param("facePrice") PersonalFacePrice facePrice);
 
-    List<DayouPersonalPriceVO> queryFromFacePriceHis(@Param("address")String address, @Param("valueTiming") Date startDate);
+    List<DayouPersonalPriceVO> queryFromFacePriceHis(@Param("address")String address, @Param("valueTiming") Date startDate, @Param("acreageMin")BigDecimal acreageMin, @Param("acreageMax")BigDecimal acreageMax);
 }

+ 3 - 0
dao/src/main/java/com/dayou/mapper/WorkFlowLogMapper.java

@@ -22,4 +22,7 @@ public interface WorkFlowLogMapper extends CustomBaseMapper<WorkFlowLog> {
                                 @Param("businessMinId") String businessMinId,@Param("businessType") String businessType);
 
     WorkFlowLog getRefuse(@Param("businessId") Long businessId, @Param("businessType") String businessType);
+
+    void updateBusinessMinId(@Param("ids") List<Long> logIds, @Param("minId") String minId);
+
 }

+ 2 - 0
dao/src/main/java/com/dayou/mapper/WorkFlowNodeInstanceMapper.java

@@ -48,4 +48,6 @@ public interface WorkFlowNodeInstanceMapper extends CustomBaseMapper<WorkFlowNod
      * @return Boolean
      */
     Boolean checkHasBusinessHandle(@Param("currentNodeId") Long currentNodeId);
+
+    void updateBusinessMinId(@Param("ids") List<Long> nodeIds, @Param("minId") String minId);
 }

+ 17 - 0
dao/src/main/resources/mapper/BusinessNumberRecycleMapper.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.dayou.mapper.BusinessNumberRecycleMapper">
+
+    <select id="takeRecycleNo" resultType="com.dayou.entity.BusinessNumber">
+        select id,year,recycle_no as next_no,take_type,business_type,month,state
+         from business_number_recycle
+        where business_type = #{businessType} and take_type = #{takeType} and deleted = 0
+            and year = #{year}
+        and state = 0
+        order by created asc limit 1
+    </select>
+
+    <update id="updateState" parameterType="java.lang.Long">
+        update business_number_recycle set state = 1 where id = #{id}
+    </update>
+</mapper>

+ 3 - 0
dao/src/main/resources/mapper/ExternalDyDataBaseMapper.xml

@@ -88,6 +88,9 @@
             houses like concat('%', #{item},'%')
         </foreach>
         )
+        <if test="acreageMin!=null and acreageMax!=null">
+            and buildArea &gt;= #{acreageMin} and buildArea &lt;= #{acreageMax}
+        </if>
         ORDER BY
         dealDate DESC
         limit 10

+ 1 - 1
dao/src/main/resources/mapper/MajorTargetMapper.xml

@@ -49,7 +49,7 @@
     </update>
 
     <select id="getSubReportNo" parameterType="java.lang.Long" resultType="com.dayou.entity.MajorTarget">
-        select statement_no,report_no , letter_no from major_target where major_id = #{businessId} and deleted = 0
+        select id,statement_no,report_no , letter_no from major_target where major_id = #{businessId} and deleted = 0
     </select>
 
     <update id="cleanSubStatementNo" parameterType="java.util.Set">

+ 8 - 1
dao/src/main/resources/mapper/PersonalFacePriceMapper.xml

@@ -18,7 +18,11 @@
                            personal_target
                        WHERE
                            amount is not null and
-                           location LIKE CONCAT('%',#{address},'%') and deleted = 0 ) pt left join
+                           location LIKE CONCAT('%',#{address},'%') and deleted = 0
+                        <if test="acreageMin!=null and acreageMax!=null">
+                            and acreage &gt;= #{acreageMin} and acreage &lt;= #{acreageMax}
+                        </if>
+                       ) pt left join
                       (select JSON_UNQUOTE(JSON_EXTRACT(location,'$.valueA')) as communityName,
                               JSON_UNQUOTE(JSON_EXTRACT(decoration,'$.valueA')) as decoration,
                               target_id as tid
@@ -150,6 +154,9 @@
             face_amount AS amount
         from personal_face_price
         where value_timing &gt;= #{valueTiming} and query_target like concat('%',#{address},'%')
+        <if test="acreageMin!=null and acreageMax!=null">
+            and face_acreage &gt;= #{acreageMin} and face_acreage &lt;= #{acreageMax}
+        </if>
         order by created DESC
             limit 0,10
     </select>

+ 9 - 0
dao/src/main/resources/mapper/WorkFlowLogMapper.xml

@@ -71,4 +71,13 @@
         and wfl.business_type = #{businessType} AND wfl.state = 'REFUSE' order by wfl.created DESC LIMIT 1
     </select>
 
+    <update id="updateBusinessMinId" >
+        update work_flow_log set business_min_id = #{minId}
+        where id in (
+        <foreach collection="ids" item="item" separator="," index="index">
+            #{item}
+        </foreach>
+        )
+    </update>
+
 </mapper>

+ 9 - 0
dao/src/main/resources/mapper/WorkFlowNodeInstanceMapper.xml

@@ -305,4 +305,13 @@
         AND instance.id = #{currentNodeId}
         AND node.code not in ('QUOTATION_FEEDBACK','STATEMENT_FEEDBACK','REPORT_FEEDBACK','LETTER_FEEDBACK')
     </select>
+
+    <update id="updateBusinessMinId" >
+        update work_flow_node_instance set business_min_id = #{minId}
+        where id in (
+            <foreach collection="ids" item="item" separator="," index="index">
+                #{item}
+            </foreach>
+            )
+    </update>
 </mapper>

+ 45 - 0
domain/src/main/java/com/dayou/dto/PersonalFacePriceBatchDTO.java

@@ -0,0 +1,45 @@
+package com.dayou.dto;
+
+import com.dayou.annotation.Excel;
+import com.dayou.annotation.ImportCell;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+
+@Data
+public class PersonalFacePriceBatchDTO {
+
+    /**
+     * 估价对象地址
+     */
+    @ImportCell(notNull = true)
+    @Excel(name = "估价对象地址")
+    private String queryTarget;
+
+    /**
+     * 面积
+     */
+    @ImportCell
+    @Excel(name = "面积(平米)")
+    private BigDecimal acreage;
+
+    /**
+     * 单价
+     */
+    @Excel(name = "单价(元)")
+    private BigDecimal price;
+
+    /**
+     * 总价
+     */
+    @Excel(name = "总价(元)")
+    private BigDecimal amount;
+
+    /**
+     * 价值时点
+     */
+    @Excel(name = "价值时点")
+    private LocalDate valueTiming;
+
+}

+ 17 - 0
domain/src/main/java/com/dayou/dto/PersonalFacePriceQueryDTO.java

@@ -4,6 +4,8 @@ import com.github.liangbaika.validate.annations.AbcValidate;
 import com.github.liangbaika.validate.enums.Check;
 import lombok.Data;
 
+import java.math.BigDecimal;
+
 
 @Data
 public class PersonalFacePriceQueryDTO {
@@ -20,4 +22,19 @@ public class PersonalFacePriceQueryDTO {
     @AbcValidate(required = true,message = "时间范围不能为空" , fun = Check.NotEmpty)
     private String limit;
 
+    /**
+     * 面积区间
+     */
+    private BigDecimal acreageMin;
+
+    /**
+     * 面积区间
+     */
+    private BigDecimal acreageMax;
+
+    /**
+     * 查询面积
+     */
+    private BigDecimal acreage;
+
 }

+ 5 - 0
domain/src/main/java/com/dayou/dto/TakeNumberDTO.java

@@ -57,4 +57,9 @@ public class TakeNumberDTO {
      * 已取的价值意见书号
      */
     private String statementNo;
+
+    /**
+     * 土地报告是否备案
+     */
+    private Boolean isRecord;
 }

+ 56 - 0
domain/src/main/java/com/dayou/entity/BusinessNumberRecycle.java

@@ -0,0 +1,56 @@
+package com.dayou.entity;
+
+import com.dayou.annotation.ExcelSheet;
+import com.dayou.common.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ * 业务号回收
+ * </p>
+ *
+ * @author wucl
+ * @since 2025-07-09
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ExcelSheet(sheetName = "业务号回收")
+public class BusinessNumberRecycle extends BaseEntity implements Serializable {
+
+    private static final long serialVersionUID=1L;
+
+    /**
+     * 取号类型
+     */
+    private String takeType;
+
+    /**
+     * 业务类型
+     */
+    private String businessType;
+
+    /**
+     * 年份
+     */
+    private Integer year;
+
+    /**
+     * 月份
+     */
+    private Integer month;
+
+    /**
+     * 回收的号码
+     */
+    private Integer recycleNo;
+
+    /**
+     * 状态:0未取 1已取
+     */
+    private Boolean state;
+
+
+}

+ 12 - 1
domain/src/main/java/com/dayou/enums/TakeNumberEnum.java

@@ -9,11 +9,22 @@ package com.dayou.enums;
  */
 public enum TakeNumberEnum {
 
+    /**
+     * 土地备案(默认)
+     */
     LAND_NUMBER("土地"),
 
+    /**
+     * 土地不备案
+     */
+    LAND_NO_NUMBER("土地不备案"),
+
     REALTY_NUMBER("房地产"),
 
-    ORDER_NUMBER("订单")
+    ORDER_NUMBER("订单"),
+
+
+
     ;
 
     TakeNumberEnum(String type) {

+ 15 - 0
service/src/main/java/com/dayou/service/IBusinessNumberRecycleService.java

@@ -0,0 +1,15 @@
+package com.dayou.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.dayou.entity.BusinessNumberRecycle;
+
+public interface IBusinessNumberRecycleService extends IService<BusinessNumberRecycle> {
+
+    /**
+     * 大中型报告号回收(已取备案报告号,后不备案)
+     * 限制:未产生报告号子号可回收
+     * @param businessId
+     * @return
+     */
+    Boolean recycleMajorReportNumber(Long businessId);
+}

+ 8 - 0
service/src/main/java/com/dayou/service/IBusinessNumberService.java

@@ -5,6 +5,7 @@ import com.dayou.entity.BusinessNumber;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.dayou.enums.MainBusinessEnum;
 import com.dayou.enums.ProductionEnum;
 import com.dayou.enums.TakeNumberEnum;
 import com.dayou.vo.IdNameVO;
@@ -97,4 +98,11 @@ public interface IBusinessNumberService extends IService<BusinessNumber> {
      * @return
      */
     String takeLetterByOrder(Long businessId,String orderId,TakeNumberEnum takeNumberEnum);
+
+    /**
+     * 从回收池里面取大中型报告号
+     * @return
+     */
+    BusinessNumber takeReportNoFromRecyclePool(MainBusinessEnum businessEnum,TakeNumberEnum takeNumberEnum,Integer year);
+
 }

+ 2 - 1
service/src/main/java/com/dayou/service/IExternalDyDataBaseService.java

@@ -2,6 +2,7 @@ package com.dayou.service;
 
 import com.dayou.vo.ExternalPersonalVO;
 
+import java.math.BigDecimal;
 import java.util.Date;
 import java.util.List;
 
@@ -15,7 +16,7 @@ public interface IExternalDyDataBaseService {
 
     List<ExternalPersonalVO> externalPriceQiYuUp(List<String> communityNames, Date startDate);
 
-    List<ExternalPersonalVO> externalPriceLianJiaDeal(List<String> communityNames, Date startDate);
+    List<ExternalPersonalVO> externalPriceLianJiaDeal(List<String> communityNames, Date startDate, BigDecimal acreageMin, BigDecimal acreageMax);
 
     List<ExternalPersonalVO> externalPriceLianJiaUp(List<String> communityNames, Date startDate);
 

+ 4 - 0
service/src/main/java/com/dayou/service/IMajorProductionService.java

@@ -93,4 +93,8 @@ public interface IMajorProductionService extends IService<MajorProduction> {
     List<MajorProduction> getPendingList(MajorProduction majorProduction);
 
     void updateEvaluateAmountAndCheckState(MajorProduction majorProduction);
+
+    Boolean updateNotRecord(Long id);
+
+    Boolean updateRecord(Long id);
 }

+ 12 - 0
service/src/main/java/com/dayou/service/IPersonalFacePriceService.java

@@ -3,11 +3,14 @@ package com.dayou.service;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.dayou.dto.PersonalFacePriceBatchDTO;
 import com.dayou.dto.PersonalFacePriceQueryDTO;
 import com.dayou.entity.PersonalFacePrice;
 import com.dayou.vo.DayouPersonalPriceVO;
 import com.dayou.vo.ExternalFacePriceVO;
+import org.springframework.web.multipart.MultipartFile;
 
+import java.math.BigDecimal;
 import java.util.List;
 
 public interface IPersonalFacePriceService extends IService<PersonalFacePrice> {
@@ -48,4 +51,13 @@ public interface IPersonalFacePriceService extends IService<PersonalFacePrice> {
     Boolean doFacePrice(PersonalFacePrice facePrice);
 
     IPage<PersonalFacePrice> getPage(Page page, PersonalFacePrice facePrice);
+
+    /**
+     * 查询系统口估价(简单算术平均法)
+     * @param facePriceQuery
+     * @return
+     */
+    BigDecimal querySysFacePrice(PersonalFacePriceQueryDTO facePriceQuery);
+
+    String  uploadPersonalFacePriceTemp(MultipartFile file);
 }

+ 119 - 0
service/src/main/java/com/dayou/service/impl/BusinessNumberRecycleServiceImpl.java

@@ -0,0 +1,119 @@
+package com.dayou.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.dayou.common.BaseEntity;
+import com.dayou.entity.BusinessNumberRecycle;
+import com.dayou.entity.Major;
+import com.dayou.entity.MajorProduction;
+import com.dayou.entity.MajorTarget;
+import com.dayou.enums.MainBusinessEnum;
+import com.dayou.enums.ProductionEnum;
+import com.dayou.enums.TakeNumberEnum;
+import com.dayou.exception.ErrorCode;
+import com.dayou.mapper.BusinessNumberRecycleMapper;
+import com.dayou.service.IBusinessNumberRecycleService;
+import com.dayou.service.IMajorProductionService;
+import com.dayou.service.IMajorService;
+import com.dayou.service.IMajorTargetService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+import static com.dayou.common.Constants.BRI;
+
+@Service
+public class BusinessNumberRecycleServiceImpl extends ServiceImpl<BusinessNumberRecycleMapper, BusinessNumberRecycle> implements IBusinessNumberRecycleService {
+
+    @Autowired
+    private IMajorTargetService majorTargetService;
+
+    @Autowired
+    private IMajorService majorService;
+
+    @Autowired
+    private IMajorProductionService majorProductionService;
+
+
+
+    @Override
+    public Boolean recycleMajorReportNumber(Long businessId) {
+        //校验该订单报告号是否可回收
+        String mainReportNo = checkOrder(businessId);
+        Pattern yearPattern = Pattern.compile("(\\d{4})");
+        Pattern numberPattern = Pattern.compile("(?<=字第)\\d+(?=号)");
+        Integer year = patternNumber(mainReportNo, yearPattern);
+        Integer number = patternNumber(mainReportNo, numberPattern);
+
+        //回收号码
+        BusinessNumberRecycle recycle = new BusinessNumberRecycle();
+        recycle.setYear(year);
+        recycle.setRecycleNo(number);
+        recycle.setBusinessType(MainBusinessEnum.MAJOR_BUSINESS.name());
+        recycle.setTakeType(TakeNumberEnum.LAND_NUMBER.name());
+        return this.save(recycle);
+    }
+
+    private String checkOrder(Long businessId) {
+        Major major = majorService.getOne(new LambdaQueryWrapper<Major>().eq(BaseEntity::getId, businessId)
+                .select(Major::getBusinessObjectType, BaseEntity::getId).eq(BaseEntity::getDeleted,false));
+        if (major == null || !TakeNumberEnum.LAND_NUMBER.getType().equals(major.getBusinessObjectType())) {
+            ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR,"订单类型错误");
+        }
+
+        List<MajorTarget> targets = majorTargetService.list(new LambdaQueryWrapper<MajorTarget>().eq(MajorTarget::getMajorId, businessId).eq(MajorTarget::getTargetType, TakeNumberEnum.LAND_NUMBER.getType())
+                .eq(BaseEntity::getDeleted, false).select(BaseEntity::getId,MajorTarget::getReportNo));
+
+        if (CollectionUtils.isEmpty(targets)){
+            ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR,"报告号不存在");
+        }
+
+        //已取部分子号,其他未取
+        List<MajorTarget> notTakeNumberTargets = targets.stream().filter(x -> x.getReportNo() == null).collect(Collectors.toList());
+        if (CollectionUtils.isNotEmpty(notTakeNumberTargets)){
+            ErrorCode.throwBusinessException(ErrorCode.IS_RECORD_ERROR);
+        }
+
+        //已分开全部取子号
+        Set<String> uniReportNo = targets.stream().map(x -> x.getReportNo()).collect(Collectors.toSet());
+
+        if (CollectionUtils.isEmpty(uniReportNo) || uniReportNo.size()!=1){
+            ErrorCode.throwBusinessException(ErrorCode.IS_RECORD_ERROR);
+        }
+
+        List<MajorProduction> prods = majorProductionService.list(new LambdaQueryWrapper<MajorProduction>().eq(MajorProduction::getMajorId, businessId).eq(MajorProduction::getProduction, ProductionEnum.REPORT.name())
+                .eq(BaseEntity::getDeleted, false));
+
+        if (CollectionUtils.isEmpty(prods) || prods.size()!=1){
+            ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR);
+        }
+
+        String mainReportNo = prods.get(0).getReportNo();
+
+        if (mainReportNo.contains(BRI)){
+            ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR);
+        }
+        return mainReportNo;
+    }
+
+    /**
+     * 解析数字
+     * @param mainReportNo
+     * @param pattern
+     * @return
+     */
+    private Integer patternNumber(String mainReportNo,Pattern pattern){
+        Matcher matcher = pattern.matcher(mainReportNo);
+        if (!matcher.find()){
+            ErrorCode.throwBusinessException(ErrorCode.PARAM_ERROR);
+        }
+        return Integer.valueOf(matcher.group());
+    }
+
+}

+ 44 - 18
service/src/main/java/com/dayou/service/impl/BusinessNumberServiceImpl.java

@@ -8,6 +8,7 @@ import com.dayou.enums.MainBusinessEnum;
 import com.dayou.enums.TakeNumberEnum;
 import com.dayou.exception.ErrorCode;
 import com.dayou.mapper.BusinessNumberMapper;
+import com.dayou.mapper.BusinessNumberRecycleMapper;
 import com.dayou.mapper.MajorProductionMapper;
 import com.dayou.service.IBusinessNumberService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -24,6 +25,7 @@ import java.util.List;
 import static com.dayou.common.Constants.*;
 import static com.dayou.enums.MainBusinessEnum.ALL_BUSINESS;
 import static com.dayou.enums.MainBusinessEnum.ASSET_BUSINESS;
+import static com.dayou.enums.TakeNumberEnum.LAND_NO_NUMBER;
 import static com.dayou.enums.TakeNumberEnum.ORDER_NUMBER;
 
 /**
@@ -43,10 +45,13 @@ public class BusinessNumberServiceImpl extends ServiceImpl<BusinessNumberMapper,
 
     private static DecimalFormat zero2 = new DecimalFormat("00");
     private final MajorProductionMapper majorProductionMapper;
+    private final BusinessNumberRecycleMapper businessNumberRecycleMapper;
 
 
-    public BusinessNumberServiceImpl(MajorProductionMapper majorProductionMapper) {
+
+    public BusinessNumberServiceImpl(MajorProductionMapper majorProductionMapper,BusinessNumberRecycleMapper businessNumberRecycleMapper) {
         this.majorProductionMapper = majorProductionMapper;
+        this.businessNumberRecycleMapper = businessNumberRecycleMapper;
     }
 
     @Override
@@ -54,29 +59,40 @@ public class BusinessNumberServiceImpl extends ServiceImpl<BusinessNumberMapper,
         TakeNumberEnum takeType = taskRecordDTO.getTakeType();
         MainBusinessEnum businessType = taskRecordDTO.getBusinessType();
         Integer year = taskRecordDTO.getYear();
-        int number ;
+        int number;
         BusinessNumber busNumber  = null;
 
-        busNumber = this.getOne(new LambdaQueryWrapper<BusinessNumber>().eq(BusinessNumber::getTakeType, takeType).eq(BusinessNumber::getBusinessType, businessType)
-                .eq(BusinessNumber::getYear, year).eq(BaseEntity::getDeleted, Boolean.FALSE));
-        if (busNumber==null){
-            busNumber = new BusinessNumber();
-            busNumber.setTakeType(takeType.name());
-            busNumber.setBusinessType(businessType.name());
-            busNumber.setYear(year);
-            busNumber.setNextNo(1);
-            this.save(busNumber);
-            number = busNumber.getNextNo();
-        }
-        else {
-            number = busNumber.getNextNo();
-        }
+        //先在回收池里面取
+        busNumber = this.takeReportNoFromRecyclePool(businessType, takeType, year);
 
-        this.update(new LambdaUpdateWrapper<BusinessNumber>().set(BusinessNumber::getNextNo,(number+1)).eq(BaseEntity::getId,busNumber.getId()));
+        if (busNumber == null) {
+
+            busNumber = this.getOne(new LambdaQueryWrapper<BusinessNumber>().eq(BusinessNumber::getTakeType, takeType).eq(BusinessNumber::getBusinessType, businessType)
+                    .eq(BusinessNumber::getYear, year).eq(BaseEntity::getDeleted, Boolean.FALSE));
+            if (busNumber==null){
+                busNumber = new BusinessNumber();
+                busNumber.setTakeType(takeType.name());
+                busNumber.setBusinessType(businessType.name());
+                busNumber.setYear(year);
+                busNumber.setNextNo(1);
+                //不备案从700开始
+                if (LAND_NO_NUMBER.equals(takeType)){
+                    busNumber.setNextNo(700);
+                }
+                this.save(busNumber);
+                number = busNumber.getNextNo();
+            }
+            else {
+                number = busNumber.getNextNo();
+            }
+
+            this.update(new LambdaUpdateWrapper<BusinessNumber>().set(BusinessNumber::getNextNo,(number+1)).eq(BaseEntity::getId,busNumber.getId()));
+        }
+        number = busNumber.getNextNo();
 
         //格式化
         //大中型取土地号
-        if (takeType.equals(TakeNumberEnum.LAND_NUMBER) && businessType.equals(MainBusinessEnum.MAJOR_BUSINESS)){
+        if ((takeType.equals(TakeNumberEnum.LAND_NUMBER) || takeType.equals(TakeNumberEnum.LAND_NO_NUMBER)) && businessType.equals(MainBusinessEnum.MAJOR_BUSINESS)){
             return LAND_NUMBER_FORMAT.replace(YEAR, String.valueOf(year)).replace(NUMBER, zero3.format(number));
         }
         //大中型取房地产号
@@ -221,6 +237,16 @@ public class BusinessNumberServiceImpl extends ServiceImpl<BusinessNumberMapper,
 
     }
 
+    @Override
+    public synchronized BusinessNumber takeReportNoFromRecyclePool(MainBusinessEnum businessEnum, TakeNumberEnum takeNumberEnum,Integer year) {
+        BusinessNumber recycle = businessNumberRecycleMapper.takeRecycleNo(businessEnum.name(), takeNumberEnum.name(),year);
+        if (recycle!=null){
+            businessNumberRecycleMapper.updateState(recycle.getId());
+        }
+        return recycle;
+
+    }
+
     /**
      * 根据主号生成字号
      * @param mainNumber

+ 3 - 2
service/src/main/java/com/dayou/service/impl/ExternalDyDataBaseServiceImpl.java

@@ -7,6 +7,7 @@ import com.dayou.vo.ExternalPersonalVO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.math.BigDecimal;
 import java.util.Date;
 import java.util.List;
 
@@ -30,9 +31,9 @@ public class ExternalDyDataBaseServiceImpl implements IExternalDyDataBaseService
     }
 
     @Override
-    public List<ExternalPersonalVO> externalPriceLianJiaDeal(List<String> communityNames, Date startDate) {
+    public List<ExternalPersonalVO> externalPriceLianJiaDeal(List<String> communityNames, Date startDate, BigDecimal acreageMin,BigDecimal acreageMax) {
         //链家成交
-        return externalDyDataBaseMapper.queryLianJiaDealPrice(communityNames,startDate);
+        return externalDyDataBaseMapper.queryLianJiaDealPrice(communityNames,startDate,acreageMin,acreageMax);
     }
 
     @Override

+ 118 - 0
service/src/main/java/com/dayou/service/impl/MajorProductionServiceImpl.java

@@ -21,6 +21,7 @@ import com.dayou.mapper.*;
 import com.dayou.message.annotation.SendMessage;
 import com.dayou.service.*;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.dayou.service.workflow.IWorkFlowLogService;
 import com.dayou.service.workflow.IWorkFlowNodeInstanceService;
 import com.dayou.utils.LoginContext;
 import com.dayou.vo.*;
@@ -33,6 +34,8 @@ import org.springframework.transaction.annotation.Transactional;
 
 import java.math.BigDecimal;
 import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
 import static com.dayou.common.Constants.*;
@@ -113,7 +116,14 @@ public class MajorProductionServiceImpl extends ServiceImpl<MajorProductionMappe
     @Autowired
     private IFinanceFineRefundService financeFineRefundService;
 
+    @Autowired
+    private IBusinessNumberRecycleService businessNumberRecycleService;
+
+    @Autowired
+    private IBusinessNumberService businessNumberService;
 
+    @Autowired
+    private IWorkFlowLogService workFlowLogService;
 
     @Override
     @SuppressWarnings("unchecked")
@@ -530,6 +540,114 @@ public class MajorProductionServiceImpl extends ServiceImpl<MajorProductionMappe
                 .set(MajorProduction::getThirdCheck,majorProduction.getThirdCheck()).eq(BaseEntity::getId,majorProduction.getId()));
     }
 
+    @Transactional
+    @Override
+    public Boolean updateNotRecord(Long id) {
+        //校验当前产品类型和备案状态
+        MajorProduction production = this.getOne(new LambdaQueryWrapper<MajorProduction>().eq(MajorProduction::getId, id).eq(MajorProduction::getProduction, REPORT.name()).eq(MajorProduction::getIsRecord, true)
+                .select(BaseEntity::getId, MajorProduction::getMajorId, MajorProduction::getReportNo));
+        if (production==null){
+            ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR,"当前产品备案状态是:不备案,无需修改。");
+        }
+
+        //1.回收已取的备案报告号
+        Long majorId = production.getMajorId();
+        businessNumberRecycleService.recycleMajorReportNumber(majorId);
+
+        //  获取老号的年份
+        String oldReportNo = production.getReportNo();
+        Pattern yearPattern = Pattern.compile("(\\d{4})");
+        Matcher matcher = yearPattern.matcher(oldReportNo);
+        if (!matcher.find()){
+            ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR,"报告号错误,请联系管理员。");
+        }
+        String year = matcher.group();
+
+        //2.重新取不备案报告号
+        TakeNumberDTO takeNumberDTO = new TakeNumberDTO();
+        takeNumberDTO.setYear(Integer.valueOf(year));
+        takeNumberDTO.setBusinessType(MainBusinessEnum.MAJOR_BUSINESS);
+        takeNumberDTO.setTakeType(TakeNumberEnum.LAND_NO_NUMBER);
+        String noRecordNo = businessNumberService.takeMainNumber(takeNumberDTO);
+        //3.更新备案号的相关历史记录
+        //3.1 估价对象表
+        majorTargetService.update(new LambdaUpdateWrapper<MajorTarget>().set(MajorTarget::getReportNo,noRecordNo).eq(MajorTarget::getMajorId,majorId));
+        //3.2 实例节点表
+        List<WorkFlowNodeInstance> nodes = workFlowNodeInstanceService.list(new LambdaQueryWrapper<WorkFlowNodeInstance>()
+                .eq(WorkFlowNodeInstance::getBusinessType, MainBusinessEnum.MAJOR_BUSINESS)
+                .eq(WorkFlowNodeInstance::getBusinessId, majorId)
+                .eq(WorkFlowNodeInstance::getBusinessMinId, oldReportNo));
+        List<Long> nodeIds = nodes.stream().map(BaseEntity::getId).collect(Collectors.toList());
+        workFlowNodeInstanceMapper.updateBusinessMinId(nodeIds,noRecordNo);
+        //3.3 节点日志表
+        List<WorkFlowLog> logs = workFlowLogService.list(new LambdaQueryWrapper<WorkFlowLog>()
+                .eq(WorkFlowLog::getBusinessType, MainBusinessEnum.MAJOR_BUSINESS)
+                .eq(WorkFlowLog::getBusinessId, majorId)
+                .eq(WorkFlowLog::getBusinessMinId, oldReportNo));
+        List<Long> logIds = logs.stream().map(BaseEntity::getId).collect(Collectors.toList());
+        workFlowLogMapper.updateBusinessMinId(logIds,noRecordNo);
+        //4.重新生成出入库二维码和产品验证二维码
+        this.update(new LambdaUpdateWrapper<MajorProduction>().set(MajorProduction::getReportNo,noRecordNo)
+                .set(MajorProduction::getQrCode,businessProductionService.doCreateNormalCode(REPORT.name(), noRecordNo))
+                .set(MajorProduction::getValidateCode,businessProductionService.doCreateValidateCode(MainBusinessEnum.MAJOR_BUSINESS, id, noRecordNo))
+                .set(MajorProduction::getIsRecord,false)
+                .eq(BaseEntity::getId,id));
+        return true;
+    }
+
+    @Transactional
+    @Override
+    public Boolean updateRecord(Long id) {
+        //校验当前产品类型和备案状态
+        MajorProduction production = this.getOne(new LambdaQueryWrapper<MajorProduction>().eq(MajorProduction::getId, id).eq(MajorProduction::getProduction, REPORT.name()).eq(MajorProduction::getIsRecord, false)
+                .select(BaseEntity::getId, MajorProduction::getMajorId, MajorProduction::getReportNo));
+        if (production==null){
+            ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR,"当前产品备案状态是:备案,无需修改。");
+        }
+
+        Long majorId = production.getMajorId();
+
+        //  获取老号的年份
+        String oldReportNo = production.getReportNo();
+        Pattern yearPattern = Pattern.compile("(\\d{4})");
+        Matcher matcher = yearPattern.matcher(oldReportNo);
+        if (!matcher.find()){
+            ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR,"报告号错误,请联系管理员。");
+        }
+        String year = matcher.group();
+
+        //2.重新取备案报告号
+        TakeNumberDTO takeNumberDTO = new TakeNumberDTO();
+        takeNumberDTO.setYear(Integer.valueOf(year));
+        takeNumberDTO.setBusinessType(MainBusinessEnum.MAJOR_BUSINESS);
+        takeNumberDTO.setTakeType(TakeNumberEnum.LAND_NUMBER);
+        String recordNo = businessNumberService.takeMainNumber(takeNumberDTO);
+        //3.更新备案号的相关历史记录
+        //3.1 估价对象表
+        majorTargetService.update(new LambdaUpdateWrapper<MajorTarget>().set(MajorTarget::getReportNo,recordNo).eq(MajorTarget::getMajorId,majorId));
+        //3.2 实例节点表
+        List<WorkFlowNodeInstance> nodes = workFlowNodeInstanceService.list(new LambdaQueryWrapper<WorkFlowNodeInstance>()
+                .eq(WorkFlowNodeInstance::getBusinessType, MainBusinessEnum.MAJOR_BUSINESS)
+                .eq(WorkFlowNodeInstance::getBusinessId, majorId)
+                .eq(WorkFlowNodeInstance::getBusinessMinId, oldReportNo));
+        List<Long> nodeIds = nodes.stream().map(BaseEntity::getId).collect(Collectors.toList());
+        workFlowNodeInstanceMapper.updateBusinessMinId(nodeIds,recordNo);
+        //3.3 节点日志表
+        List<WorkFlowLog> logs = workFlowLogService.list(new LambdaQueryWrapper<WorkFlowLog>()
+                .eq(WorkFlowLog::getBusinessType, MainBusinessEnum.MAJOR_BUSINESS)
+                .eq(WorkFlowLog::getBusinessId, majorId)
+                .eq(WorkFlowLog::getBusinessMinId, oldReportNo));
+        List<Long> logIds = logs.stream().map(BaseEntity::getId).collect(Collectors.toList());
+        workFlowLogMapper.updateBusinessMinId(logIds,recordNo);
+        //4.重新生成出入库二维码和产品验证二维码
+        this.update(new LambdaUpdateWrapper<MajorProduction>().set(MajorProduction::getReportNo,recordNo)
+                .set(MajorProduction::getQrCode,businessProductionService.doCreateNormalCode(REPORT.name(), recordNo))
+                .set(MajorProduction::getValidateCode,businessProductionService.doCreateValidateCode(MainBusinessEnum.MAJOR_BUSINESS, id, recordNo))
+                .set(MajorProduction::getIsRecord,true)
+                .eq(BaseEntity::getId,id));
+        return true;
+    }
+
     @Override
     public Page<TaskTodoVO> todoSaveFilePage(Page page, TaskTodoVO todoVO,String keyword) {
         todoVO.setHandlerId(LoginContext.getCurrentUserId());

+ 73 - 14
service/src/main/java/com/dayou/service/impl/PersonalFacePriceServiceImpl.java

@@ -1,28 +1,32 @@
 package com.dayou.service.impl;
 
+import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.dayou.dto.AddressDTO;
+import com.dayou.dto.PersonalFacePriceBatchDTO;
 import com.dayou.dto.PersonalFacePriceQueryDTO;
 import com.dayou.entity.PersonalFacePrice;
+import com.dayou.exception.ErrorCode;
 import com.dayou.mapper.PersonalFacePriceMapper;
 import com.dayou.service.IExternalDyDataBaseService;
 import com.dayou.service.IGlobalConfigService;
 import com.dayou.service.IPersonalFacePriceService;
-import com.dayou.utils.AddressUtil;
-import com.dayou.utils.DateUtils;
-import com.dayou.utils.LoginContext;
+import com.dayou.utils.*;
 import com.dayou.vo.DayouPersonalPriceVO;
 import com.dayou.vo.ExternalFacePriceVO;
 import com.dayou.vo.ExternalPersonalVO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
 
+import java.io.IOException;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
+import java.net.URLEncoder;
 import java.time.LocalDate;
 import java.util.*;
 import java.util.stream.Collectors;
@@ -53,8 +57,8 @@ public class PersonalFacePriceServiceImpl extends ServiceImpl<PersonalFacePriceM
         AddressDTO targetAddress = AddressUtil.parseAddress(location);
         String roadNumberAddress = AddressUtil.getRoadNumberAddress(location);
         if (StrUtil.isNotBlank(roadNumberAddress)) {
-            byRoadNumberResult = personalFacePriceMapper.queryByFuzzyAddress(roadNumberAddress,startDate);
-            facePricesByRoadNumber = personalFacePriceMapper.queryFromFacePriceHis(roadNumberAddress,startDate);
+            byRoadNumberResult = personalFacePriceMapper.queryByFuzzyAddress(roadNumberAddress,startDate,facePriceQuery.getAcreageMin(),facePriceQuery.getAcreageMax());
+            facePricesByRoadNumber = personalFacePriceMapper.queryFromFacePriceHis(roadNumberAddress,startDate,facePriceQuery.getAcreageMin(),facePriceQuery.getAcreageMax());
             facePricesByRoadNumber.stream().forEach(x->x.setMatching("全地址匹配(口估)"));
             byRoadNumberResult.stream().forEach(x->x.setMatching("全地址匹配"));
         }
@@ -64,9 +68,9 @@ public class PersonalFacePriceServiceImpl extends ServiceImpl<PersonalFacePriceM
         List<DayouPersonalPriceVO> facePricesByRoadNameNumber = new ArrayList<>();
         String roadAndRoadNumber = AddressUtil.getRoadAndRoadNumber(location);
         if (StrUtil.isNotBlank(roadAndRoadNumber)){
-            byRoadNameNumberResult = personalFacePriceMapper.queryByFuzzyAddress(roadAndRoadNumber,startDate);
+            byRoadNameNumberResult = personalFacePriceMapper.queryByFuzzyAddress(roadAndRoadNumber,startDate,facePriceQuery.getAcreageMin(),facePriceQuery.getAcreageMax());
             filterByCityAndDistrict(byRoadNameNumberResult,targetAddress);
-            facePricesByRoadNameNumber = personalFacePriceMapper.queryFromFacePriceHis(roadNumberAddress,startDate);
+            facePricesByRoadNameNumber = personalFacePriceMapper.queryFromFacePriceHis(roadNumberAddress,startDate,facePriceQuery.getAcreageMin(),facePriceQuery.getAcreageMax());
             facePricesByRoadNameNumber.stream().forEach(x->x.setMatching("路名路号匹配(口估)"));
             byRoadNameNumberResult.stream().forEach(x->x.setMatching("路名路号匹配"));
         }
@@ -76,8 +80,8 @@ public class PersonalFacePriceServiceImpl extends ServiceImpl<PersonalFacePriceM
         List<DayouPersonalPriceVO> facePriceByCommunity = new ArrayList<>();
         String communityNameFromAddress = AddressUtil.getCommunityNameFromAddress(location);
         if (StrUtil.isNotBlank(communityNameFromAddress)){
-            byCommunityNameResult = personalFacePriceMapper.queryByFuzzyAddress(communityNameFromAddress,startDate);
-            facePriceByCommunity = personalFacePriceMapper.queryFromFacePriceHis(roadNumberAddress,startDate);
+            byCommunityNameResult = personalFacePriceMapper.queryByFuzzyAddress(communityNameFromAddress,startDate,facePriceQuery.getAcreageMin(),facePriceQuery.getAcreageMax());
+            facePriceByCommunity = personalFacePriceMapper.queryFromFacePriceHis(roadNumberAddress,startDate,facePriceQuery.getAcreageMin(),facePriceQuery.getAcreageMax());
             filterByCityAndDistrict(byCommunityNameResult,targetAddress);
             byCommunityNameResult.stream().forEach(x->x.setMatching("楼盘名匹配"));
             facePriceByCommunity.stream().forEach(x->x.setMatching("楼盘名匹配(口估)"));
@@ -135,7 +139,7 @@ public class PersonalFacePriceServiceImpl extends ServiceImpl<PersonalFacePriceM
         }
 
         List<String> communityNames = communityName1.stream().distinct().collect(Collectors.toList());
-        return queryExternalDataByCommunityNames(communityNames,startDate);
+        return queryExternalDataByCommunityNames(communityNames,startDate,facePriceQuery.getAcreageMin(),facePriceQuery.getAcreageMax());
 
     }
 
@@ -144,7 +148,7 @@ public class PersonalFacePriceServiceImpl extends ServiceImpl<PersonalFacePriceM
         Date startDate = DateUtils.facePriceLimitDate(facePriceQuery.getLimit());
         String community = facePriceQuery.getQueryTarget();
         List<DayouPersonalPriceVO> result = personalFacePriceMapper.queryByFuzzyCommunityName(community,startDate);
-        List<DayouPersonalPriceVO> facePrices = personalFacePriceMapper.queryFromFacePriceHis(community, startDate);
+        List<DayouPersonalPriceVO> facePrices = personalFacePriceMapper.queryFromFacePriceHis(community, startDate,facePriceQuery.getAcreageMin(),facePriceQuery.getAcreageMax());
         facePrices.forEach(x->{
             x.setMatching("楼盘名(口估)");
             x.setCommunityName(x.getLocation());
@@ -160,7 +164,7 @@ public class PersonalFacePriceServiceImpl extends ServiceImpl<PersonalFacePriceM
         Date startDate = DateUtils.facePriceLimitDate(facePriceQuery.getLimit());
         String communityName = facePriceQuery.getQueryTarget();
         List<String> communityNames = Collections.singletonList(communityName);
-        return queryExternalDataByCommunityNames(communityNames,startDate);
+        return queryExternalDataByCommunityNames(communityNames,startDate,facePriceQuery.getAcreageMin(),facePriceQuery.getAcreageMax());
     }
 
     @Override
@@ -178,6 +182,61 @@ public class PersonalFacePriceServiceImpl extends ServiceImpl<PersonalFacePriceM
         return result;
     }
 
+    @Override
+    public BigDecimal querySysFacePrice(PersonalFacePriceQueryDTO facePriceQuery) {
+        //定义面积区间跨度
+        BigDecimal diff = new BigDecimal(10);
+        BigDecimal acreage = facePriceQuery.getAcreage();
+        if (acreage != null){
+            facePriceQuery.setAcreageMax(acreage.add(diff));
+            facePriceQuery.setAcreageMin(acreage.subtract(diff));
+        }
+
+        facePriceQuery.setLimit("一年内");
+
+        //获取数据源集合
+        List<DayouPersonalPriceVO> dyPrices = this.personalPriceByLocation(facePriceQuery);
+        ExternalFacePriceVO externalFacePriceVO = this.externalPriceByLocation(facePriceQuery);
+        BigDecimal dealAvgPrice = BigDecimal.ZERO;
+        BigDecimal dyAvgPrice = BigDecimal.ZERO;
+        int i = 0;
+        if (externalFacePriceVO != null){
+            //链家成交均价
+            dealAvgPrice = externalFacePriceVO.getDealPrice();
+            i += 1;
+        }
+
+        if (CollectionUtil.isNotEmpty(dyPrices)){
+            //大友评估均价
+            double reduce = dyPrices.stream().filter(x->x.getPrice()!=null).map(DayouPersonalPriceVO::getPrice).mapToDouble(BigDecimal::doubleValue).reduce(0, Double::sum);
+            dyAvgPrice = BigDecimal.valueOf(reduce).divide(BigDecimal.valueOf(dyPrices.size()==0?1:dyPrices.size()), 0, RoundingMode.HALF_UP);
+            i += 1;
+        }
+
+        //综合均价
+        return i==0?BigDecimal.ZERO:dealAvgPrice.add(dyAvgPrice).divide(new BigDecimal(i), RoundingMode.HALF_UP);
+    }
+
+    @Override
+    public String uploadPersonalFacePriceTemp(MultipartFile file) {
+        try {
+            List<PersonalFacePriceBatchDTO> batchQuery = ExcelUtil.importExcel(PersonalFacePriceBatchDTO.class,file.getInputStream(),1);
+            for (PersonalFacePriceBatchDTO batch : batchQuery) {
+                PersonalFacePriceQueryDTO target = new PersonalFacePriceQueryDTO();
+                BeanUtil.copyProperties(batch, target);
+                batch.setPrice(this.querySysFacePrice(target));
+                batch.setAmount(batch.getPrice().multiply(batch.getAcreage()==null?BigDecimal.ZERO:batch.getAcreage()).setScale(2, RoundingMode.HALF_UP));
+                batch.setValueTiming(LocalDate.now());
+            }
+            ExcelPlusUtil<PersonalFacePriceBatchDTO> util = new ExcelPlusUtil<PersonalFacePriceBatchDTO>(PersonalFacePriceBatchDTO.class);
+            String url = util.exportExcel2File(batchQuery, "批量询价结果");
+            return url;
+        } catch (IOException e) {
+            ErrorCode.throwBusinessException(ErrorCode.DEFAULTERROR);
+        }
+        return null;
+    }
+
 
     /**
      * 移除路名相同,但行政区域不同的元素
@@ -211,10 +270,10 @@ public class PersonalFacePriceServiceImpl extends ServiceImpl<PersonalFacePriceM
      * @param startDate
      * @return
      */
-    private ExternalFacePriceVO queryExternalDataByCommunityNames(List<String> communityNames, Date startDate){
+    private ExternalFacePriceVO queryExternalDataByCommunityNames(List<String> communityNames, Date startDate, BigDecimal acreageMin,BigDecimal acreageMax){
         if (CollectionUtil.isNotEmpty(communityNames)){
             //成交价
-            List<ExternalPersonalVO> lianJiaDeal = externalDyDataBaseService.externalPriceLianJiaDeal(communityNames, startDate);
+            List<ExternalPersonalVO> lianJiaDeal = externalDyDataBaseService.externalPriceLianJiaDeal(communityNames, startDate,acreageMin,acreageMax);
             //List<ExternalPersonalVO> qiYuDeal = externalDyDataBaseService.externalPriceQiYuDeal(communityNames,startDate);
             //挂牌价
             List<ExternalPersonalVO> qiYuUp = externalDyDataBaseService.externalPriceQiYuUp(communityNames, startDate);

+ 23 - 2
service/src/main/java/com/dayou/workflow/handler/MajorNodeHandler.java

@@ -22,6 +22,7 @@ import com.dayou.service.workflow.IWorkFlowNodeInstanceService;
 import com.dayou.service.workflow.IWorkNodeService;
 import com.dayou.service.workflow.IWorkTaskRecordService;
 import com.dayou.workflow.config.WorkNodeProcessable;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
@@ -45,6 +46,7 @@ import static com.dayou.enums.workflow.WorkflowNodeEnum.*;
  * @since: 2023/11/1
  * created with IntelliJ IDEA.
  */
+@Slf4j
 @Component
 public class MajorNodeHandler extends WorkNodeProcessable {
 
@@ -80,9 +82,14 @@ public class MajorNodeHandler extends WorkNodeProcessable {
     private IUserService userService;
 
     @Autowired
+    private IBusinessNumberRecycleService businessNumberRecycleService;
+
+    @Autowired
     private IMajorService majorService;
 
 
+
+
     @Override
     public boolean forward(WorkNodeCommit workNodeCommit) {
         WorkFlowNodeInstance currentInstanceNode = workFlowNodeInstanceMapper.getById(workNodeCommit.getInstanceNodeId());
@@ -173,8 +180,8 @@ public class MajorNodeHandler extends WorkNodeProcessable {
         List<String> checkNodes = Arrays.asList(new String[]{CHECK_STATEMENT.name(), CHECK_REPORT.name(), CHECK_LETTER.name()});
         if (writeNodes.contains(currentNode.getNodeCode()) && commit.getCleanReportNo()!=null && commit.getCleanReportNo()){
             //是否取号?
-            List<MajorTarget> productionNos = majorTargetMapper.getSubReportNo(currentNode.getBusinessId()).stream()
-                    .filter(x->x!=null).collect(Collectors.toList());
+            List<MajorTarget> targets = majorTargetMapper.getSubReportNo(currentNode.getBusinessId());
+            List<MajorTarget> productionNos = targets.stream().filter(x->x!=null).collect(Collectors.toList());
 
             if (currentNode.getNodeCode().equals(WRITE_STATEMENT.name())){
                 Set<String> statementNos = productionNos.stream().filter(x->StrUtil.isNotBlank(x.getStatementNo()))
@@ -187,10 +194,24 @@ public class MajorNodeHandler extends WorkNodeProcessable {
                 }
             }
             if (currentNode.getNodeCode().equals(WRITE_REPORT.name())){
+                Major major = majorService.getOne(new LambdaQueryWrapper<Major>().eq(BaseEntity::getId, currentNode.getBusinessId()).select(BaseEntity::getId, Major::getBusinessObjectType).eq(BaseEntity::getDeleted, false));
+
+                Set<String> uniqueReport = targets.stream().map(MajorTarget::getReportNo).collect(Collectors.toSet());
                 Set<String> reportNos = productionNos.stream().filter(x->StrUtil.isNotBlank(x.getReportNo()))
                         .map(MajorTarget::getReportNo).collect(Collectors.toSet());
+
+                if (uniqueReport.size()>1 && StrUtil.equals("土地",major.getBusinessObjectType())){
+                    ErrorCode.throwBusinessException(ErrorCode.CUSTOM_ERROR,"已取备案类型的土地报告号,不能退回。");
+                }
+
                 if (CollectionUtil.isNotEmpty(reportNos)){
                     checkRealAmount(reportNos);
+
+                    if (StrUtil.equals("土地",major.getBusinessObjectType())){
+                        //如果是备案的土地号号码需要回收
+                        businessNumberRecycleService.recycleMajorReportNumber(currentNode.getBusinessId());
+                    }
+
                     majorTargetMapper.cleanSubReportNo(reportNos);
                     majorProductionMapper.delete(new LambdaQueryWrapper<MajorProduction>()
                             .in(MajorProduction::getReportNo,reportNos));

+ 19 - 0
sql/update_sql.sql

@@ -957,3 +957,22 @@ CREATE TABLE `major_appraiser_unit`  (
 ALTER TABLE major ADD COLUMN evaluate_unit decimal ( 8,1 ) COMMENT '评估部计件数';
 ALTER TABLE major_target ADD COLUMN scene_image varchar (255) COMMENT '现场照片';
 ALTER TABLE major_target ADD COLUMN city_array varchar (255) COMMENT '省市县';
+
+/**
+  日期:2025-07-10
+  修改人:wucl
+  更新到test-env
+ */
+CREATE TABLE `business_number_recycle`  (
+                                                  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
+                                                  `take_type` varchar(32) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci NOT NULL COMMENT '取号类型',
+                                                  `business_type` varchar(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci NOT NULL COMMENT '业务类型',
+                                                  `year` int NOT NULL COMMENT '年份',
+                                                  `month` int NULL DEFAULT NULL COMMENT '月份',
+                                                  `recycle_no` int NOT NULL COMMENT '回收的号码',
+                                                  `state` bit(1) NOT NULL DEFAULT b'0' COMMENT '状态(已取,未取)',
+                                                  `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '逻辑删除标识:1:删除 0:未删除',
+                                                  `created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+                                                  `modified` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '修改时间',
+                                                  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb3 COLLATE = utf8mb3_unicode_ci COMMENT = '业务号回收' ROW_FORMAT = Dynamic;