Procházet zdrojové kódy

添加预计算接口

ximinghao před 4 měsíci
rodič
revize
4f1fb502d1

+ 111 - 73
src/main/java/com/skyversation/xjcy/counter/DataPreCounter.java

@@ -2,7 +2,6 @@ package com.skyversation.xjcy.counter;
 
 import com.alibaba.fastjson.JSONObject;
 import lombok.AllArgsConstructor;
-import lombok.Getter;
 
 import java.math.BigDecimal;
 import java.time.Instant;
@@ -15,14 +14,18 @@ import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 public class DataPreCounter {
+
+    public static final Object LOCK = new Object();
+
     /**
      * 注意输入的数据有副作用
      * @param allPark 所有参与的park数据,为避免数据不完整,请提供整个产业园的数据
      * @param allLease 所有参与的租赁,提供所有涉及的房间的所有数据即可,如果数据出现房间级的不完整,就会导致结果有误
      */
-    public DataPreCounter(List<JSONObject> allPark, List<JSONObject> allLease) {
-        this.parkNeedUpload = new HashSet<>();
-        this.leaseNeedUpload = new HashSet<>();
+    public DataPreCounter(List<JSONObject> allPark, List<JSONObject> allLease, LocalDate now) {
+        this.now = now;
+        this.parkNeedUploadId = new HashSet<>();
+        this.leaseNeedUploadId = new HashSet<>();
         this.allPark = allPark;
         this.allLease = allLease;
         allLy = new ArrayList<>();
@@ -50,6 +53,19 @@ public class DataPreCounter {
         });
     }
 
+    public Set<JSONObject> getRoomsWithCode(Collection<String> roomCodes){
+        return allRoom.stream()
+                .filter(v->roomCodes.contains(v.getString(String.valueOf(ParkKey.c_park_code))))
+                .collect(Collectors.toSet());
+    }
+
+    public List<JSONObject> getParkNeedUpload() {
+        return allPark.stream().filter(v->parkNeedUploadId.contains(v.getString("id"))).collect(Collectors.toList());
+    }
+
+    public List<JSONObject> getLeaseNeedUpload() {
+        return allLease.stream().filter(v->leaseNeedUploadId.contains(v.getString("id"))).collect(Collectors.toList());
+    }
     private enum LeaseKey {
         c_room_code, c_enterprise_code, c_start_date, c_end_date, c_lease_purpose, c_is_latest_lease, c_lease_status, update_time, c_enterprise_name
     }
@@ -102,10 +118,8 @@ public class DataPreCounter {
 
     }
 
-    @Getter
-    private final Set<JSONObject> parkNeedUpload;
-    @Getter
-    private final Set<JSONObject> leaseNeedUpload;
+    private final Set<String> parkNeedUploadId;
+    private final Set<String> leaseNeedUploadId;
     private final List<JSONObject> allPark;
     private final List<JSONObject> allLy;
     private final List<JSONObject> allLd;
@@ -113,29 +127,33 @@ public class DataPreCounter {
     private final List<JSONObject> allRoom;
     private final List<JSONObject> allLease;
 
-    private final LocalDateTime now = LocalDateTime.now();
+
+
+    private final LocalDate now ;
 
     /**
      * 运行预统计,有副作用,注意只能运行提供了租赁数据的房间,你可以从parkNeedUpload和leaseNeedUpload中获取所有更新过的数据
      * @param roomRange 统计的范围
      */
     public void run(Collection<JSONObject> roomRange){
-        if (roomRange==null) {
-            roomRange = allRoom;
+        synchronized (LOCK) {
+            if (roomRange==null) {
+                roomRange = allRoom;
+            }
+            //更新并检查所有需更新房间
+            List<JSONObject> updatedRooms = roomRange.stream()
+                    .filter(this::countRoom).collect(Collectors.toList());
+            //按层级统计面积
+            //楼层
+            List<JSONObject> fatherLcs = findFathers(updatedRooms,allLc);
+            //楼栋
+            List<JSONObject> fatherLds = findFathers(fatherLcs,allLd);
+            //楼宇/产业园
+            List<JSONObject> fatherLys = findFathers(fatherLds,allLy);
+            fatherLds.forEach(this::countParkByChild);
+            fatherLcs.forEach(this::countParkByChild);
+            fatherLys.forEach(this::countParkByChild);
         }
-        //更新并检查所有需更新房间
-        List<JSONObject> updatedRooms = roomRange.stream()
-                .filter(this::countRoom).collect(Collectors.toList());
-        //按层级统计面积
-        //楼层
-        Set<JSONObject> fatherLcs = findFathers(updatedRooms,allLc);
-        fatherLcs.forEach(this::countParkByChild);
-        //楼栋
-        Set<JSONObject> fatherLds = findFathers(fatherLcs,allLd);
-        fatherLds.forEach(this::countParkByChild);
-        //楼宇/产业园
-        Set<JSONObject> fatherLys = findFathers(fatherLds,allLy);
-        fatherLys.forEach(this::countParkByChild);
 
     }
     /**
@@ -145,13 +163,13 @@ public class DataPreCounter {
         run(allRoom);
     }
 
-    private Set<JSONObject> findFathers(Collection<JSONObject> children,List<JSONObject> fatherRange) {
+    private List<JSONObject> findFathers(Collection<JSONObject> children,List<JSONObject> fatherRange) {
         Set<String> fatherCode= children.stream()
                 .map(v->v.getString(String.valueOf(ParkKey.c_parent_code)))
                 .collect(Collectors.toSet());
         return fatherRange.stream()
                 .filter(v->fatherCode.contains(v.getString(String.valueOf(ParkKey.c_park_code))))
-                .collect(Collectors.toSet());
+                .collect(Collectors.toList());
     }
     /**
      * 预计算单房间与相关租赁,会修改输入值,会自动统计变动对象
@@ -173,53 +191,56 @@ public class DataPreCounter {
         boolean shouldLeaseUpdateFlag = shouldLeaseUpdate(oldWorkingLeases, newWorkingLease);
 
         if (shouldLeaseUpdateFlag) {
-
             //更新lease last指示数的状态
             updateLeaseLast(newWorkingLease, oldWorkingLeases);
+        }
 
-            //更新房间状态
-            updateRoomLease(room, newWorkingLease);
-
+        //评估房间是否需要更新
+        boolean shouldRoomUpdateFlag = shouldRoomUpdate(room,newWorkingLease);
+        if(shouldRoomUpdateFlag){
+            updateRoomLease(room,newWorkingLease);
             return true;
         }
+
         return false;
     }
 
+
     private void updateRoomLease(JSONObject room, JSONObject lease) {
-        if (lease == null) {
+        if (lease == null||!checkLeaseWorking(lease)) {
             //绑定企业信息
             updateStringValue(room,
                     String.valueOf(ParkKey.c_zlqymc),
                     null,
-                    parkNeedUpload);
+                    parkNeedUploadId);
             updateStringValue(room,
                     String.valueOf(ParkKey.c_zlqydm),
                     null,
-                    parkNeedUpload);
+                    parkNeedUploadId);
             //更新房间状态
-            updateStringValue(room, String.valueOf(ParkKey.c_room_status), "1", parkNeedUpload);
+            updateStringValue(room, String.valueOf(ParkKey.c_room_status), "1", parkNeedUploadId);
             //更新面积数据
             String roomSaleType = room.getString(String.valueOf(ParkKey.c_room_sale_type));
             boolean isForSale = "3".equals(roomSaleType);
             boolean isForRent = "1".equals(roomSaleType);
             Double BuildArea = room.getDouble(String.valueOf(ParkKey.c_building_area));
 
-            updateDoubleValue(room, String.valueOf(ParkKey.c_self_used_area), 0d, parkNeedUpload);
-            updateDoubleValue(room, String.valueOf(ParkKey.c_sellable_area), isForSale ? BuildArea : 0d, parkNeedUpload);
-            updateDoubleValue(room, String.valueOf(ParkKey.c_sold_area), 0d, parkNeedUpload);
-            updateDoubleValue(room, String.valueOf(ParkKey.c_rentable_area), isForRent ? BuildArea : 0d, parkNeedUpload);
-            updateDoubleValue(room, String.valueOf(ParkKey.c_rented_area), 0d, parkNeedUpload);
-            updateDoubleValue(room, String.valueOf(ParkKey.c_vacant_area), isForRent || isForSale ? BuildArea : 0d, parkNeedUpload);
+            updateDoubleValue(room, String.valueOf(ParkKey.c_self_used_area), 0d, parkNeedUploadId);
+            updateDoubleValue(room, String.valueOf(ParkKey.c_sellable_area), isForSale ? BuildArea : 0d, parkNeedUploadId);
+            updateDoubleValue(room, String.valueOf(ParkKey.c_sold_area), 0d, parkNeedUploadId);
+            updateDoubleValue(room, String.valueOf(ParkKey.c_rentable_area), isForRent ? BuildArea : 0d, parkNeedUploadId);
+            updateDoubleValue(room, String.valueOf(ParkKey.c_rented_area), 0d, parkNeedUploadId);
+            updateDoubleValue(room, String.valueOf(ParkKey.c_vacant_area), isForRent || isForSale ? BuildArea : 0d, parkNeedUploadId);
         } else {
             //绑定企业信息
             updateStringValue(room,
                     String.valueOf(ParkKey.c_zlqydm),
                     lease.getString(String.valueOf(LeaseKey.c_enterprise_code)),
-                    parkNeedUpload);
+                    parkNeedUploadId);
             updateStringValue(room,
                     String.valueOf(ParkKey.c_zlqymc),
                     lease.getString(String.valueOf(LeaseKey.c_enterprise_name)),
-                    parkNeedUpload);
+                    parkNeedUploadId);
             //更新房间状态
             String roomSaleType = room.getString(String.valueOf(ParkKey.c_room_sale_type));
             boolean isForSale = "3".equals(roomSaleType);
@@ -236,26 +257,26 @@ public class DataPreCounter {
             } else {
                 state = null; // 如果房间缺失用途数据,则默许缺失蔓延到状态数据
             }
-            updateStringValue(room, String.valueOf(ParkKey.c_room_status), state, parkNeedUpload);
+            updateStringValue(room, String.valueOf(ParkKey.c_room_status), state, parkNeedUploadId);
 
             //更新面积数据
 
             Double BuildArea = room.getDouble(String.valueOf(ParkKey.c_building_area));
 
-            updateDoubleValue(room, String.valueOf(ParkKey.c_self_used_area), isForSelfUsed ? BuildArea : 0d, parkNeedUpload);
-            updateDoubleValue(room, String.valueOf(ParkKey.c_sellable_area), 0d, parkNeedUpload);
-            updateDoubleValue(room, String.valueOf(ParkKey.c_sold_area), isForSale ? BuildArea : 0d, parkNeedUpload);
-            updateDoubleValue(room, String.valueOf(ParkKey.c_rentable_area), 0d, parkNeedUpload);
-            updateDoubleValue(room, String.valueOf(ParkKey.c_rented_area), isForRent ? BuildArea : 0d, parkNeedUpload);
-            updateDoubleValue(room, String.valueOf(ParkKey.c_vacant_area), 0d, parkNeedUpload);
+            updateDoubleValue(room, String.valueOf(ParkKey.c_self_used_area), isForSelfUsed ? BuildArea : 0d, parkNeedUploadId);
+            updateDoubleValue(room, String.valueOf(ParkKey.c_sellable_area), 0d, parkNeedUploadId);
+            updateDoubleValue(room, String.valueOf(ParkKey.c_sold_area), isForSale ? BuildArea : 0d, parkNeedUploadId);
+            updateDoubleValue(room, String.valueOf(ParkKey.c_rentable_area), 0d, parkNeedUploadId);
+            updateDoubleValue(room, String.valueOf(ParkKey.c_rented_area), isForRent ? BuildArea : 0d, parkNeedUploadId);
+            updateDoubleValue(room, String.valueOf(ParkKey.c_vacant_area), 0d, parkNeedUploadId);
         }
 
     }
 
     private void updateLeaseLast(JSONObject newWorkingLease, List<JSONObject> oldWorkingLeases) {
         oldWorkingLeases.forEach(v -> updateStringValue(v, String.valueOf(LeaseKey.c_is_latest_lease),
-                "1", leaseNeedUpload));
-        updateStringValue(newWorkingLease, String.valueOf(LeaseKey.c_is_latest_lease), "2", leaseNeedUpload);
+                "1", leaseNeedUploadId));
+        updateStringValue(newWorkingLease, String.valueOf(LeaseKey.c_is_latest_lease), "2", leaseNeedUploadId);
     }
 
     private boolean shouldLeaseUpdate(List<JSONObject> allLastWorkingLease, JSONObject workingLease) {
@@ -267,22 +288,30 @@ public class DataPreCounter {
             if (!allLastWorkingLease.isEmpty()) {
                 lastWorkingLease = allLastWorkingLease.get(0);
             }
-            //新旧执行中lease相同
+            //新旧执行中lease相同
             return workingLease != lastWorkingLease;
         }
     }
+    private boolean shouldRoomUpdate(JSONObject room, JSONObject lease) {
+        //检查企业数据
+        boolean isEnterpriseDataEqual = compareRoomAndLeaseByKey(room, lease,ParkKey.c_zlqydm,LeaseKey.c_enterprise_code);
+        isEnterpriseDataEqual = isEnterpriseDataEqual && compareRoomAndLeaseByKey(room, lease,ParkKey.c_zlqymc,LeaseKey.c_enterprise_name);
+
+        //检查房间状态与lease匹配性
+        boolean roomUsing = !"1".equals(room.getString(String.valueOf(ParkKey.c_room_status)));
+        boolean leaseWorking = checkLeaseWorking(lease);
+        boolean isWorkingDataEqual = roomUsing == leaseWorking;
+        return !(isEnterpriseDataEqual && isWorkingDataEqual);
+    }
+
+    private static boolean compareRoomAndLeaseByKey(JSONObject room, JSONObject lease,ParkKey roomKey,LeaseKey leaseKey) {
+        return Objects.equals(room.getString(String.valueOf(roomKey)), lease.getString(String.valueOf(leaseKey)));
+    }
 
     private JSONObject getWorkingLease(Supplier<Stream<JSONObject>> involveLease) {
         JSONObject workingLease = involveLease.get()
                 .sorted(Comparator.comparingLong((JSONObject v) -> v.getLong(String.valueOf(LeaseKey.update_time))).reversed())
-                .filter(v -> {
-                    LocalDate startTime = getLeaseStartTime(v);
-                    LocalDate endTime = getLeaseEndTime(v);
-                    if (startTime == null || endTime == null) {
-                        return false;
-                    }
-                    return !startTime.isAfter(now.toLocalDate()) && !endTime.isBefore(now.toLocalDate());
-                })
+                .filter(this::checkLeaseWorking)
                 .findFirst().orElse(null);
         if (workingLease == null) {
             workingLease = involveLease.get()
@@ -291,7 +320,7 @@ public class DataPreCounter {
                         if (startTime == null) {
                             return false;
                         }
-                        return startTime.isAfter(now.toLocalDate());
+                        return startTime.isAfter(now);
                     }).min(Comparator.comparingLong(v -> v.getLong(String.valueOf(LeaseKey.c_start_date)))).orElse(null);
         }
         if (workingLease == null) {
@@ -301,13 +330,22 @@ public class DataPreCounter {
                         if (endTime == null) {
                             return false;
                         }
-                        return endTime.isBefore(now.toLocalDate());
+                        return endTime.isBefore(now);
                     })
                     .max(Comparator.comparingLong(v -> v.getLong(String.valueOf(LeaseKey.c_end_date)))).orElse(null);
         }
         return workingLease;
     }
 
+    private boolean checkLeaseWorking(JSONObject Lease) {
+        LocalDate startTime = getLeaseStartTime(Lease);
+        LocalDate endTime = getLeaseEndTime(Lease);
+        if (startTime == null || endTime == null) {
+            return false;
+        }
+        return !startTime.isAfter(now) && !endTime.isBefore(now);
+    }
+
     /**
      * 根据父子关系统计面积等等数据,使用时从下到上,一层层处理
      *
@@ -341,13 +379,13 @@ public class DataPreCounter {
                 .map(parkDataCount::new)
                 .reduce(new parkDataCount(), parkDataCount::add, parkDataCount::add);
 
-        updateDoubleValue(father, String.valueOf(ParkKey.c_building_area), countResult.buildArea.doubleValue(), parkNeedUpload);
-        updateDoubleValue(father, String.valueOf(ParkKey.c_sellable_area), countResult.sellableArea.doubleValue(), parkNeedUpload);
-        updateDoubleValue(father, String.valueOf(ParkKey.c_sold_area), countResult.soldArea.doubleValue(), parkNeedUpload);
-        updateDoubleValue(father, String.valueOf(ParkKey.c_rentable_area), countResult.rentableArea.doubleValue(), parkNeedUpload);
-        updateDoubleValue(father, String.valueOf(ParkKey.c_rented_area), countResult.rentedArea.doubleValue(), parkNeedUpload);
-        updateDoubleValue(father, String.valueOf(ParkKey.c_self_used_area), countResult.selfUseArea.doubleValue(), parkNeedUpload);
-        updateDoubleValue(father, String.valueOf(ParkKey.c_vacant_area), countResult.vacantArea.doubleValue(), parkNeedUpload);
+        updateDoubleValue(father, String.valueOf(ParkKey.c_building_area), countResult.buildArea.doubleValue(), parkNeedUploadId);
+        updateDoubleValue(father, String.valueOf(ParkKey.c_sellable_area), countResult.sellableArea.doubleValue(), parkNeedUploadId);
+        updateDoubleValue(father, String.valueOf(ParkKey.c_sold_area), countResult.soldArea.doubleValue(), parkNeedUploadId);
+        updateDoubleValue(father, String.valueOf(ParkKey.c_rentable_area), countResult.rentableArea.doubleValue(), parkNeedUploadId);
+        updateDoubleValue(father, String.valueOf(ParkKey.c_rented_area), countResult.rentedArea.doubleValue(), parkNeedUploadId);
+        updateDoubleValue(father, String.valueOf(ParkKey.c_self_used_area), countResult.selfUseArea.doubleValue(), parkNeedUploadId);
+        updateDoubleValue(father, String.valueOf(ParkKey.c_vacant_area), countResult.vacantArea.doubleValue(), parkNeedUploadId);
     }
 
     private static BigDecimal nullToZero(BigDecimal v) {
@@ -374,19 +412,19 @@ public class DataPreCounter {
         return getKeyAndPackToTime(lease, String.valueOf(LeaseKey.c_end_date));
     }
 
-    private void updateStringValue(JSONObject obj, String key, String value, Set<JSONObject> uploadSet) {
+    private void updateStringValue(JSONObject obj, String key, String value, Set<String> uploadList) {
         String oldValue = obj.getString(key);
         if (!oldValue.equals(value)) {
             obj.put(key, value);
-            uploadSet.add(obj);
+            uploadList.add(obj.getString("id"));
         }
     }
 
-    private void updateDoubleValue(JSONObject obj, String key, Double value, Set<JSONObject> uploadSet) {
+    private void updateDoubleValue(JSONObject obj, String key, Double value, Set<String> uploadList) {
         Double oldValue = obj.getDouble(key);
         if (!oldValue.equals(value)) {
             obj.put(key, value);
-            uploadSet.add(obj);
+            uploadList.add(obj.getString("id"));
         }
     }
 }

+ 10 - 5
src/main/java/com/skyversation/xjcy/dms/DMSService.java

@@ -6,13 +6,11 @@ import com.alibaba.fastjson.JSONObject;
 import com.skyversation.xjcy.bean.*;
 import com.skyversation.xjcy.util.HttpUtil;
 import org.springframework.beans.factory.annotation.Value;
-import org.springframework.core.io.FileSystemResource;
 import org.springframework.core.io.Resource;
 import org.springframework.stereotype.Service;
 import org.springframework.util.LinkedMultiValueMap;
 import org.springframework.util.MultiValueMap;
 
-import java.io.File;
 import java.time.LocalDate;
 import java.util.*;
 import java.util.stream.Collectors;
@@ -54,6 +52,9 @@ public class DMSService {
     }
 
     public String updateToDms(Collection<JSONObject> objs,String token,DMSColumn column) {
+        if (objs == null || objs.isEmpty()) {
+            return null;
+        }
         MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
         params.add("modelId",column.getModelId());
         params.add("json",JSON.toJSONString(objs));
@@ -148,9 +149,13 @@ public class DMSService {
 
     //下面几个接口是重计算用的,有重新插入的需求,不能放进queryEnum,不能领域化
     public List<JSONObject> getAllParkByLy(String lyCode,String token) {
-        DMSRequest request = new DMSRequest();
-        request.addWhere("parent_cyy_code", "1", lyCode);
-        return queryDmsList(request, token, DMSColumn.INDUSTRIAL_PARK.getId());
+        DMSRequest requestChildren = new DMSRequest();
+        requestChildren.addWhere("parent_cyy_code", "1", lyCode);
+        List<JSONObject> result = queryDmsList(requestChildren, token, DMSColumn.INDUSTRIAL_PARK.getId());
+        DMSRequest requestFarther = new DMSRequest();
+        requestFarther.addWhere("c_park_code", "1", lyCode);
+        result.addAll( queryDmsList(requestFarther, token, DMSColumn.INDUSTRIAL_PARK.getId()));
+        return result;
     }
 
     public List<JSONObject> getAllPark(String token) {

+ 38 - 0
src/main/java/com/skyversation/xjcy/service/DataPreCountService.java

@@ -0,0 +1,38 @@
+package com.skyversation.xjcy.service;
+
+import com.alibaba.fastjson.JSONObject;
+import com.skyversation.xjcy.counter.DataPreCounter;
+import com.skyversation.xjcy.dms.DMSColumn;
+import com.skyversation.xjcy.dms.DMSService;
+import com.skyversation.xjcy.oauth.LoginService;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 对数据进行预统计的服务,统计的结果直接写入数据库
+ */
+@Service
+public class DataPreCountService {
+    @Resource
+    DMSService dmsService;
+
+    public void updateLimitInRooms(String LyCode, Collection<String> roomCodes,String token){
+        List<JSONObject> allParkByLy = dmsService.getAllParkByLy(LyCode, token);
+        List<JSONObject> allLeaseByRooms = dmsService.getAllLeaseByRooms(new HashSet<>(roomCodes), token);
+
+        LocalDate now = LocalDate.now();
+
+        DataPreCounter dataPreCounter = new DataPreCounter(allParkByLy,allLeaseByRooms, now);
+        dataPreCounter.run(dataPreCounter.getRoomsWithCode(roomCodes));
+        dmsService.updateToDms(dataPreCounter.getParkNeedUpload(),token, DMSColumn.INDUSTRIAL_PARK);
+        dmsService.updateToDms(dataPreCounter.getLeaseNeedUpload(),token,DMSColumn.LEASE_DETAIL);
+    }
+
+}